]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/FormGraphics.C
try this for distinguishing inner and outer tabs
[lyx.git] / src / frontends / xforms / FormGraphics.C
1 /* FormGraphics.C
2  * FormGraphics Interface Class Implementation
3  */
4
5 #include <config.h> 
6
7 #ifdef __GNUG__
8 #pragma implementation
9 #endif 
10
11 #include "lyx_gui_misc.h"
12 #include "input_validators.h"
13 #include "FormGraphics.h"
14 #include "form_graphics.h"
15 #include "Dialogs.h"
16 #include "LyXView.h"
17 #include "BufferView.h"
18
19 #include "debug.h" // for lyxerr
20
21 #include "support/lstrings.h"  // for strToDbl & tostr
22 #include "support/FileInfo.h"  // for FileInfo
23 #include "xform_helpers.h"     // for browseFile
24 #include "support/filetools.h" // for AddName
25 #include "insets/insetgraphics.h"
26 #include "insets/insetgraphicsParams.h"
27
28 #include "RadioButtonGroup.h"
29
30 #include "support/LAssert.h"
31
32 using std::endl;
33 using std::make_pair;
34
35 FormGraphics::FormGraphics(LyXView * lv, Dialogs * d)
36         : FormInset(lv, d, _("Graphics"), new NoRepeatedApplyReadOnlyPolicy),
37           dialog_(0), inset_(0),
38           // The buttons c-tor values are the number of buttons we use
39           // This is only to reduce memory waste.
40           widthButtons(5), heightButtons(4), displayButtons(4),
41           last_image_path(".")
42 {
43         // let the dialog be shown
44         // This is a permanent connection so we won't bother
45         // storing a copy because we won't be disconnecting.
46         d->showGraphics.connect(slot(this, &FormGraphics::showDialog));
47 }
48
49
50 FormGraphics::~FormGraphics()
51 {
52         // Remove all associations for the radio buttons
53         widthButtons.reset();
54         heightButtons.reset();
55         displayButtons.reset();
56         
57         // Free the form.
58         // delete dialog_;
59 }
60
61
62 void FormGraphics::build()
63 {
64         dialog_ = build_graphics();
65         Assert(dialog_ != 0);
66         if (!dialog_) {
67                 lyxerr << "ERROR: Failed to create the Graphics Inset dialog." << endl;
68                 return ;
69         }
70
71         // Workaround dumb xforms sizing bug
72         minw_ = form()->w;
73         minh_ = form()->h;
74
75         // This is the place to add settings of the dialog that did not go
76         // to the .fd file.
77
78         // Set the input widgets to issue a callback to input() whenever
79         // they change, so we can verify their content.
80         fl_set_input_return (dialog_->input_width,
81                               FL_RETURN_CHANGED);
82         fl_set_input_return (dialog_->input_height,
83                               FL_RETURN_CHANGED);
84         fl_set_input_return (dialog_->input_filename,
85                               FL_RETURN_CHANGED);
86         //    fl_set_input_return(dialog_->input_rotate_angle,
87         //            FL_RETURN_CHANGED);
88
89         // Set the maximum characters that can be written in the input texts.
90         fl_set_input_maxchars(dialog_->input_width, WIDTH_MAXDIGITS);
91         fl_set_input_maxchars(dialog_->input_height, HEIGHT_MAXDIGITS);
92         fl_set_input_maxchars(dialog_->input_filename, FILENAME_MAXCHARS);
93         fl_set_input_maxchars(dialog_->input_rotate_angle, ROTATE_MAXCHARS);
94
95         // Set input filter on width and height to make them accept only
96         // unsigned numbers.
97         fl_set_input_filter(dialog_->input_width,
98                             fl_unsigned_int_filter);
99         fl_set_input_filter(dialog_->input_height,
100                             fl_unsigned_int_filter);
101
102
103         // Add the widgets of the width radio buttons to their group
104         widthButtons.reset();
105         widthButtons.registerRadioButton(dialog_->radio_width_default,
106                                          InsetGraphicsParams::DEFAULT_SIZE);
107         widthButtons.registerRadioButton(dialog_->radio_width_cm,
108                                          InsetGraphicsParams::CM);
109         widthButtons.registerRadioButton(dialog_->radio_width_inch,
110                                          InsetGraphicsParams::INCH);
111         widthButtons.registerRadioButton(dialog_->radio_width_percent_page,
112                                          InsetGraphicsParams::PERCENT_PAGE);
113         widthButtons.registerRadioButton(dialog_->radio_width_percent_column,
114                                          InsetGraphicsParams::PERCENT_COLUMN);
115
116         // Add the widgets of the height radio buttons to their group
117         heightButtons.reset();
118         heightButtons.registerRadioButton(dialog_->radio_height_default,
119                                           InsetGraphicsParams::DEFAULT_SIZE);
120         heightButtons.registerRadioButton(dialog_->radio_height_cm,
121                                           InsetGraphicsParams::CM);
122         heightButtons.registerRadioButton(dialog_->radio_height_inch,
123                                           InsetGraphicsParams::INCH);
124         heightButtons.registerRadioButton(dialog_->radio_height_percent_page,
125                                           InsetGraphicsParams::PERCENT_PAGE);
126
127         // Add the widgets of the display radio buttons to their group
128         displayButtons.reset();
129         displayButtons.registerRadioButton(dialog_->radio_display_color,
130                                            InsetGraphicsParams::COLOR);
131         displayButtons.registerRadioButton(dialog_->radio_display_grayscale,
132                                            InsetGraphicsParams::GRAYSCALE);
133         displayButtons.registerRadioButton(dialog_->radio_display_monochrome,
134                                            InsetGraphicsParams::MONOCHROME);
135         displayButtons.registerRadioButton(dialog_->radio_no_display,
136                                            InsetGraphicsParams::NONE);
137
138         // Manage the ok, apply, restore and cancel/close buttons
139         bc_.setOK(dialog_->button_ok);
140         bc_.setApply(dialog_->button_apply);
141         bc_.setCancel(dialog_->button_cancel);
142         bc_.setUndoAll(dialog_->button_restore);
143         bc_.refresh();
144
145         bc_.addReadOnly(dialog_->input_filename);
146         bc_.addReadOnly(dialog_->button_browse);
147         bc_.addReadOnly(dialog_->input_width);
148         bc_.addReadOnly(dialog_->input_height);
149         bc_.addReadOnly(dialog_->radio_button_group_width);
150         bc_.addReadOnly(dialog_->radio_button_group_height);
151         bc_.addReadOnly(dialog_->radio_button_group_display);
152         bc_.addReadOnly(dialog_->input_rotate_angle);
153         bc_.addReadOnly(dialog_->check_inline);
154         bc_.addReadOnly(dialog_->input_subcaption);
155         bc_.addReadOnly(dialog_->check_subcaption);
156 }
157
158
159 FL_FORM * FormGraphics::form() const
160 {
161         if (dialog_ ) return dialog_->form;
162         return 0;
163 }
164
165
166 void FormGraphics::disconnect()
167 {
168         inset_ = 0;
169         FormInset::disconnect();
170 }
171
172
173 void FormGraphics::showDialog(InsetGraphics * inset)
174 {
175         // If we are connected to another inset, disconnect.
176         if (inset_)
177                 ih_.disconnect();
178
179         inset_ = inset;
180
181         ih_ = inset_->hideDialog.connect(slot(this, &FormGraphics::hide));
182         show();
183 }
184
185
186 void FormGraphics::apply()
187 {
188         Assert(inset_ != 0);
189
190         // Take all dialog details and insert them to the inset.
191
192         // Create the parameters structure and fill the data from the dialog.
193         InsetGraphicsParams igp;
194
195         igp.filename = fl_get_input(dialog_->input_filename);
196
197         igp.display = static_cast < InsetGraphicsParams::DisplayType >
198                       (displayButtons.getButton());
199
200         igp.widthResize = static_cast < InsetGraphicsParams::Resize >
201                           (widthButtons.getButton());
202         igp.widthSize = strToDbl(fl_get_input(dialog_->input_width));
203
204         igp.heightResize = static_cast < InsetGraphicsParams::Resize >
205                            (heightButtons.getButton());
206         igp.heightSize = strToDbl(fl_get_input(dialog_->input_height));
207
208         igp.rotateAngle = strToInt(fl_get_input(dialog_->input_rotate_angle));
209         if (igp.rotateAngle >= 360)
210                 igp.rotateAngle = igp.rotateAngle % 360;
211         if (igp.rotateAngle <= -360)
212                 igp.rotateAngle = - (( -igp.rotateAngle) % 360);
213
214         igp.subcaption = fl_get_button(dialog_->check_subcaption);
215         igp.subcaptionText = fl_get_input(dialog_->input_subcaption);
216
217         igp.inlineFigure = fl_get_button(dialog_->check_inline);
218
219         igp.testInvariant();
220
221         // Set the parameters in the inset, it also returns true if the new
222         // parameters are different from what was in the inset already.
223         bool changed = inset_->setParams(igp);
224
225         // Tell LyX we've got a change, and mark the document dirty, if it changed.
226         lv_->view()->updateInset(inset_, changed);
227 }
228
229
230 void FormGraphics::update()
231 {
232         Assert(inset_ != 0);
233
234         // Update dialog with details from inset
235         InsetGraphicsParams igp = inset_->getParams();
236
237         // Update the filename input field
238         fl_set_input(dialog_->input_filename,
239                      igp.filename.c_str());
240
241         // Update the display depth radio buttons
242         displayButtons.setButton(igp.display);
243
244         // Update the width radio buttons and input field
245         widthButtons.setButton(igp.widthResize);
246         fl_set_input(dialog_->input_width,
247                      tostr(igp.widthSize).c_str());
248
249         // Update the height radio buttons and input field
250         heightButtons.setButton(igp.heightResize);
251         fl_set_input(dialog_->input_height,
252                      tostr(igp.heightSize).c_str());
253
254         // Update the rotate angle
255         fl_set_input(dialog_->input_rotate_angle,
256                      tostr(igp.rotateAngle).c_str());
257
258         // Update the subcaption check button and input field
259         fl_set_button(dialog_->check_subcaption,
260                       igp.subcaption);
261         fl_set_input(dialog_->input_subcaption,
262                      igp.subcaptionText.c_str());
263
264         // Update the inline figure check button
265         fl_set_button(dialog_->check_inline,
266                       igp.inlineFigure);
267
268         // update the dialog's read only / read-write status
269         bc_.readOnly(lv_->buffer()->isReadonly());
270
271         // Now make sure that the buttons are set correctly.
272         input(0, 0);
273 }
274
275
276 bool FormGraphics::input(FL_OBJECT *, long data )
277 {
278         State cb = static_cast<State>( data );
279
280         bool inputOK = true;
281
282         switch (cb) {
283         case CHECKINPUT:
284                 inputOK = checkInput();
285                 break;
286         case BROWSE:
287                 browse();
288                 break;
289         case ADVANCEDINPUT:
290                 lyxerr << "Advanced Options button depressed, "
291                        << "show advanced options dialog"
292                        << endl;
293                 break;
294         default:
295                 break;
296         }
297         
298         return inputOK;
299 }
300
301
302 bool FormGraphics::checkInput()
303 {
304         // Put verifications that the dialog shows some sane values,
305         // if not disallow clicking on ok/apply.
306         // Possibly use a label in the bottom of the dialog to give the reason.
307
308         // Is all input boxes convey a valid meaning?
309         bool inputOK = true;
310
311         // Things that we check (meaning they are incorrect states):
312         // 1. No filename specified.
313         // 2. Width radio button is not Default and width text is not a number.
314         // 3. Height radio button is not Default and height text is a not a number
315
316         // Note: radio button default means that the user asks for the image
317         // to be included as is with no size change, in this case we don't need
318         // any width or height.
319
320         // We verify now that there is a filename, it exists, it's a file
321         // and it's readable.
322         string filename = fl_get_input(dialog_->input_filename);
323         FileInfo file(filename);
324         if (filename.empty()
325                 || !file.isOK()
326                 || !file.exist()
327                 || !file.isRegular()
328                 || !file.readable()
329            )
330                 inputOK = false;
331
332         // Width radio button not default and no number.
333         if (!fl_get_button(dialog_->radio_width_default)
334                 && strToDbl(fl_get_input(dialog_->input_width)) <= 0.0) {
335
336                 inputOK = false;
337         }
338
339         // Height radio button not default and no number.
340         if (!fl_get_button(dialog_->radio_height_default)
341                 && strToDbl(fl_get_input(dialog_->input_height)) <= 0.0) {
342
343                 inputOK = false;
344         }
345
346         return inputOK;
347 }
348
349
350 // We need these in the file browser.
351 extern string system_lyxdir;
352 extern string user_lyxdir;
353
354 void FormGraphics::browse()
355 {
356         // Get the filename from the dialog
357         string const filename = fl_get_input(dialog_->input_filename);
358
359         string const title = N_("Graphics");
360         string const pattern = "*(ps|png)";
361
362         // Does user clipart directory exist?
363         string clipdir = AddName (user_lyxdir, "clipart");
364         FileInfo fileInfo(clipdir);
365         if (!(fileInfo.isOK() && fileInfo.isDir()))
366                 // No - bail out to system clipart directory
367                 clipdir = AddName (system_lyxdir, "clipart");
368         pair<string, string> dir1(N_("Clipart"), clipdir);
369         
370         // Show the file browser dialog
371         string const new_filename =
372                 browseFile(filename, title, pattern, dir1,
373                            make_pair(string(), string()));
374
375         // Save the filename to the dialog
376         if (new_filename != filename && !new_filename.empty()) {
377                 fl_set_input(dialog_->input_filename, new_filename.c_str());
378                 input(0, 0);
379         }
380 }