2 * FormGraphics Interface Class Implementation
6 * * Handle the case when the buffer is read-only.
7 * Initial work is done, if we are read-only the ok/cancel are
8 * disabled. Probably we need to find a better way to deal with it.
13 #pragma implementation
18 #include "lyx_gui_misc.h"
20 #include FORMS_H_LOCATION
22 #include "xform_macros.h"
23 #include "input_validators.h"
24 #include "FormGraphics.h"
25 #include "form_graphics.h"
28 #include "BufferView.h"
30 #include "debug.h" // for lyxerr
32 #include "support/lstrings.h" // for strToDbl & tostr
33 #include "support/FileInfo.h" // for FileInfo
34 #include "filedlg.h" // for LyXFileDlg
35 #include "support/filetools.h" // for AddName
36 #include "insets/insetgraphics.h"
37 #include "insets/insetgraphicsParams.h"
39 #include "RadioButtonGroup.h"
41 #ifdef ENABLE_ASSERTIONS
42 #include "support/LAssert.h"
47 C_RETURNCB(FormGraphics, WMHideCB)
48 C_GENERICCB(FormGraphics, OKCB)
49 C_GENERICCB(FormGraphics, ApplyCB)
50 C_GENERICCB(FormGraphics, CancelCB)
51 C_GENERICCB(FormGraphics, BrowseCB)
52 C_GENERICCB(FormGraphics, AdvancedOptionsCB)
53 C_GENERICCB(FormGraphics, InputCB)
56 FormGraphics::FormGraphics(LyXView * lv, Dialogs * d)
57 : dialog_(0), lv_(lv), d_(d), inset_(0),
58 // The buttons c-tor values are the number of buttons we use
59 // This is only to reduce memory waste.
60 widthButtons(5), heightButtons(4), displayButtons(4),
64 // let the dialog be shown
65 // This is a permanent connection so we won't bother
66 // storing a copy because we won't be disconnecting.
67 d->showGraphics.connect(slot(this, &FormGraphics::showDialog));
71 FormGraphics::~FormGraphics()
77 void FormGraphics::build()
79 dialog_ = build_graphics();
80 #ifdef ENABLE_ASSERTIONS
86 // This is the place to add settings of the dialog that did not go
89 // Set the input widgets to issue a callback to input() whenever
90 // they change, so we can verify their content.
91 fl_set_input_return(dialog_->input_width,
93 fl_set_input_return(dialog_->input_height,
95 fl_set_input_return(dialog_->input_filename,
97 // fl_set_input_return(dialog_->input_rotate_angle,
98 // FL_RETURN_CHANGED);
100 // Set the maximum characters that can be written in the input texts.
101 fl_set_input_maxchars(dialog_->input_width, WIDTH_MAXDIGITS);
102 fl_set_input_maxchars(dialog_->input_height, HEIGHT_MAXDIGITS);
103 fl_set_input_maxchars(dialog_->input_filename, FILENAME_MAXCHARS);
104 fl_set_input_maxchars(dialog_->input_rotate_angle, ROTATE_MAXCHARS);
106 // Set input filter on width and height to make them accept only
108 fl_set_input_filter(dialog_->input_width,
109 fl_unsigned_int_filter);
110 fl_set_input_filter(dialog_->input_height,
111 fl_unsigned_int_filter);
114 // Add the widgets of the width radio buttons to their group
115 widthButtons.reset();
116 widthButtons.registerRadioButton(dialog_->radio_width_default,
117 InsetGraphicsParams::DEFAULT_SIZE);
118 widthButtons.registerRadioButton(dialog_->radio_width_cm,
119 InsetGraphicsParams::CM);
120 widthButtons.registerRadioButton(dialog_->radio_width_inch,
121 InsetGraphicsParams::INCH);
122 widthButtons.registerRadioButton(dialog_->radio_width_percent_page,
123 InsetGraphicsParams::PERCENT_PAGE);
124 widthButtons.registerRadioButton(dialog_->radio_width_percent_column,
125 InsetGraphicsParams::PERCENT_COLUMN);
127 // Add the widgets of the height radio buttons to their group
128 heightButtons.reset();
129 heightButtons.registerRadioButton(dialog_->radio_height_default,
130 InsetGraphicsParams::DEFAULT_SIZE);
131 heightButtons.registerRadioButton(dialog_->radio_height_cm,
132 InsetGraphicsParams::CM);
133 heightButtons.registerRadioButton(dialog_->radio_height_inch,
134 InsetGraphicsParams::INCH);
135 heightButtons.registerRadioButton(dialog_->radio_height_percent_page,
136 InsetGraphicsParams::PERCENT_PAGE);
138 // Add the widgets of the display radio buttons to their group
139 displayButtons.reset();
140 displayButtons.registerRadioButton(dialog_->radio_display_color,
141 InsetGraphicsParams::COLOR);
142 displayButtons.registerRadioButton(dialog_->radio_display_grayscale,
143 InsetGraphicsParams::GRAYSCALE);
144 displayButtons.registerRadioButton(dialog_->radio_display_monochrome,
145 InsetGraphicsParams::MONOCHROME);
146 displayButtons.registerRadioButton(dialog_->radio_no_display,
147 InsetGraphicsParams::NONE);
149 // Connect a signal to hide the window when the window manager orders it.
150 fl_set_form_atclose(dialog_->form_graphics,
151 C_FormGraphicsWMHideCB, 0);
154 void FormGraphics::show()
156 // If the dialog doesn't exist yet, build it.
161 // Update the form with the data from the inset.
164 // If the form is visible
165 if (dialog_->form_graphics->visible) {
167 fl_raise_form(dialog_->form_graphics);
169 // Otherwise (invisible), show it.
170 fl_show_form(dialog_->form_graphics,
175 // And connect the signals 'updateBufferDependent',
176 // 'hideBufferDependent' and 'hideGraphics'.
177 u_ = d_->updateBufferDependent.connect(slot(this,
178 &FormGraphics::update));
179 h_ = d_->hideBufferDependent.connect(slot(this,
180 &FormGraphics::hide));
184 void FormGraphics::showDialog(InsetGraphics* inset)
186 #ifdef ENABLE_ASSERTIONS
190 // If we are connected to another inset, disconnect.
197 ih_ = inset_->hide.connect(slot(this, &FormGraphics::hide));
203 void FormGraphics::hide()
205 // If the dialog exists, and the form is allocated and visible.
207 && dialog_->form_graphics
208 && dialog_->form_graphics->visible) {
210 fl_hide_form(dialog_->form_graphics);
212 // And disconnect the signals.
220 // Most of the time, the dialog is not needed anymore, we'll free it
221 // now to save memory.
226 void FormGraphics::free()
228 // hide() will disconnect the signals so we need not worry about them.
230 if (dialog_->form_graphics) {
231 // If the dialog is visible, hide it.
232 if (dialog_->form_graphics->visible) {
236 // Remove all associations for the radio buttons
237 widthButtons.reset();
238 heightButtons.reset();
239 displayButtons.reset();
242 fl_free_form(dialog_->form_graphics);
250 void FormGraphics::apply()
252 #ifdef ENABLE_ASSERTIONS
258 // Take all dialog details and insert them to the inset.
260 // Create the parameters structure and fill the data from the dialog.
261 InsetGraphicsParams igp;
263 igp.filename = fl_get_input(dialog_->input_filename);
265 igp.display = static_cast<InsetGraphicsParams::DisplayType>
266 (displayButtons.getButton());
268 igp.widthResize = static_cast<InsetGraphicsParams::Resize>
269 (widthButtons.getButton());
270 igp.widthSize = strToDbl(fl_get_input(dialog_->input_width));
272 igp.heightResize = static_cast<InsetGraphicsParams::Resize>
273 (heightButtons.getButton());
274 igp.heightSize = strToDbl(fl_get_input(dialog_->input_height));
276 igp.rotateAngle = strToInt(fl_get_input(dialog_->input_rotate_angle));
277 if (igp.rotateAngle >= 360)
278 igp.rotateAngle = igp.rotateAngle % 360;
279 if (igp.rotateAngle <= -360)
280 igp.rotateAngle = - ((-igp.rotateAngle) % 360);
282 igp.subcaption = fl_get_button(dialog_->check_subcaption);
283 igp.subcaptionText = fl_get_input(dialog_->input_subcaption);
285 igp.inlineFigure = fl_get_button(dialog_->check_inline);
287 #ifdef ENABLE_ASSERTIONS
291 // Set the parameters in the inset, it also returns true if the new
292 // parameters are different from what was in the inset already.
293 bool changed = inset_->setParams(igp);
295 // Tell LyX we've got a change, and mark the document dirty, if it changed.
296 lv_->view()->updateInset(inset_, changed);
299 void FormGraphics::update()
301 #ifdef ENABLE_ASSERTIONS
307 // Update dialog with details from inset
308 InsetGraphicsParams igp = inset_->getParams();
310 // Update the filename input field
311 fl_set_input(dialog_->input_filename,
312 igp.filename.c_str());
314 // Update the display depth radio buttons
315 displayButtons.setButton(igp.display);
317 // Update the width radio buttons and input field
318 widthButtons.setButton(igp.widthResize);
319 fl_set_input(dialog_->input_width,
320 tostr(igp.widthSize).c_str());
322 // Update the height radio buttons and input field
323 heightButtons.setButton(igp.heightResize);
324 fl_set_input(dialog_->input_height,
325 tostr(igp.heightSize).c_str());
327 // Update the rotate angle
328 fl_set_input(dialog_->input_rotate_angle,
329 tostr(igp.rotateAngle).c_str());
331 // Update the subcaption check button and input field
332 fl_set_button(dialog_->check_subcaption,
334 fl_set_input(dialog_->input_subcaption,
335 igp.subcaptionText.c_str());
337 // Update the inline figure check button
338 fl_set_button(dialog_->check_inline,
341 // Now make sure that the buttons are set correctly.
345 void FormGraphics::input()
347 // Put verifications that the dialog shows some sane values,
348 // if not disallow clicking on ok/apply.
349 // Possibly use a label in the bottom of the dialog to give the reason.
351 // Is all input boxes convey a valid meaning?
354 // Things that we check (meaning they are incorrect states):
355 // 1. No filename specified.
356 // 2. Width radio button is not Default and width text is not a number.
357 // 3. Height radio button is not Default and height text is a not a number
359 // Note: radio button default means that the user asks for the image
360 // to be included as is with no size change, in this case we don't need
361 // any width or height.
363 // We verify now that there is a filename, it exists, it's a file
364 // and it's readable.
365 string filename = fl_get_input(dialog_->input_filename);
366 FileInfo file(filename);
375 // Width radio button not default and no number.
376 if (!fl_get_button(dialog_->radio_width_default)
377 && strToDbl(fl_get_input(dialog_->input_width)) <= 0.0) {
382 // Height radio button not default and no number.
383 if (!fl_get_button(dialog_->radio_height_default)
384 && strToDbl(fl_get_input(dialog_->input_height)) <= 0.0) {
390 // Now set the buttons to the correct state.
391 if (inputOK && ! lv_->buffer()->isReadonly()) {
392 fl_activate_object(dialog_->button_ok);
393 fl_activate_object(dialog_->button_apply);
394 fl_set_object_lcol(dialog_->button_ok, FL_BLACK);
395 fl_set_object_lcol(dialog_->button_apply, FL_BLACK);
397 fl_deactivate_object(dialog_->button_ok);
398 fl_deactivate_object(dialog_->button_apply);
399 fl_set_object_lcol(dialog_->button_ok, FL_INACTIVE);
400 fl_set_object_lcol(dialog_->button_apply, FL_INACTIVE);
405 // We need these in the file browser.
406 extern string system_lyxdir;
407 extern string user_lyxdir;
408 //extern string system_tempdir;
410 // Need to move this to the form_graphics
411 string FormGraphics::browseFile(string const & filename)
413 if (! filename.empty() )
414 last_image_path = OnlyPath(filename);
416 // Does user clipart directory exist?
417 string bufclip = AddName (user_lyxdir, "clipart");
418 FileInfo fileInfo(bufclip);
419 if (!(fileInfo.isOK() && fileInfo.isDir()))
420 // No - bail out to system clipart directory
421 bufclip = AddName (system_lyxdir, "clipart");
424 fileDlg.SetButton(0, _("Clipart"), bufclip);
429 string p = fileDlg.Select(_("Graphics"),
431 "*(ps|png)", filename);
433 if (p.empty()) return p;
435 last_image_path = OnlyPath(p);
437 if (p.find_first_of("#~$% ") != string::npos) {
438 WriteAlert(_("Filename can't contain any "
439 "of these characters:"),
440 // xgettext:no-c-format
441 _("space, '#', '~', '$' or '%'."));
452 void FormGraphics::browse()
454 // Get the filename from the dialog
455 string filename = fl_get_input(dialog_->input_filename);
457 // Show the file browser dialog
458 string new_filename = browseFile(filename);
460 // Save the filename to the dialog
461 if (new_filename != filename && ! new_filename.empty()) {
462 fl_set_input(dialog_->input_filename,
463 new_filename.c_str());
464 // The above set input doesn't cause an input event so we do
465 // it manually. Otherwise the user needs to cause an input event
466 // to get the ok/apply buttons to be activated.
472 int FormGraphics::WMHideCB(FL_FORM * form, void *)
474 // Ensure that the signal h is disconnected even if the
475 // window manager is used to close the dialog.
476 FormGraphics * pre = static_cast<FormGraphics*>(form->u_vdata);
482 void FormGraphics::OKCB(FL_OBJECT * ob, long)
484 FormGraphics * pre = static_cast<FormGraphics*>(ob->form->u_vdata);
489 void FormGraphics::ApplyCB(FL_OBJECT * ob, long)
491 FormGraphics * pre = static_cast<FormGraphics*>(ob->form->u_vdata);
495 void FormGraphics::CancelCB(FL_OBJECT * ob, long)
497 FormGraphics * pre = static_cast<FormGraphics*>(ob->form->u_vdata);
501 void FormGraphics::BrowseCB(FL_OBJECT * ob, long)
503 FormGraphics * pre = static_cast<FormGraphics*>(ob->form->u_vdata);
507 void FormGraphics::AdvancedOptionsCB(FL_OBJECT * /* ob */, long)
509 // FormGraphics * pre = static_cast<FormGraphics*>(ob->form->u_vdata);
510 // pre->showAdvancedOptions();
511 lyxerr << "Advanced Options button depressed, "
512 "show advanced options dialog"
516 void FormGraphics::InputCB(FL_OBJECT * ob, long)
518 FormGraphics * pre = static_cast<FormGraphics*>(ob->form->u_vdata);