]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/FormGraphics.C
J�rgen Spitzm�ller's changes to the graphics dialog.
[lyx.git] / src / frontends / xforms / FormGraphics.C
1 /* This file is part of
2  * ====================================================== 
3  *
4  *           LyX, The Document Processor
5  *
6  *           Copyright 2000-2001 The LyX Team.
7  *
8  * ======================================================
9  *
10  * \file FormGraphics.C
11  * \author Baruch Even, baruch.even@writeme.com
12  */
13
14 #include <config.h> 
15
16 #ifdef __GNUG__
17 #pragma implementation
18 #endif 
19
20 #include "xformsBC.h"
21 #include "ControlGraphics.h"
22 #include "FormGraphics.h"
23 #include "form_graphics.h"
24
25 #include "xforms_helpers.h"
26 #include "input_validators.h"
27 #include "debug.h" // for lyxerr
28 #include "support/lstrings.h"  // for strToDbl & tostr
29 #include "support/FileInfo.h"  // for FileInfo
30 #include "insets/insetgraphicsParams.h"
31 #include "lyxrc.h" // for lyxrc.display_graphics
32
33 using std::endl;
34
35 namespace {
36
37 // Zero test for double precision numbers
38 double const tol = 1.0e-08;
39
40 // The maximum digits for the image scale
41 int const SCALE_MAXDIGITS = 3;
42
43 // The maximum digits for the image width
44 int const WIDTH_MAXDIGITS = 3;
45
46 // The maximum digits for the image height
47 int const HEIGHT_MAXDIGITS = 3;
48
49 // The max characters in the rotation angle (minus sign and 3 digits)
50 int const ROTATE_MAXCHARS = 4;
51
52 // The maximum characters in a filename.
53 int const FILENAME_MAXCHARS = 1024;
54  
55 } // namespace anon
56
57
58 typedef FormCB<ControlGraphics, FormDB<FD_form_graphics> > base_class;
59
60 FormGraphics::FormGraphics(ControlGraphics & c)
61         : base_class(c, _("Graphics"))
62 {}
63
64
65 void FormGraphics::build()
66 {
67         dialog_.reset(build_graphics());
68
69         // This is the place to add settings of the dialog that did not go
70         // to the .fd file.
71
72         // Set the input widgets to issue a callback to input() whenever
73         // they change, so we can verify their content.
74         fl_set_input_return (dialog_->input_filename,     FL_RETURN_CHANGED);
75         fl_set_input_return (dialog_->input_scale,        FL_RETURN_CHANGED);
76         fl_set_input_return (dialog_->input_width,        FL_RETURN_CHANGED);
77         fl_set_input_return (dialog_->input_height,       FL_RETURN_CHANGED);
78         fl_set_input_return (dialog_->input_rotate_angle, FL_RETURN_CHANGED);
79         fl_set_input_return (dialog_->input_subcaption,   FL_RETURN_CHANGED);
80
81         // Set the maximum characters that can be written in the input texts.
82         fl_set_input_maxchars(dialog_->input_scale,        SCALE_MAXDIGITS);
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_scale,  fl_unsigned_float_filter);
91         fl_set_input_filter(dialog_->input_width,  fl_unsigned_float_filter);
92         fl_set_input_filter(dialog_->input_height, fl_unsigned_float_filter);
93
94         // Set input filter on rotate_angle to make it accept only
95         // floating point numbers.
96         fl_set_input_filter(dialog_->input_rotate_angle, fl_float_filter);
97
98         // Create the contents of the choices
99         string const width = " cm | inch | page %% | column %% ";
100         fl_addto_choice(dialog_->choice_width_units, width.c_str());
101
102         string const height = " cm | inch | page %% ";
103         fl_addto_choice(dialog_->choice_height_units, height.c_str());
104
105         // Manage the ok, apply, restore and cancel/close buttons
106         bc().setOK(dialog_->button_ok);
107         bc().setApply(dialog_->button_apply);
108         bc().setCancel(dialog_->button_cancel);
109         bc().setRestore(dialog_->button_restore);
110
111         bc().addReadOnly(dialog_->input_filename);
112         bc().addReadOnly(dialog_->button_browse);
113         bc().addReadOnly(dialog_->check_display);
114         bc().addReadOnly(dialog_->input_scale);
115         bc().addReadOnly(dialog_->input_width);
116         bc().addReadOnly(dialog_->choice_width_units);
117         bc().addReadOnly(dialog_->input_height);
118         bc().addReadOnly(dialog_->choice_height_units);
119         bc().addReadOnly(dialog_->input_rotate_angle);
120         bc().addReadOnly(dialog_->input_subcaption);
121         bc().addReadOnly(dialog_->check_subcaption);
122 }
123
124
125 void FormGraphics::apply()
126 {
127         // Create the parameters structure and fill the data from the dialog.
128         InsetGraphicsParams & igp = controller().params();
129
130         igp.filename = fl_get_input(dialog_->input_filename);
131
132         if (lyxrc.display_graphics == "no") {
133                 igp.display = InsetGraphicsParams::NONE;
134
135         } else {
136                 if (fl_get_button(dialog_->check_display)) {
137                         if (lyxrc.display_graphics == "mono") {
138                                 igp.display = InsetGraphicsParams::MONOCHROME;
139                         } else if (lyxrc.display_graphics == "gray") {
140                                 igp.display = InsetGraphicsParams::GRAYSCALE;
141                         } else if (lyxrc.display_graphics == "color") {
142                                 igp.display = InsetGraphicsParams::COLOR;
143                         }
144                         
145                 } else {
146                         igp.display = InsetGraphicsParams::NONE;
147                 }
148         }
149
150         double const scale =
151                 strToDbl(strip(fl_get_input(dialog_->input_scale)));
152         if (scale < tol) {
153                 double const width =
154                         strToDbl(strip(fl_get_input(dialog_->input_width)));
155
156                 if (width < tol) {
157                         igp.widthResize = InsetGraphicsParams::DEFAULT_SIZE;
158                         igp.widthSize   = 0.0;
159                 } else {
160                         switch (fl_get_choice(dialog_->choice_width_units)) {
161                         case 2:
162                                 igp.widthResize = InsetGraphicsParams::INCH;
163                                 break;
164                         case 3:
165                                 igp.widthResize =
166                                         InsetGraphicsParams::PERCENT_PAGE;
167                                 break;
168                         case 4:
169                                 igp.widthResize =
170                                         InsetGraphicsParams::PERCENT_COLUMN;
171                                 break;
172                         default:
173                                 igp.widthResize = InsetGraphicsParams::CM;
174                                 break;
175                         }
176                         igp.widthSize = width;
177                 }
178                 
179                 double const height =
180                         strToDbl(strip(fl_get_input(dialog_->input_height)));
181                 
182                 if (height < tol) {
183                         igp.heightResize = InsetGraphicsParams::DEFAULT_SIZE;
184                         igp.heightSize   = 0.0;
185                 } else {
186                         switch (fl_get_choice(dialog_->choice_height_units)) {
187                         case 2:
188                                 igp.heightResize = InsetGraphicsParams::INCH;
189                                 break;
190                         case 3:
191                                 igp.heightResize =
192                                         InsetGraphicsParams::PERCENT_PAGE;
193                                 break;
194                         default:
195                                 igp.heightResize = InsetGraphicsParams::CM;
196                                 break;
197                         }
198                         igp.heightSize = height;
199                 }
200                 
201         } else {
202                 igp.widthResize  = InsetGraphicsParams::DEFAULT_SIZE;
203                 igp.widthSize    = 0.0;
204                 igp.heightResize = InsetGraphicsParams::SCALE;
205                 igp.heightSize   = scale;
206         }
207         
208         igp.rotateAngle =
209                 strToDbl(strip(fl_get_input(dialog_->input_rotate_angle)));
210         while (igp.rotateAngle < 0.0 || igp.rotateAngle > 360.0) {
211                 if (igp.rotateAngle < 0.0) {
212                         igp.rotateAngle += 360.0;
213                 } else if (igp.rotateAngle > 360.0) {
214                         igp.rotateAngle -= 360.0;
215                 }
216         }
217
218         igp.subcaption = fl_get_button(dialog_->check_subcaption);
219         igp.subcaptionText = fl_get_input(dialog_->input_subcaption);
220
221         igp.testInvariant();
222 }
223
224
225 void FormGraphics::update()
226 {
227         // Update dialog with details from inset
228         InsetGraphicsParams & igp = controller().params();
229
230         // Update the filename input field
231         fl_set_input(dialog_->input_filename,
232                      igp.filename.c_str());
233
234         // To display or not to display
235         if (lyxrc.display_graphics == "no") {
236                 fl_set_button(dialog_->check_display, 0);
237         } else {
238                 if (igp.display == InsetGraphicsParams::NONE) {
239                         fl_set_button(dialog_->check_display, 0);
240                 } else {
241                         fl_set_button(dialog_->check_display, 1);
242                 }
243         }
244
245         setEnabled(dialog_->check_display, (lyxrc.display_graphics != "no"));
246
247         if (igp.heightResize == InsetGraphicsParams::SCALE) {
248                 string number = tostr(igp.heightSize);
249                 fl_set_input(dialog_->input_scale, number.c_str());
250                 fl_set_input(dialog_->input_width, "");
251                 fl_set_choice(dialog_->choice_width_units, 1);
252                 fl_set_input(dialog_->input_height, "");
253                 fl_set_choice(dialog_->choice_height_units, 1);
254
255         } else {
256                 fl_set_input(dialog_->input_scale, "");
257
258                 string number;
259                 if (igp.widthResize != InsetGraphicsParams::DEFAULT_SIZE) {
260                         number = tostr(igp.widthSize);
261                 }
262                 fl_set_input(dialog_->input_width, number.c_str());
263
264                 int pos = 1;
265                 switch (igp.widthResize) {
266                 case InsetGraphicsParams::INCH:
267                         pos = 2; break;
268
269                 case InsetGraphicsParams::PERCENT_PAGE:
270                         pos = 3; break;
271
272                 case InsetGraphicsParams::PERCENT_COLUMN:
273                         pos = 4; break;
274
275                 default:
276                         break;
277                 }
278                 fl_set_choice(dialog_->choice_width_units, pos);
279
280                 number.erase();
281                 if (igp.heightResize != InsetGraphicsParams::DEFAULT_SIZE) {
282                         number = tostr(igp.heightSize);
283                 }
284                 fl_set_input(dialog_->input_height, number.c_str());
285
286                 pos = 1;
287                 switch (igp.heightResize) {
288                 case InsetGraphicsParams::INCH:
289                         pos = 2; break;
290
291                 case InsetGraphicsParams::PERCENT_PAGE:
292                         pos = 3; break;
293
294                 default:
295                         break;
296                 }
297                 fl_set_choice(dialog_->choice_height_units, pos);
298         }
299                 
300         // Update the rotate angle
301         fl_set_input(dialog_->input_rotate_angle,
302                      tostr(igp.rotateAngle).c_str());
303
304         // Update the subcaption check button and input field
305         fl_set_button(dialog_->check_subcaption,
306                       igp.subcaption);
307         fl_set_input(dialog_->input_subcaption,
308                      igp.subcaptionText.c_str());
309
310         setEnabled(dialog_->input_subcaption,
311                    fl_get_button(dialog_->check_subcaption));
312 }
313
314
315 ButtonPolicy::SMInput FormGraphics::input(FL_OBJECT * ob, long)
316 {
317         if (ob == dialog_->button_browse) {
318                 // Get the filename from the dialog
319                 string const in_name = fl_get_input(dialog_->input_filename);
320                 string const out_name = controller().Browse(in_name);
321
322                 if (out_name != in_name && !out_name.empty()) {
323                         fl_set_input(dialog_->input_filename, out_name.c_str());
324                 }
325         }
326
327         if (ob == dialog_->input_scale) {
328                 double const scale =
329                         strToDbl(strip(fl_get_input(dialog_->input_scale)));
330                 if (scale > tol) {
331                         fl_set_input(dialog_->input_width, "");
332                         fl_set_choice(dialog_->choice_width_units, 1);
333                         fl_set_input(dialog_->input_height, "");
334                         fl_set_choice(dialog_->choice_height_units, 1);
335                 }
336         }
337
338         if (ob == dialog_->input_width || ob == dialog_->input_height) {
339                 double const width =
340                         strToDbl(strip(fl_get_input(dialog_->input_width)));
341                 double const height =
342                         strToDbl(strip(fl_get_input(dialog_->input_height)));
343
344                 if (width > tol || height > tol) {
345                         fl_set_input(dialog_->input_scale, "");
346                 }
347         }
348
349         if (ob == dialog_->check_subcaption) {
350                 setEnabled(dialog_->input_subcaption,
351                            fl_get_button(dialog_->check_subcaption));
352         }
353
354         return checkInput();
355 }
356
357
358 ButtonPolicy::SMInput FormGraphics::checkInput()
359 {
360         // Put verifications that the dialog shows some sane values,
361         // if not disallow clicking on ok/apply.
362         // Possibly use a label in the bottom of the dialog to give the reason.
363
364         ButtonPolicy::SMInput activate = ButtonPolicy::SMI_VALID;
365
366         // We verify now that there is a filename, it exists, it's a file
367         // and it's readable.
368         string filename = fl_get_input(dialog_->input_filename);
369         FileInfo file(filename);
370         if (filename.empty()
371                 || !file.isOK()
372                 || !file.exist()
373                 || !file.isRegular()
374                 || !file.readable()
375            )
376                 activate = ButtonPolicy::SMI_INVALID;
377
378         return activate;
379 }