]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/FormGraphics.C
Bugfixes: checkboxes to radiobuttons (from J�rgen S) and remove a little
[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                 //use inch as default with US papersizes in lyxrc
266                 if (lyxrc.default_papersize < 3)
267                         pos = 2;
268                 switch (igp.widthResize) {
269                 case InsetGraphicsParams::CM:
270                         pos = 1; break;
271
272                 case InsetGraphicsParams::INCH:
273                         pos = 2; break;
274
275                 case InsetGraphicsParams::PERCENT_PAGE:
276                         pos = 3; break;
277
278                 case InsetGraphicsParams::PERCENT_COLUMN:
279                         pos = 4; break;
280
281                 default:
282                         break;
283                 }
284                 fl_set_choice(dialog_->choice_width_units, pos);
285
286                 number.erase();
287                 if (igp.heightResize != InsetGraphicsParams::DEFAULT_SIZE) {
288                         number = tostr(igp.heightSize);
289                 }
290                 fl_set_input(dialog_->input_height, number.c_str());
291
292                 pos = 1;
293                 //use inch as default with US papersizes in lyxrc
294                 if (lyxrc.default_papersize < 3)
295                         pos = 2;
296                 switch (igp.heightResize) {
297                 case InsetGraphicsParams::CM:
298                         pos = 1; break;
299
300                 case InsetGraphicsParams::INCH:
301                         pos = 2; break;
302
303                 case InsetGraphicsParams::PERCENT_PAGE:
304                         pos = 3; break;
305
306                 default:
307                         break;
308                 }
309                 fl_set_choice(dialog_->choice_height_units, pos);
310         }
311                 
312         // Update the rotate angle
313         fl_set_input(dialog_->input_rotate_angle,
314                      tostr(igp.rotateAngle).c_str());
315
316         // Update the subcaption check button and input field
317         fl_set_button(dialog_->check_subcaption,
318                       igp.subcaption);
319         fl_set_input(dialog_->input_subcaption,
320                      igp.subcaptionText.c_str());
321
322         setEnabled(dialog_->input_subcaption,
323                    fl_get_button(dialog_->check_subcaption));
324 }
325
326
327 ButtonPolicy::SMInput FormGraphics::input(FL_OBJECT * ob, long)
328 {
329         if (ob == dialog_->button_browse) {
330                 // Get the filename from the dialog
331                 string const in_name = fl_get_input(dialog_->input_filename);
332                 string const out_name = controller().Browse(in_name);
333
334                 if (out_name != in_name && !out_name.empty()) {
335                         fl_set_input(dialog_->input_filename, out_name.c_str());
336                 }
337         }
338
339         if (ob == dialog_->input_scale) {
340                 double const scale =
341                         strToDbl(strip(fl_get_input(dialog_->input_scale)));
342                 if (scale > tol) {
343                         fl_set_input(dialog_->input_width, "");
344                         fl_set_choice(dialog_->choice_width_units, 1);
345                         fl_set_input(dialog_->input_height, "");
346                         fl_set_choice(dialog_->choice_height_units, 1);
347                 }
348         }
349
350         if (ob == dialog_->input_width || ob == dialog_->input_height) {
351                 double const width =
352                         strToDbl(strip(fl_get_input(dialog_->input_width)));
353                 double const height =
354                         strToDbl(strip(fl_get_input(dialog_->input_height)));
355
356                 if (width > tol || height > tol) {
357                         fl_set_input(dialog_->input_scale, "");
358                 }
359         }
360
361         if (ob == dialog_->check_subcaption) {
362                 setEnabled(dialog_->input_subcaption,
363                            fl_get_button(dialog_->check_subcaption));
364         }
365
366         return checkInput();
367 }
368
369
370 ButtonPolicy::SMInput FormGraphics::checkInput()
371 {
372         // Put verifications that the dialog shows some sane values,
373         // if not disallow clicking on ok/apply.
374         // Possibly use a label in the bottom of the dialog to give the reason.
375
376         ButtonPolicy::SMInput activate = ButtonPolicy::SMI_VALID;
377
378         // We verify now that there is a filename, it exists, it's a file
379         // and it's readable.
380         string filename = fl_get_input(dialog_->input_filename);
381         FileInfo file(filename);
382         if (filename.empty()
383                 || !file.isOK()
384                 || !file.exist()
385                 || !file.isRegular()
386                 || !file.readable()
387            )
388                 activate = ButtonPolicy::SMI_INVALID;
389
390         return activate;
391 }