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