]> git.lyx.org Git - lyx.git/blobdiff - src/frontends/xforms/FormExternal.C
the convert patch
[lyx.git] / src / frontends / xforms / FormExternal.C
index edf65d0c4d6609a8868ea56b10b6b2ae31cabb8d..7bffb9c4755c9022cd29df8707e150d39e8d4631 100644 (file)
-/* This file is part of
- * ====================================================== 
- *
- *           LyX, The Document Processor
- *
- *           Copyright 2000-2001 The LyX Team.
- *
- * ======================================================
- *
+/**
  * \file FormExternal.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
  * \author Asger Alstrup
  * \author John Levon
- * \author Angus Leeming, a.leeming@ic.ac.uk
+ * \author Angus Leeming
+ *
+ * Full author contact details are available in file CREDITS.
  */
 
 #include <config.h>
 
-#ifdef __GNUG__
-#pragma implementation
-#endif
-
-#include "xformsBC.h"
-#include "ControlExternal.h"
 #include "FormExternal.h"
-#include "form_external.h"
-#include "gettext.h"
+#include "forms/form_external.h"
+
+#include "checkedwidgets.h"
+#include "input_validators.h"
+#include "Tooltips.h"
 #include "xforms_helpers.h"
-#include "helper_funcs.h"
+#include "xformsBC.h"
 
-typedef FormCB<ControlExternal, FormDB<FD_form_external> > base_class;
+#include "controllers/ControlExternal.h"
 
-FormExternal::FormExternal(ControlExternal & c)
-       : base_class(c, _("Edit external file"))
-{}
+#include "lengthcommon.h"
+#include "lyxrc.h"
 
+#include "insets/ExternalTemplate.h"
+#include "insets/insetexternal.h"
 
