]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/FormExternal.C
get rid of broken_header.h and some unneeded tests
[lyx.git] / src / frontends / xforms / FormExternal.C
1 /**
2  * \file FormExternal.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Asger Alstrup
7  * \author John Levon
8  * \author Angus Leeming
9  *
10  * Full author contact details are available in file CREDITS.
11  */
12
13 #include <config.h>
14
15 #include "FormExternal.h"
16 #include "forms/form_external.h"
17
18 #include "checkedwidgets.h"
19 #include "input_validators.h"
20 #include "Tooltips.h"
21 #include "xforms_helpers.h"
22 #include "xformsBC.h"
23
24 #include "controllers/ControlExternal.h"
25
26 #include "lengthcommon.h"
27 #include "lyxrc.h"
28
29 #include "insets/ExternalTemplate.h"
30 #include "insets/insetexternal.h"
31
32 #include "support/lstrings.h"
33 #include "support/lyxlib.h"
34 #include "support/tostr.h"
35
36 #include "lyx_forms.h"
37
38 namespace external = lyx::external;
39
40 using std::find;
41 using std::string;
42 using std::vector;
43
44 namespace lyx {
45
46 using support::bformat;
47 using support::float_equal;
48 using support::getStringFromVector;
49 using support::isStrDbl;
50 using support::strToDbl;
51 using support::strToInt;
52 using support::token;
53 using support::trim;
54
55 namespace frontend {
56
57 namespace {
58
59 LyXLength::UNIT defaultUnit()
60 {
61         LyXLength::UNIT default_unit = LyXLength::CM;
62         switch (lyxrc.default_papersize) {
63         case PAPER_USLETTER:
64         case PAPER_LEGALPAPER:
65         case PAPER_EXECUTIVEPAPER:
66                 default_unit = LyXLength::IN;
67                 break;
68         default:
69                 break;
70         }
71         return default_unit;
72 }
73
74
75 void setDisplay(FL_OBJECT * displayCB, FL_OBJECT * showCO, FL_OBJECT * scaleED,
76                 external::DisplayType display, unsigned int scale,
77                 bool read_only)
78 {
79         BOOST_ASSERT(displayCB && displayCB->objclass == FL_CHECKBUTTON);
80         BOOST_ASSERT(showCO && showCO->objclass == FL_CHOICE);
81         BOOST_ASSERT(scaleED && scaleED->objclass == FL_INPUT);
82
83         int item = 1;
84         switch (display) {
85         case external::DefaultDisplay:
86                 item = 1;
87                 break;
88         case external::MonochromeDisplay:
89                 item = 2;
90                 break;
91         case external::GrayscaleDisplay:
92                 item = 3;
93                 break;
94         case external::ColorDisplay:
95                 item = 4;
96                 break;
97         case external::PreviewDisplay:
98                 item = 5;
99                 break;
100         case external::NoDisplay:
101                 item = 1;
102                 break;
103         }
104
105         fl_set_choice(showCO, item);
106
107         bool const no_display = display == external::NoDisplay;
108         setEnabled(showCO, !no_display && !read_only);
109
110         fl_set_button(displayCB, !no_display);
111
112         fl_set_input(scaleED, tostr(scale).c_str());
113         setEnabled(scaleED, !no_display && !read_only);
114 }
115
116
117 void getDisplay(external::DisplayType & display,
118                 unsigned int & scale,
119                 FL_OBJECT * displayCB,
120                 FL_OBJECT * showCO,
121                 FL_OBJECT * scaleED)
122 {
123         BOOST_ASSERT(displayCB && displayCB->objclass == FL_CHECKBUTTON);
124         BOOST_ASSERT(showCO && showCO->objclass == FL_CHOICE);
125         BOOST_ASSERT(scaleED && scaleED->objclass == FL_INPUT);
126
127         switch (fl_get_choice(showCO)) {
128         case 1:
129                 display = external::DefaultDisplay;
130                 break;
131         case 2:
132                 display = external::MonochromeDisplay;
133                 break;
134         case 3:
135                 display = external::GrayscaleDisplay;
136                 break;
137         case 4:
138                 display = external::ColorDisplay;
139                 break;
140         case 5:
141                 display = external::PreviewDisplay;
142                 break;
143         }
144
145         if (!fl_get_button(displayCB))
146                 display = external::NoDisplay;
147
148         scale = strToInt(getString(scaleED));
149 }
150
151
152 void setRotation(FL_OBJECT * angleED, FL_OBJECT * originCO,
153                  external::RotationData const & data)
154 {
155         BOOST_ASSERT(angleED && angleED->objclass == FL_INPUT);
156         BOOST_ASSERT(originCO && originCO->objclass == FL_CHOICE);
157
158         fl_set_choice(originCO, 1 + int(data.origin()));
159         fl_set_input(angleED, tostr(data.angle()).c_str());
160 }
161
162
163 void getRotation(external::RotationData & data,
164                  FL_OBJECT * angleED, FL_OBJECT * originCO)
165 {
166         BOOST_ASSERT(angleED && angleED->objclass == FL_INPUT);
167         BOOST_ASSERT(originCO && originCO->objclass == FL_CHOICE);
168
169         typedef external::RotationData::OriginType OriginType;
170
171         data.origin(static_cast<OriginType>(fl_get_choice(originCO) - 1));
172         data.angle(strToDbl(getString(angleED)));
173 }
174
175
176 void setSize(FL_OBJECT * widthED, FL_OBJECT * widthUnitCO,
177              FL_OBJECT * heightED, FL_OBJECT * heightUnitCO,
178              FL_OBJECT * aspectratioCB,
179              external::ResizeData const & data)
180 {
181         BOOST_ASSERT(widthED && widthED->objclass == FL_INPUT);
182         BOOST_ASSERT(widthUnitCO && widthUnitCO->objclass == FL_CHOICE);
183         BOOST_ASSERT(heightED && heightED->objclass == FL_INPUT);
184         BOOST_ASSERT(heightUnitCO && heightUnitCO->objclass == FL_CHOICE);
185         BOOST_ASSERT(aspectratioCB &&
186                      aspectratioCB->objclass == FL_CHECKBUTTON);
187
188         bool using_scale = data.usingScale();
189         double scale =  data.scale;
190         if (data.no_resize()) {
191                 // Everything is zero, so default to this!
192                 using_scale = true;
193                 scale = 100;
194         }
195
196         if (using_scale) {
197                 fl_set_input(widthED, tostr(scale).c_str());
198                 fl_set_choice(widthUnitCO, 1);
199         } else {
200                 fl_set_input(widthED, tostr(data.width.value()).c_str());
201                 // Because 'Scale' is position 1...
202                 // Note also that width cannot be zero here, so
203                 // we don't need to worry about the default unit.
204                 fl_set_choice(widthUnitCO, data.width.unit() + 2);
205         }
206
207         string const h = data.height.zero() ? string() : data.height.asString();
208         LyXLength::UNIT default_unit = data.width.zero() ?
209                 defaultUnit() : data.width.unit();
210         updateWidgetsFromLengthString(heightED, heightUnitCO,
211                                       h, stringFromUnit(default_unit));
212
213         setEnabled(heightED, !using_scale);
214         setEnabled(heightUnitCO, !using_scale);
215
216         fl_set_button(aspectratioCB, data.keepAspectRatio);
217
218         bool const disable_aspectRatio = using_scale ||
219                 data.width.zero() || data.height.zero();
220         setEnabled(aspectratioCB, !disable_aspectRatio);
221 }
222
223
224 void getSize(external::ResizeData & data,
225              FL_OBJECT * widthED, FL_OBJECT * widthUnitCO,
226              FL_OBJECT * heightED, FL_OBJECT * heightUnitCO,
227              FL_OBJECT * aspectratioCB)
228 {
229         BOOST_ASSERT(widthED && widthED->objclass == FL_INPUT);
230         BOOST_ASSERT(widthUnitCO && widthUnitCO->objclass == FL_CHOICE);
231         BOOST_ASSERT(heightED && heightED->objclass == FL_INPUT);
232         BOOST_ASSERT(heightUnitCO && heightUnitCO->objclass == FL_CHOICE);
233         BOOST_ASSERT(aspectratioCB &&
234                      aspectratioCB->objclass == FL_CHECKBUTTON);
235
236         string const width = getString(widthED);
237
238         if (fl_get_choice(widthUnitCO) > 1) {
239                 // Subtract one, because scale is 1.
240                 int const unit = fl_get_choice(widthUnitCO) - 1;
241
242                 LyXLength w;
243                 if (isValidLength(width, &w))
244                         data.width = w;
245                 else if (isStrDbl(width))
246                         data.width = LyXLength(strToDbl(width),
247                                            static_cast<LyXLength::UNIT>(unit));
248                 else
249                         data.width = LyXLength();
250
251                 data.scale = 0.0;
252
253         } else {
254                 // scaling instead of a width
255                 data.scale = strToDbl(width);
256                 data.width = LyXLength();
257         }
258
259         data.height = LyXLength(getLengthFromWidgets(heightED, heightUnitCO));
260
261         data.keepAspectRatio = fl_get_button(aspectratioCB);
262 }
263
264
265 void setCrop(FL_OBJECT * clipCB,
266              FL_OBJECT * xlED, FL_OBJECT * ybED,
267              FL_OBJECT * xrED, FL_OBJECT * ytED,
268              external::ClipData const & data)
269 {
270         BOOST_ASSERT(clipCB && clipCB->objclass == FL_CHECKBUTTON);
271         BOOST_ASSERT(xlED && xlED->objclass == FL_INPUT);
272         BOOST_ASSERT(ybED && ybED->objclass == FL_INPUT);
273         BOOST_ASSERT(xrED && xrED->objclass == FL_INPUT);
274         BOOST_ASSERT(ytED && ytED->objclass == FL_INPUT);
275
276         fl_set_button(clipCB, data.clip);
277         graphics::BoundingBox const & bbox = data.bbox;
278         fl_set_input(xlED, tostr(bbox.xl).c_str());
279         fl_set_input(ybED, tostr(bbox.yb).c_str());
280         fl_set_input(xrED, tostr(bbox.xr).c_str());
281         fl_set_input(ytED, tostr(bbox.yt).c_str());
282 }
283
284
285 void getCrop(external::ClipData & data,
286              FL_OBJECT * clipCB,
287              FL_OBJECT * xlED, FL_OBJECT * ybED,
288              FL_OBJECT * xrED, FL_OBJECT * ytED,
289              bool bb_changed)
290 {
291         BOOST_ASSERT(clipCB && clipCB->objclass == FL_CHECKBUTTON);
292         BOOST_ASSERT(xlED && xlED->objclass == FL_INPUT);
293         BOOST_ASSERT(ybED && ybED->objclass == FL_INPUT);
294         BOOST_ASSERT(xrED && xrED->objclass == FL_INPUT);
295         BOOST_ASSERT(ytED && ytED->objclass == FL_INPUT);
296
297         data.clip = fl_get_button(clipCB);
298
299         if (!bb_changed)
300                 return;
301
302         data.bbox.xl = strToInt(getString(xlED));
303         data.bbox.yb = strToInt(getString(ybED));
304         data.bbox.xr = strToInt(getString(xrED));
305         data.bbox.yt = strToInt(getString(ytED));
306 }
307
308
309 void getExtra(external::ExtraData & data,
310               FormExternal::MapType const & extra)
311 {
312         typedef FormExternal::MapType MapType;
313         MapType::const_iterator it  = extra.begin();
314         MapType::const_iterator const end = extra.end();
315         for (; it != end; ++it)
316                 data.set(it->first, trim(it->second));
317 }
318
319 } // namespace anon
320
321
322 typedef FormController<ControlExternal, FormView<FD_external> > base_class;
323
324 FormExternal::FormExternal(Dialog & parent)
325         : base_class(parent, _("External Material"))
326 {}
327
328
329 void FormExternal::build()
330 {
331         dialog_.reset(build_external(this));
332         file_.reset(build_external_file(this));
333         lyxview_.reset(build_external_lyxview(this));
334         rotate_.reset(build_external_rotate(this));
335         scale_.reset(build_external_scale(this));
336         crop_.reset(build_external_crop(this));
337         options_.reset(build_external_options(this));
338
339         bcview().setOK(dialog_->button_ok);
340         bcview().setApply(dialog_->button_apply);
341         bcview().setCancel(dialog_->button_close);
342
343         bcview().addReadOnly(file_->input_file);
344         bcview().addReadOnly(file_->button_browse);
345         bcview().addReadOnly(file_->button_edit);
346         bcview().addReadOnly(file_->choice_template);
347         bcview().addReadOnly(file_->check_draft);
348
349         bcview().addReadOnly(lyxview_->check_show);
350         bcview().addReadOnly(lyxview_->choice_show);
351         bcview().addReadOnly(lyxview_->input_displayscale);
352
353         bcview().addReadOnly(rotate_->input_angle);
354         bcview().addReadOnly(rotate_->choice_origin);
355
356         bcview().addReadOnly(scale_->input_width);
357         bcview().addReadOnly(scale_->choice_width);
358         bcview().addReadOnly(scale_->input_height);
359         bcview().addReadOnly(scale_->choice_height);
360         bcview().addReadOnly(scale_->check_aspectratio);
361
362         bcview().addReadOnly(crop_->check_bbox);
363         bcview().addReadOnly(crop_->button_get_bbox);
364         bcview().addReadOnly(crop_->input_xr);
365         bcview().addReadOnly(crop_->input_yt);
366         bcview().addReadOnly(crop_->input_xl);
367         bcview().addReadOnly(crop_->input_yb);
368
369         bcview().addReadOnly(options_->choice_option);
370         bcview().addReadOnly(options_->input_option);
371
372         // initial setting
373 //      addCheckedPositiveFloat(bcview(), scale_->input_width);
374         // As I haven't written addCheckedPositiveFloat, we default to
375         // always checking that it is a valide LyXLength, even when
376         // I'm 'scaling'. No harm done, just not as strict as it might be.
377         addCheckedLyXLength(bcview(), scale_->input_width);
378         addCheckedLyXLength(bcview(), scale_->input_height);
379
380 //      addCheckedPositiveFloat(bcview(), input_displayscale);
381         fl_set_input_filter(lyxview_->input_displayscale,
382                             fl_unsigned_int_filter);
383
384         fl_set_input_filter(crop_->input_xr, fl_unsigned_int_filter);
385         fl_set_input_filter(crop_->input_yt, fl_unsigned_int_filter);
386         fl_set_input_filter(crop_->input_xl, fl_unsigned_int_filter);
387         fl_set_input_filter(crop_->input_yb, fl_unsigned_int_filter);
388
389         fl_set_input_return(file_->input_file,            FL_RETURN_CHANGED);
390         fl_set_input_return(lyxview_->input_displayscale, FL_RETURN_CHANGED);
391         fl_set_input_return(rotate_->input_angle,         FL_RETURN_CHANGED);
392         fl_set_input_return(scale_->input_width,          FL_RETURN_CHANGED);
393         fl_set_input_return(scale_->input_height,         FL_RETURN_CHANGED);
394         fl_set_input_return(crop_->input_xr,              FL_RETURN_CHANGED);
395         fl_set_input_return(crop_->input_yt,              FL_RETURN_CHANGED);
396         fl_set_input_return(crop_->input_xl,              FL_RETURN_CHANGED);
397         fl_set_input_return(crop_->input_yb,              FL_RETURN_CHANGED);
398         fl_set_input_return(options_->input_option,       FL_RETURN_CHANGED);
399
400         // Trigger an input event for cut&paste with middle mouse button.
401         setPrehandler(file_->input_file);
402         setPrehandler(lyxview_->input_displayscale);
403         setPrehandler(rotate_->input_angle);
404         setPrehandler(scale_->input_width);
405         setPrehandler(scale_->input_height);
406         setPrehandler(crop_->input_xr);
407         setPrehandler(crop_->input_yt);
408         setPrehandler(crop_->input_xl);
409         setPrehandler(crop_->input_yb);
410         setPrehandler(options_->input_option);
411
412         string const choice =
413                 ' ' + getStringFromVector(controller().getTemplates(), " | ") +
414                 ' ';
415         fl_addto_choice(file_->choice_template, choice.c_str());
416
417         string const display_list =
418                 _("Default|Monochrome|Grayscale|Color|Preview");
419         fl_addto_choice(lyxview_->choice_show, display_list.c_str());
420
421         // Fill the origins combo
422         typedef vector<external::RotationDataType> Origins;
423         Origins const & all_origins = external::all_origins();
424         for (Origins::size_type i = 0; i != all_origins.size(); ++i)
425                 fl_addto_choice(rotate_->choice_origin,
426                                 external::origin_gui_str(i).c_str());
427
428         string const height_list = buildChoiceLengthString();
429         string const width_list = bformat(_("Scale%%%%|%1$s"), height_list);
430
431         fl_addto_choice(scale_->choice_width, width_list.c_str());
432         fl_addto_choice(scale_->choice_height, height_list.c_str());
433
434         // Set up the tooltips.
435         string str = _("The file you want to insert.");
436         tooltips().init(file_->input_file, str);
437         str = _("Browse the directories.");
438         tooltips().init(file_->button_browse, str);
439
440         str = _("Scale the image to inserted percentage value.");
441         tooltips().init(lyxview_->input_displayscale, str);
442         str = _("Select display mode for this image.");
443         tooltips().init(options_->choice_option, str);
444
445         // Stack tabs
446         tabmap_[FILETAB] =
447                 fl_addto_tabfolder(dialog_->tabfolder, _("File").c_str(),
448                                    file_->form);
449
450         tabmap_[LYXVIEWTAB] =
451                 fl_addto_tabfolder(dialog_->tabfolder, _("LyX View").c_str(),
452                                    lyxview_->form);
453         tabmap_[ROTATETAB] =
454                 fl_addto_tabfolder(dialog_->tabfolder, _("Rotate").c_str(),
455                                    rotate_->form);
456         tabmap_[SCALETAB] =
457                 fl_addto_tabfolder(dialog_->tabfolder, _("Scale").c_str(),
458                                    scale_->form);
459         tabmap_[CROPTAB] =
460                 fl_addto_tabfolder(dialog_->tabfolder, _("Crop").c_str(),
461                                    crop_->form);
462         tabmap_[OPTIONSTAB] =
463                 fl_addto_tabfolder(dialog_->tabfolder, _("Options").c_str(),
464                                    options_->form);
465 }
466
467
468 void FormExternal::update()
469 {
470         fl_set_folder_bynumber(dialog_->tabfolder, 1);
471         InsetExternalParams const & params = controller().params();
472
473         string const buffer_path = kernel().bufferFilepath();
474         string const name = params.filename.outputFilename(buffer_path);
475         fl_set_input(file_->input_file, name.c_str());
476
477         int ID = controller().getTemplateNumber(params.templatename());
478         if (ID < 0) ID = 0;
479         fl_set_choice(file_->choice_template, ID+1);
480
481         updateComboChange();
482
483         fl_set_button(file_->check_draft, params.draft);
484
485         setDisplay(lyxview_->check_show, lyxview_->choice_show,
486                    lyxview_->input_displayscale,
487                    params.display, params.lyxscale,
488                    kernel().isBufferReadonly());
489
490         setRotation(rotate_->input_angle, rotate_->choice_origin,
491                     params.rotationdata);
492
493         setSize(scale_->input_width, scale_->choice_width,
494                 scale_->input_height, scale_->choice_height,
495                 scale_->check_aspectratio,
496                 params.resizedata);
497
498         setCrop(crop_->check_bbox,
499                 crop_->input_xl, crop_->input_yb,
500                 crop_->input_xr, crop_->input_yt,
501                 params.clipdata);
502         controller().bbChanged(!params.clipdata.bbox.empty());
503 }
504
505
506 void FormExternal::updateComboChange()
507 {
508         int const choice = fl_get_choice(file_->choice_template) - 1;
509         external::Template templ = controller().getTemplate(choice);
510
511         // Update the help text
512         string const txt = formatted(templ.helpText,
513                                      file_->browser_template->w - 20);
514         fl_clear_browser(file_->browser_template);
515         fl_addto_browser(file_->browser_template, txt.c_str());
516         fl_set_browser_topline(file_->browser_template, 0);
517
518         // Ascertain which (if any) transformations the template supports
519         // and disable tabs hosting unsupported transforms.
520         typedef vector<external::TransformID> TransformIDs;
521         TransformIDs const transformIds = templ.transformIds;
522         TransformIDs::const_iterator tr_begin = transformIds.begin();
523         TransformIDs::const_iterator const tr_end = transformIds.end();
524
525         tabmap_[FILETAB];
526         tabmap_[LYXVIEWTAB];
527         tabmap_[ROTATETAB];
528         tabmap_[SCALETAB];
529         tabmap_[CROPTAB];
530         tabmap_[OPTIONSTAB];
531
532         bool found = find(tr_begin, tr_end, external::Rotate) != tr_end;
533         setEnabled(tabmap_[ROTATETAB], found);
534
535         found = find(tr_begin, tr_end, external::Resize) != tr_end;
536         setEnabled(tabmap_[SCALETAB], found);
537
538         found = find(tr_begin, tr_end, external::Clip) != tr_end;
539         setEnabled(tabmap_[CROPTAB], found);
540
541         found = find(tr_begin, tr_end, external::Extra) != tr_end;
542         setEnabled(tabmap_[OPTIONSTAB], found);
543
544         if (!found)
545                 return;
546
547         // Ascertain whether the template has any formats supporting
548         // the 'Extra' option
549         FL_OBJECT * const ob_input  = options_->input_option;
550         FL_OBJECT * const ob_choice = options_->choice_option;
551         extra_.clear();
552         fl_set_input(ob_input, "");
553         fl_clear_choice(ob_choice);
554
555         external::Template::Formats::const_iterator it  = templ.formats.begin();
556         external::Template::Formats::const_iterator end = templ.formats.end();
557         for (; it != end; ++it) {
558                 if (it->second.option_transformers.find(external::Extra) ==
559                     it->second.option_transformers.end())
560                         continue;
561                 string const format = it->first;
562                 string const opt = controller().params().extradata.get(format);
563                 fl_addto_choice(ob_choice, format.c_str());
564                 extra_[format] = opt;
565         }
566
567         bool const enabled = fl_get_choice_maxitems(ob_choice) > 0;
568
569         setEnabled(tabmap_[OPTIONSTAB], enabled);
570         setEnabled(ob_input,  enabled && !kernel().isBufferReadonly());
571         setEnabled(ob_choice, enabled);
572
573         if (enabled) {
574                 fl_set_choice(ob_choice, 1);
575                 string const format = fl_get_choice_text(ob_choice);
576                 fl_set_input(ob_input, extra_[format].c_str());
577         }
578 }
579
580
581 void FormExternal::apply()
582 {
583         InsetExternalParams params = controller().params();
584
585         string const buffer_path = kernel().bufferFilepath();
586         params.filename.set(getString(file_->input_file), buffer_path);
587
588         int const choice = fl_get_choice(file_->choice_template) - 1;
589         params.settemplate(controller().getTemplate(choice).lyxName);
590
591         params.draft = fl_get_button(file_->check_draft);
592
593         getDisplay(params.display, params.lyxscale,
594                    lyxview_->check_show, lyxview_->choice_show,
595                    lyxview_->input_displayscale);
596
597         if (isActive(tabmap_[ROTATETAB]))
598                 getRotation(params.rotationdata,
599                             rotate_->input_angle, rotate_->choice_origin);
600
601         if (isActive(tabmap_[SCALETAB]))
602                 getSize(params.resizedata,
603                         scale_->input_width, scale_->choice_width,
604                         scale_->input_height, scale_->choice_height,
605                         scale_->check_aspectratio);
606
607         if (isActive(tabmap_[CROPTAB]))
608                 getCrop(params.clipdata,
609                         crop_->check_bbox,
610                         crop_->input_xl, crop_->input_yb,
611                         crop_->input_xr, crop_->input_yt,
612                         controller().bbChanged());
613
614         if (isActive(tabmap_[OPTIONSTAB]))
615                 getExtra(params.extradata, extra_);
616
617         controller().setParams(params);
618 }
619
620
621 ButtonPolicy::SMInput FormExternal::input(FL_OBJECT * ob, long)
622 {
623         ButtonPolicy::SMInput result = ButtonPolicy::SMI_VALID;
624
625         if (ob == file_->choice_template) {
626
627                 // set to the chosen template
628                 updateComboChange();
629
630         } else if (ob == file_->button_browse) {
631
632                 string const in_name  = fl_get_input(file_->input_file);
633
634                 int const choice = fl_get_choice(file_->choice_template) - 1;
635                 string const template_name =
636                         controller().getTemplate(choice).lyxName;
637                 string const out_name =
638                         controller().browse(in_name, template_name);
639                 fl_set_input(file_->input_file, out_name.c_str());
640
641         } else if (ob == file_->button_edit) {
642                 controller().editExternal();
643                 result = ButtonPolicy::SMI_NOOP;
644
645         } else if (ob == lyxview_->check_show) {
646
647                 bool const checked = fl_get_button(ob);
648                 setEnabled(lyxview_->choice_show, checked);
649                 setEnabled(lyxview_->input_displayscale, checked);
650
651         } else if (ob == crop_->button_get_bbox) {
652
653                 getBB();
654
655         } else if (ob == scale_->input_width ||
656                    ob == scale_->input_height) {
657
658                 setEnabled(scale_->check_aspectratio,
659                            activateAspectratio());
660
661         } else if (ob == scale_->choice_width) {
662
663                 widthUnitChanged();
664
665         } else if (ob == crop_->input_xr ||
666                    ob == crop_->input_yt ||
667                    ob == crop_->input_xl ||
668                    ob == crop_->input_yb) {
669
670                 controller().bbChanged(true);
671
672         } else if (ob == options_->input_option) {
673
674                 string const format =
675                         fl_get_choice_text(options_->choice_option);
676                 extra_[format] = getString(options_->input_option);
677
678         } else if (ob == options_->choice_option) {
679
680                 string const format =
681                         fl_get_choice_text(options_->choice_option);
682                 fl_set_input(options_->input_option, extra_[format].c_str());
683                 result = ButtonPolicy::SMI_NOOP;
684         }
685
686         return result;
687 }
688
689
690 bool FormExternal::activateAspectratio() const
691 {
692         if (fl_get_choice(scale_->choice_width) == 1)
693                 return false;
694
695         string const wstr = getString(scale_->input_width);
696         if (wstr.empty())
697                 return false;
698         bool const wIsDbl = isStrDbl(wstr);
699         if (wIsDbl && float_equal(strToDbl(wstr), 0.0, 0.05))
700                 return false;
701         LyXLength l;
702         if (!wIsDbl && (!isValidLength(wstr, &l) || l.zero()))
703                 return false;
704
705         string const hstr = getString(scale_->input_height);
706         if (hstr.empty())
707                 return false;
708         bool const hIsDbl = isStrDbl(hstr);
709         if (hIsDbl && float_equal(strToDbl(hstr), 0.0, 0.05))
710                 return false;
711         if (!hIsDbl && (!isValidLength(hstr, &l) || l.zero()))
712                 return false;
713
714         return true;
715 }
716
717
718 void FormExternal::getBB()
719 {
720         fl_set_input(crop_->input_xl, "0");
721         fl_set_input(crop_->input_yb, "0");
722         fl_set_input(crop_->input_xr, "0");
723         fl_set_input(crop_->input_yt, "0");
724
725         string const filename = getString(file_->input_file);
726         if (filename.empty())
727                 return;
728
729         string const bb = controller().readBB(filename);
730         if (bb.empty())
731                 return;
732
733         fl_set_input(crop_->input_xl, token(bb, ' ', 0).c_str());
734         fl_set_input(crop_->input_yb, token(bb, ' ', 1).c_str());
735         fl_set_input(crop_->input_xr, token(bb, ' ', 2).c_str());
736         fl_set_input(crop_->input_yt, token(bb, ' ', 3).c_str());
737
738         controller().bbChanged(false);
739 }
740
741
742 void FormExternal::widthUnitChanged()
743 {
744         if (fl_get_choice(scale_->choice_width) == 1)
745                 return;
746
747         bool useHeight = fl_get_choice(scale_->choice_width) > 1;
748
749 //      if (useHeight)
750 //              widthED->setValidator(unsignedLengthValidator(widthED));
751 //      else
752 //              widthED->setValidator(new QDoubleValidator(0, 1000, 2, widthED));
753
754         setEnabled(scale_->input_height, useHeight);
755         setEnabled(scale_->choice_height, useHeight);
756 }
757
758 } // namespace frontend
759 } // namespace lyx