-void FormExternal::apply()
+#include "support/lstrings.h"
+#include "support/lyxlib.h"
+#include "support/convert.h"
+
+#include "lyx_forms.h"
+
+namespace external = lyx::external;
+
+using std::find;
+using std::string;
+using std::vector;
+
+namespace lyx {
+
+using support::bformat;
+using support::float_equal;
+using support::getStringFromVector;
+using support::isStrDbl;
+using support::token;
+using support::trim;
+
+namespace frontend {
+
+namespace {
+
+LyXLength::UNIT defaultUnit()
 {
-       controller().params().filename =
-               fl_get_input(dialog_->input_filename);
-       controller().params().parameters =
-               fl_get_input(dialog_->input_parameters);
+       LyXLength::UNIT default_unit = LyXLength::CM;
+       switch (lyxrc.default_papersize) {
+       case PAPER_USLETTER:
+       case PAPER_LEGALPAPER:
+       case PAPER_EXECUTIVEPAPER:
+               default_unit = LyXLength::IN;
+               break;
+       default:
+               break;
+       }
+       return default_unit;
+}
+
 
-       int const choice = fl_get_choice(dialog_->choice_template);
-       controller().params().templ = controller().getTemplate(choice);
+void setDisplay(FL_OBJECT * displayCB, FL_OBJECT * showCO, FL_OBJECT * scaleED,
+               external::DisplayType display, unsigned int scale,
+               bool read_only)
+{
+       BOOST_ASSERT(displayCB && displayCB->objclass == FL_CHECKBUTTON);
+       BOOST_ASSERT(showCO && showCO->objclass == FL_CHOICE);
+       BOOST_ASSERT(scaleED && scaleED->objclass == FL_INPUT);
+
+       int item = 1;
+       switch (display) {
+       case external::DefaultDisplay:
+               item = 1;
+               break;
+       case external::MonochromeDisplay:
+               item = 2;
+               break;
+       case external::GrayscaleDisplay:
+               item = 3;
+               break;
+       case external::ColorDisplay:
+               item = 4;
+               break;
+       case external::PreviewDisplay:
+               item = 5;
+               break;
+       case external::NoDisplay:
+               item = 1;
+               break;
+       }
+
+       fl_set_choice(showCO, item);
+
+       bool const no_display = display == external::NoDisplay;
+       setEnabled(showCO, !no_display && !read_only);
+
+       fl_set_button(displayCB, !no_display);
+
+       fl_set_input(scaleED, convert<string>(scale).c_str());
+       setEnabled(scaleED, !no_display && !read_only);
 }
 
 
+void getDisplay(external::DisplayType & display,
+               unsigned int & scale,
+               FL_OBJECT * displayCB,
+               FL_OBJECT * showCO,
+               FL_OBJECT * scaleED)
+{
+       BOOST_ASSERT(displayCB && displayCB->objclass == FL_CHECKBUTTON);
+       BOOST_ASSERT(showCO && showCO->objclass == FL_CHOICE);
+       BOOST_ASSERT(scaleED && scaleED->objclass == FL_INPUT);
+
+       switch (fl_get_choice(showCO)) {
+       case 1:
+               display = external::DefaultDisplay;
+               break;
+       case 2:
+               display = external::MonochromeDisplay;
+               break;
+       case 3:
+               display = external::GrayscaleDisplay;
+               break;
+       case 4:
+               display = external::ColorDisplay;
+               break;
+       case 5:
+               display = external::PreviewDisplay;
+               break;
+       }
+
+       if (!fl_get_button(displayCB))
+               display = external::NoDisplay;
+
+       scale = convert<int>(getString(scaleED));
+}
+
+
+void setRotation(FL_OBJECT * angleED, FL_OBJECT * originCO,
+                external::RotationData const & data)
+{
+       BOOST_ASSERT(angleED && angleED->objclass == FL_INPUT);
+       BOOST_ASSERT(originCO && originCO->objclass == FL_CHOICE);
+
+       fl_set_choice(originCO, 1 + int(data.origin()));
+       fl_set_input(angleED, data.angle.c_str());
+}
+
+
+void getRotation(external::RotationData & data,
+                FL_OBJECT * angleED, FL_OBJECT * originCO)
+{
+       BOOST_ASSERT(angleED && angleED->objclass == FL_INPUT);
+       BOOST_ASSERT(originCO && originCO->objclass == FL_CHOICE);
+
+       typedef external::RotationData::OriginType OriginType;
+
+       data.origin(static_cast<OriginType>(fl_get_choice(originCO) - 1));
+       data.angle = getString(angleED);
+}
+
+
+void setSize(FL_OBJECT * widthED, FL_OBJECT * widthUnitCO,
+            FL_OBJECT * heightED, FL_OBJECT * heightUnitCO,
+            FL_OBJECT * aspectratioCB,
+            external::ResizeData const & data)
+{
+       BOOST_ASSERT(widthED && widthED->objclass == FL_INPUT);
+       BOOST_ASSERT(widthUnitCO && widthUnitCO->objclass == FL_CHOICE);
+       BOOST_ASSERT(heightED && heightED->objclass == FL_INPUT);
+       BOOST_ASSERT(heightUnitCO && heightUnitCO->objclass == FL_CHOICE);
+       BOOST_ASSERT(aspectratioCB &&
+                    aspectratioCB->objclass == FL_CHECKBUTTON);
+
+       bool using_scale = data.usingScale();
+       std::string scale =  data.scale;
+       if (data.no_resize()) {
+               // Everything is zero, so default to this!
+               using_scale = true;
+               scale = "100";
+       }
+
+       if (using_scale) {
+               fl_set_input(widthED, scale.c_str());
+               fl_set_choice(widthUnitCO, 1);
+       } else {
+               fl_set_input(widthED, convert<string>(data.width.value()).c_str());
+               // Because 'Scale' is position 1...
+               // Note also that width cannot be zero here, so
+               // we don't need to worry about the default unit.
+               fl_set_choice(widthUnitCO, data.width.unit() + 2);
+       }
+
+       string const h = data.height.zero() ? string() : data.height.asString();
+       LyXLength::UNIT default_unit = data.width.zero() ?
+               defaultUnit() : data.width.unit();
+       updateWidgetsFromLengthString(heightED, heightUnitCO,
+                                     h, stringFromUnit(default_unit));
+
+       setEnabled(heightED, !using_scale);
+       setEnabled(heightUnitCO, !using_scale);
+
+       fl_set_button(aspectratioCB, data.keepAspectRatio);
+
+       bool const disable_aspectRatio = using_scale ||
+               data.width.zero() || data.height.zero();
+       setEnabled(aspectratioCB, !disable_aspectRatio);
+}
+
+
+void getSize(external::ResizeData & data,
+            FL_OBJECT * widthED, FL_OBJECT * widthUnitCO,
+            FL_OBJECT * heightED, FL_OBJECT * heightUnitCO,
+            FL_OBJECT * aspectratioCB)
+{
+       BOOST_ASSERT(widthED && widthED->objclass == FL_INPUT);
+       BOOST_ASSERT(widthUnitCO && widthUnitCO->objclass == FL_CHOICE);
+       BOOST_ASSERT(heightED && heightED->objclass == FL_INPUT);
+       BOOST_ASSERT(heightUnitCO && heightUnitCO->objclass == FL_CHOICE);
+       BOOST_ASSERT(aspectratioCB &&
+                    aspectratioCB->objclass == FL_CHECKBUTTON);
+
+       string const width = getString(widthED);
+
+       if (fl_get_choice(widthUnitCO) > 1) {
+               // Subtract one, because scale is 1.
+               int const unit = fl_get_choice(widthUnitCO) - 1;
+
+               LyXLength w;
+               if (isValidLength(width, &w))
+                       data.width = w;
+               else if (isStrDbl(width))
+                       data.width = LyXLength(convert<double>(width),
+                                          static_cast<LyXLength::UNIT>(unit));
+               else
+                       data.width = LyXLength();
+
+               data.scale.erase();
+       } else {
+               // scaling instead of a width
+               data.scale = width;
+               data.width = LyXLength();
+       }
+
+       data.height = LyXLength(getLengthFromWidgets(heightED, heightUnitCO));
+
+       data.keepAspectRatio = fl_get_button(aspectratioCB);
+}
+
+
+void setCrop(FL_OBJECT * clipCB,
+            FL_OBJECT * xlED, FL_OBJECT * ybED,
+            FL_OBJECT * xrED, FL_OBJECT * ytED,
+            external::ClipData const & data)
+{
+       BOOST_ASSERT(clipCB && clipCB->objclass == FL_CHECKBUTTON);
+       BOOST_ASSERT(xlED && xlED->objclass == FL_INPUT);
+       BOOST_ASSERT(ybED && ybED->objclass == FL_INPUT);
+       BOOST_ASSERT(xrED && xrED->objclass == FL_INPUT);
+       BOOST_ASSERT(ytED && ytED->objclass == FL_INPUT);
+
+       fl_set_button(clipCB, data.clip);
+       graphics::BoundingBox const & bbox = data.bbox;
+       fl_set_input(xlED, convert<string>(bbox.xl).c_str());
+       fl_set_input(ybED, convert<string>(bbox.yb).c_str());
+       fl_set_input(xrED, convert<string>(bbox.xr).c_str());
+       fl_set_input(ytED, convert<string>(bbox.yt).c_str());
+}
+
+
+void getCrop(external::ClipData & data,
+            FL_OBJECT * clipCB,
+            FL_OBJECT * xlED, FL_OBJECT * ybED,
+            FL_OBJECT * xrED, FL_OBJECT * ytED,
+            bool bb_changed)
+{
+       BOOST_ASSERT(clipCB && clipCB->objclass == FL_CHECKBUTTON);
+       BOOST_ASSERT(xlED && xlED->objclass == FL_INPUT);
+       BOOST_ASSERT(ybED && ybED->objclass == FL_INPUT);
+       BOOST_ASSERT(xrED && xrED->objclass == FL_INPUT);
+       BOOST_ASSERT(ytED && ytED->objclass == FL_INPUT);
+
+       data.clip = fl_get_button(clipCB);
+
+       if (!bb_changed)
+               return;
+
+       data.bbox.xl = convert<int>(getString(xlED));
+       data.bbox.yb = convert<int>(getString(ybED));
+       data.bbox.xr = convert<int>(getString(xrED));
+       data.bbox.yt = convert<int>(getString(ytED));
+}
+
+
+void getExtra(external::ExtraData & data,
+             FormExternal::MapType const & extra)
+{
+       typedef FormExternal::MapType MapType;
+       MapType::const_iterator it  = extra.begin();
+       MapType::const_iterator const end = extra.end();
+       for (; it != end; ++it)
+               data.set(it->first, trim(it->second));
+}
+
+} // namespace anon
+
+
+typedef FormController<ControlExternal, FormView<FD_external> > base_class;
+
+FormExternal::FormExternal(Dialog & parent)
+       : base_class(parent, _("External Material"))
+{}
+
+
 void FormExternal::build()
 {
-       dialog_.reset(build_external());
+       dialog_.reset(build_external(this));
+       file_.reset(build_external_file(this));
+       lyxview_.reset(build_external_lyxview(this));
+       rotate_.reset(build_external_rotate(this));
+       scale_.reset(build_external_scale(this));
+       crop_.reset(build_external_crop(this));
+       options_.reset(build_external_options(this));
+
+       bcview().setOK(dialog_->button_ok);
+       bcview().setApply(dialog_->button_apply);
+       bcview().setCancel(dialog_->button_close);
+
+       bcview().addReadOnly(file_->input_file);
+       bcview().addReadOnly(file_->button_browse);
+       bcview().addReadOnly(file_->button_edit);
+       bcview().addReadOnly(file_->choice_template);
+       bcview().addReadOnly(file_->check_draft);
+
+       bcview().addReadOnly(lyxview_->check_show);
+       bcview().addReadOnly(lyxview_->choice_show);
+       bcview().addReadOnly(lyxview_->input_displayscale);
+
+       bcview().addReadOnly(rotate_->input_angle);
+       bcview().addReadOnly(rotate_->choice_origin);
+
+       bcview().addReadOnly(scale_->input_width);
+       bcview().addReadOnly(scale_->choice_width);
+       bcview().addReadOnly(scale_->input_height);
+       bcview().addReadOnly(scale_->choice_height);
+       bcview().addReadOnly(scale_->check_aspectratio);
+
+       bcview().addReadOnly(crop_->check_bbox);
+       bcview().addReadOnly(crop_->button_get_bbox);
+       bcview().addReadOnly(crop_->input_xr);
+       bcview().addReadOnly(crop_->input_yt);
+       bcview().addReadOnly(crop_->input_xl);
+       bcview().addReadOnly(crop_->input_yb);
+
+       bcview().addReadOnly(options_->choice_option);
+       bcview().addReadOnly(options_->input_option);
+
+       // initial setting
+//     addCheckedPositiveFloat(bcview(), scale_->input_width);
+       // As I haven't written addCheckedPositiveFloat, we default to
+       // always checking that it is a valide LyXLength, even when
+       // I'm 'scaling'. No harm done, just not as strict as it might be.
+       addCheckedLyXLength(bcview(), scale_->input_width);
+       addCheckedLyXLength(bcview(), scale_->input_height);
+
+//     addCheckedPositiveFloat(bcview(), input_displayscale);
+       fl_set_input_filter(lyxview_->input_displayscale,
+                           fl_unsigned_int_filter);
+
+       fl_set_input_filter(crop_->input_xr, fl_unsigned_int_filter);
+       fl_set_input_filter(crop_->input_yt, fl_unsigned_int_filter);
+       fl_set_input_filter(crop_->input_xl, fl_unsigned_int_filter);
+       fl_set_input_filter(crop_->input_yb, fl_unsigned_int_filter);
+
+       fl_set_input_return(file_->input_file,            FL_RETURN_CHANGED);
+       fl_set_input_return(lyxview_->input_displayscale, FL_RETURN_CHANGED);
+       fl_set_input_return(rotate_->input_angle,         FL_RETURN_CHANGED);
+       fl_set_input_return(scale_->input_width,          FL_RETURN_CHANGED);
+       fl_set_input_return(scale_->input_height,         FL_RETURN_CHANGED);
+       fl_set_input_return(crop_->input_xr,              FL_RETURN_CHANGED);
+       fl_set_input_return(crop_->input_yt,              FL_RETURN_CHANGED);
+       fl_set_input_return(crop_->input_xl,              FL_RETURN_CHANGED);
+       fl_set_input_return(crop_->input_yb,              FL_RETURN_CHANGED);
+       fl_set_input_return(options_->input_option,       FL_RETURN_CHANGED);
+
+       // Trigger an input event for cut&paste with middle mouse button.
+       setPrehandler(file_->input_file);
+       setPrehandler(lyxview_->input_displayscale);
+       setPrehandler(rotate_->input_angle);
+       setPrehandler(scale_->input_width);
+       setPrehandler(scale_->input_height);
+       setPrehandler(crop_->input_xr);
+       setPrehandler(crop_->input_yt);
+       setPrehandler(crop_->input_xl);
+       setPrehandler(crop_->input_yb);
+       setPrehandler(options_->input_option);
 
        string const choice =
-           " " + getStringFromVector(controller().getTemplates(), " | ") + " ";
-       fl_addto_choice(dialog_->choice_template, choice.c_str());
+               ' ' + getStringFromVector(controller().getTemplates(), " | ") +
+               ' ';
+       fl_addto_choice(file_->choice_template, choice.c_str());
 
-       bc().setOK(dialog_->button_ok);
-       bc().setApply(dialog_->button_apply);
-       bc().setCancel(dialog_->button_cancel);
+       string const display_list =
+               _("Default|Monochrome|Grayscale|Color|Preview");
+       fl_addto_choice(lyxview_->choice_show, display_list.c_str());
 
-       bc().addReadOnly(dialog_->input_filename);
-       bc().addReadOnly(dialog_->button_filenamebrowse);
-       bc().addReadOnly(dialog_->input_parameters);
+       // Fill the origins combo
+       typedef vector<external::RotationDataType> Origins;
+       Origins const & all_origins = external::all_origins();
+       for (Origins::size_type i = 0; i != all_origins.size(); ++i)
+               fl_addto_choice(rotate_->choice_origin,
+                               external::origin_gui_str(i).c_str());
+
+       string const height_list = buildChoiceLengthString();
+       string const width_list = bformat(_("Scale%%%%|%1$s"), height_list);
+
+       fl_addto_choice(scale_->choice_width, width_list.c_str());
+       fl_addto_choice(scale_->choice_height, height_list.c_str());
+
+       // Set up the tooltips.
+       string str = _("The file you want to insert.");
+       tooltips().init(file_->input_file, str);
+       str = _("Browse the directories.");
+       tooltips().init(file_->button_browse, str);
+
+       str = _("Scale the image to inserted percentage value.");
+       tooltips().init(lyxview_->input_displayscale, str);
+       str = _("Select display mode for this image.");
+       tooltips().init(options_->choice_option, str);
+
+       // Stack tabs
+       tabmap_[FILETAB] =
+               fl_addto_tabfolder(dialog_->tabfolder, _("File").c_str(),
+                                  file_->form);
+
+       tabmap_[LYXVIEWTAB] =
+               fl_addto_tabfolder(dialog_->tabfolder, _("LyX View").c_str(),
+                                  lyxview_->form);
+       tabmap_[ROTATETAB] =
+               fl_addto_tabfolder(dialog_->tabfolder, _("Rotate").c_str(),
+                                  rotate_->form);
+       tabmap_[SCALETAB] =
+               fl_addto_tabfolder(dialog_->tabfolder, _("Scale").c_str(),
+                                  scale_->form);
+       tabmap_[CROPTAB] =
+               fl_addto_tabfolder(dialog_->tabfolder, _("Crop").c_str(),
+                                  crop_->form);
+       tabmap_[OPTIONSTAB] =
+               fl_addto_tabfolder(dialog_->tabfolder, _("Options").c_str(),
+                                  options_->form);
 }
 
 
 void FormExternal::update()
 {
-       InsetExternal::Params const & params = controller().params();
+       fl_set_folder_bynumber(dialog_->tabfolder, 1);
+       InsetExternalParams const & params = controller().params();
 
-       fl_set_input(dialog_->input_filename, params.filename.c_str());
-       fl_set_input(dialog_->input_parameters, params.parameters.c_str());
+       string const buffer_path = kernel().bufferFilepath();
+       string const name = params.filename.outputFilename(buffer_path);
+       fl_set_input(file_->input_file, name.c_str());
 
-       int const ID = controller().getTemplateNumber(params.templ.lyxName);
-       if (ID >= 0) {
-               setEnabled(dialog_->choice_template, true);
-               fl_set_choice(dialog_->choice_template, ID+1);
-       } else
-               setEnabled(dialog_->choice_template, false);
+       int ID = controller().getTemplateNumber(params.templatename());
+       if (ID < 0) ID = 0;
+       fl_set_choice(file_->choice_template, ID+1);
 
        updateComboChange();
+
+       fl_set_button(file_->check_draft, params.draft);
+
+       setDisplay(lyxview_->check_show, lyxview_->choice_show,
+                  lyxview_->input_displayscale,
+                  params.display, params.lyxscale,
+                  kernel().isBufferReadonly());
+
+       setRotation(rotate_->input_angle, rotate_->choice_origin,
+                   params.rotationdata);
+
+       setSize(scale_->input_width, scale_->choice_width,
+               scale_->input_height, scale_->choice_height,
+               scale_->check_aspectratio,
+               params.resizedata);
+
+       setCrop(crop_->check_bbox,
+               crop_->input_xl, crop_->input_yb,
+               crop_->input_xr, crop_->input_yt,
+               params.clipdata);
+       controller().bbChanged(!params.clipdata.bbox.empty());
+}
+
+
+void FormExternal::updateComboChange()
+{
+       int const choice = fl_get_choice(file_->choice_template) - 1;
+       external::Template templ = controller().getTemplate(choice);
+
+       // Update the help text
+       string const txt = formatted(templ.helpText,
+                                    file_->browser_template->w - 20);
+       fl_clear_browser(file_->browser_template);
+       fl_addto_browser(file_->browser_template, txt.c_str());
+       fl_set_browser_topline(file_->browser_template, 0);
+
+       // Ascertain which (if any) transformations the template supports
+       // and disable tabs hosting unsupported transforms.
+       typedef vector<external::TransformID> TransformIDs;
+       TransformIDs const transformIds = templ.transformIds;
+       TransformIDs::const_iterator tr_begin = transformIds.begin();
+       TransformIDs::const_iterator const tr_end = transformIds.end();
+
+       tabmap_[FILETAB];
+       tabmap_[LYXVIEWTAB];
+       tabmap_[ROTATETAB];
+       tabmap_[SCALETAB];
+       tabmap_[CROPTAB];
+       tabmap_[OPTIONSTAB];
+
+       bool found = find(tr_begin, tr_end, external::Rotate) != tr_end;
+       setEnabled(tabmap_[ROTATETAB], found);
+
+       found = find(tr_begin, tr_end, external::Resize) != tr_end;
+       setEnabled(tabmap_[SCALETAB], found);
+
+       found = find(tr_begin, tr_end, external::Clip) != tr_end;
+       setEnabled(tabmap_[CROPTAB], found);
+
+       found = find(tr_begin, tr_end, external::Extra) != tr_end;
+       setEnabled(tabmap_[OPTIONSTAB], found);
+
+       if (!found)
+               return;
+
+       // Ascertain whether the template has any formats supporting
+       // the 'Extra' option
+       FL_OBJECT * const ob_input  = options_->input_option;
+       FL_OBJECT * const ob_choice = options_->choice_option;
+       extra_.clear();
+       fl_set_input(ob_input, "");
+       fl_clear_choice(ob_choice);
+
+       external::Template::Formats::const_iterator it  = templ.formats.begin();
+       external::Template::Formats::const_iterator end = templ.formats.end();
+       for (; it != end; ++it) {
+               if (it->second.option_transformers.find(external::Extra) ==
+                   it->second.option_transformers.end())
+                       continue;
+               string const format = it->first;
+               string const opt = controller().params().extradata.get(format);
+               fl_addto_choice(ob_choice, format.c_str());
+               extra_[format] = opt;
+       }
+
+       bool const enabled = fl_get_choice_maxitems(ob_choice) > 0;
+
+       setEnabled(tabmap_[OPTIONSTAB], enabled);
+       setEnabled(ob_input,  enabled && !kernel().isBufferReadonly());
+       setEnabled(ob_choice, enabled);
+
+       if (enabled) {
+               fl_set_choice(ob_choice, 1);
+               string const format = fl_get_choice_text(ob_choice);
+               fl_set_input(ob_input, extra_[format].c_str());
+       }
+}
+
+
+void FormExternal::apply()
+{
+       InsetExternalParams params = controller().params();
+
+       string const buffer_path = kernel().bufferFilepath();
+       params.filename.set(getString(file_->input_file), buffer_path);
+
+       int const choice = fl_get_choice(file_->choice_template) - 1;
+       params.settemplate(controller().getTemplate(choice).lyxName);
+
+       params.draft = fl_get_button(file_->check_draft);
+
+       getDisplay(params.display, params.lyxscale,
+                  lyxview_->check_show, lyxview_->choice_show,
+                  lyxview_->input_displayscale);
+
+       if (isActive(tabmap_[ROTATETAB]))
+               getRotation(params.rotationdata,
+                           rotate_->input_angle, rotate_->choice_origin);
+
+       if (isActive(tabmap_[SCALETAB]))
+               getSize(params.resizedata,
+                       scale_->input_width, scale_->choice_width,
+                       scale_->input_height, scale_->choice_height,
+                       scale_->check_aspectratio);
+
+       if (isActive(tabmap_[CROPTAB]))
+               getCrop(params.clipdata,
+                       crop_->check_bbox,
+                       crop_->input_xl, crop_->input_yb,
+                       crop_->input_xr, crop_->input_yt,
+                       controller().bbChanged());
+
+       if (isActive(tabmap_[OPTIONSTAB]))
+               getExtra(params.extradata, extra_);
+
+       controller().setParams(params);
 }
 
 
 ButtonPolicy::SMInput FormExternal::input(FL_OBJECT * ob, long)
 {
-       if (ob == dialog_->choice_template) {
+       ButtonPolicy::SMInput result = ButtonPolicy::SMI_VALID;
 
-               // set to the chosen template
-               int const choice = fl_get_choice(dialog_->choice_template);
-               controller().params().templ = controller().getTemplate(choice);
+       if (ob == file_->choice_template) {
 
+               // set to the chosen template
                updateComboChange();
 
-       } else if (ob == dialog_->button_filenamebrowse) {
+       } else if (ob == file_->button_browse) {
+
+               string const in_name  = fl_get_input(file_->input_file);
 
-               string const in_name  = fl_get_input(dialog_->input_filename);
-               string const out_name = controller().Browse(in_name);
-               fl_set_input(dialog_->input_filename, out_name.c_str());
+               int const choice = fl_get_choice(file_->choice_template) - 1;
+               string const template_name =
+                       controller().getTemplate(choice).lyxName;
+               string const out_name =
+                       controller().browse(in_name, template_name);
+               fl_set_input(file_->input_file, out_name.c_str());
 
-       } else if (ob == dialog_->button_edit) {
+       } else if (ob == file_->button_edit) {
                controller().editExternal();
+               result = ButtonPolicy::SMI_NOOP;
+
+       } else if (ob == lyxview_->check_show) {
+
+               bool const checked = fl_get_button(ob);
+               setEnabled(lyxview_->choice_show, checked);
+               setEnabled(lyxview_->input_displayscale, checked);
+
+       } else if (ob == crop_->button_get_bbox) {
+
+               getBB();
+
+       } else if (ob == scale_->input_width ||
+                  ob == scale_->input_height) {
+
+               setEnabled(scale_->check_aspectratio,
+                          activateAspectratio());
+
+       } else if (ob == scale_->choice_width) {
+
+               widthUnitChanged();
+
+       } else if (ob == crop_->input_xr ||
+                  ob == crop_->input_yt ||
+                  ob == crop_->input_xl ||
+                  ob == crop_->input_yb) {
 
-       } else if (ob == dialog_->button_view) {
-               controller().viewExternal();
+               controller().bbChanged(true);
 
-       } else if (ob == dialog_->button_update) {
-               controller().updateExternal();
+       } else if (ob == options_->input_option) {
+
+               string const format =
+                       fl_get_choice_text(options_->choice_option);
+               extra_[format] = getString(options_->input_option);
+
+       } else if (ob == options_->choice_option) {
+
+               string const format =
+                       fl_get_choice_text(options_->choice_option);
+               fl_set_input(options_->input_option, extra_[format].c_str());
+               result = ButtonPolicy::SMI_NOOP;
        }
 
-       return ButtonPolicy::SMI_VALID;
+       return result;
 }
 
 
-void FormExternal::updateComboChange()
+bool FormExternal::activateAspectratio() const
 {
-       // Update the help text
-       fl_clear_browser(dialog_->browser_helptext);
-       fl_addto_browser(dialog_->browser_helptext,
-                        controller().params().templ.helpText.c_str());
-       fl_set_browser_topline(dialog_->browser_helptext, 0);
+       if (fl_get_choice(scale_->choice_width) == 1)
+               return false;
+
+       string const wstr = getString(scale_->input_width);
+       if (wstr.empty())
+               return false;
+       bool const wIsDbl = isStrDbl(wstr);
+       if (wIsDbl && float_equal(convert<double>(wstr), 0.0, 0.05))
+               return false;
+       LyXLength l;
+       if (!wIsDbl && (!isValidLength(wstr, &l) || l.zero()))
+               return false;
 
-       bool const enabled = (!controller().params().templ.automaticProduction);
-       setEnabled(dialog_->button_update, enabled);
+       string const hstr = getString(scale_->input_height);
+       if (hstr.empty())
+               return false;
+       bool const hIsDbl = isStrDbl(hstr);
+       if (hIsDbl && float_equal(convert<double>(hstr), 0.0, 0.05))
+               return false;
+       if (!hIsDbl && (!isValidLength(hstr, &l) || l.zero()))
+               return false;
+
+       return true;
 }
+
+
+void FormExternal::getBB()
+{
+       fl_set_input(crop_->input_xl, "0");
+       fl_set_input(crop_->input_yb, "0");
+       fl_set_input(crop_->input_xr, "0");
+       fl_set_input(crop_->input_yt, "0");
+
+       string const filename = getString(file_->input_file);
+       if (filename.empty())
+               return;
+
+       string const bb = controller().readBB(filename);
+       if (bb.empty())
+               return;
+
+       fl_set_input(crop_->input_xl, token(bb, ' ', 0).c_str());
+       fl_set_input(crop_->input_yb, token(bb, ' ', 1).c_str());
+       fl_set_input(crop_->input_xr, token(bb, ' ', 2).c_str());
+       fl_set_input(crop_->input_yt, token(bb, ' ', 3).c_str());
+
+       controller().bbChanged(false);
+}
+
+
+void FormExternal::widthUnitChanged()
+{
+       if (fl_get_choice(scale_->choice_width) == 1)
+               return;
+
+       bool useHeight = fl_get_choice(scale_->choice_width) > 1;
+
+//     if (useHeight)
+//             widthED->setValidator(unsignedLengthValidator(widthED));
+//     else
+//             widthED->setValidator(new QDoubleValidator(0, 1000, 2, widthED));
+
+       setEnabled(scale_->input_height, useHeight);
+       setEnabled(scale_->choice_height, useHeight);
+}
+
+} // namespace frontend
+} // namespace lyx