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
17 #include "lyx_gui_misc.h"
19 #include FORMS_H_LOCATION
21 #include "xform_macros.h"
22 #include "input_validators.h"
23 #include "FormGraphics.h"
24 #include "form_graphics.h"
27 #include "BufferView.h"
29 #include "debug.h" // for lyxerr
31 #include "support/lstrings.h" // for strToDbl & tostr
32 #include "support/FileInfo.h" // for FileInfo
33 #include "filedlg.h" // for LyXFileDlg
34 #include "support/filetools.h" // for AddName
35 #include "insets/insetgraphics.h"
36 #include "insets/insetgraphicsParams.h"
38 #include "RadioButtonGroup.h"
40 #ifdef ENABLE_ASSERTIONS
41 #include "support/LAssert.h"
46 C_RETURNCB(FormGraphics, WMHideCB)
47 C_GENERICCB(FormGraphics, OKCB)
48 C_GENERICCB(FormGraphics, ApplyCB)
49 C_GENERICCB(FormGraphics, CancelCB)
50 C_GENERICCB(FormGraphics, BrowseCB)
51 C_GENERICCB(FormGraphics, AdvancedOptionsCB)
52 C_GENERICCB(FormGraphics, InputCB)
55 FormGraphics::FormGraphics(LyXView * lv, Dialogs * d)
56 : dialog_(0), lv_(lv), d_(d), inset_(0),
57 // The buttons c-tor values are the number of buttons we use
58 // This is only to reduce memory waste.
59 widthButtons(5), heightButtons(4), displayButtons(4),
63 // let the dialog be shown
64 // This is a permanent connection so we won't bother
65 // storing a copy because we won't be disconnecting.
66 d->showGraphics.connect(slot(this, &FormGraphics::showDialog));
70 FormGraphics::~FormGraphics()
76 void FormGraphics::build()
78 dialog_ = build_graphics();
79 #ifdef ENABLE_ASSERTIONS
85 // This is the place to add settings of the dialog that did not go
88 // Set the input widgets to issue a callback to input() whenever
89 // they change, so we can verify their content.
90 fl_set_input_return(dialog_->input_width,
92 fl_set_input_return(dialog_->input_height,
94 fl_set_input_return(dialog_->input_filename,
96 // fl_set_input_return(dialog_->input_rotate_angle,
97 // FL_RETURN_CHANGED);
99 // Set the maximum characters that can be written in the input texts.
100 fl_set_input_maxchars(dialog_->input_width, WIDTH_MAXDIGITS);
101 fl_set_input_maxchars(dialog_->input_height, HEIGHT_MAXDIGITS);
102 fl_set_input_maxchars(dialog_->input_filename, FILENAME_MAXCHARS);
103 fl_set_input_maxchars(dialog_->input_rotate_angle, ROTATE_MAXCHARS);
105 // Set input filter on width and height to make them accept only
107 fl_set_input_filter(dialog_->input_width,
108 fl_unsigned_int_filter);
109 fl_set_input_filter(dialog_->input_height,
110 fl_unsigned_int_filter);
113 // Add the widgets of the width radio buttons to their group
114 widthButtons.reset();
115 widthButtons.registerRadioButton(dialog_->radio_width_default,
116 InsetGraphicsParams::DEFAULT_SIZE);
117 widthButtons.registerRadioButton(dialog_->radio_width_cm,
118 InsetGraphicsParams::CM);
119 widthButtons.registerRadioButton(dialog_->radio_width_inch,
120 InsetGraphicsParams::INCH);
121 widthButtons.registerRadioButton(dialog_->radio_width_percent_page,
122 InsetGraphicsParams::PERCENT_PAGE);
123 widthButtons.registerRadioButton(dialog_->radio_width_percent_column,
124 InsetGraphicsParams::PERCENT_COLUMN);
126 // Add the widgets of the height radio buttons to their group
127 heightButtons.reset();
128 heightButtons.registerRadioButton(dialog_->radio_height_default,
129 InsetGraphicsParams::DEFAULT_SIZE);
130 heightButtons.registerRadioButton(dialog_->radio_height_cm,
131 InsetGraphicsParams::CM);
132 heightButtons.registerRadioButton(dialog_->radio_height_inch,
133 InsetGraphicsParams::INCH);
134 heightButtons.registerRadioButton(dialog_->radio_height_percent_page,
135 InsetGraphicsParams::PERCENT_PAGE);
137 // Add the widgets of the display radio buttons to their group
138 displayButtons.reset();
139 displayButtons.registerRadioButton(dialog_->radio_display_color,
140 InsetGraphicsParams::COLOR);
141 displayButtons.registerRadioButton(dialog_->radio_display_grayscale,
142 InsetGraphicsParams::GRAYSCALE);
143 displayButtons.registerRadioButton(dialog_->radio_display_monochrome,
144 InsetGraphicsParams::MONOCHROME);
145 displayButtons.registerRadioButton(dialog_->radio_no_display,
146 InsetGraphicsParams::NONE);
148 // Connect a signal to hide the window when the window manager orders it.
149 fl_set_form_atclose(dialog_->form_graphics,
150 C_FormGraphicsWMHideCB, 0);
153 void FormGraphics::show()
155 // If the dialog doesn't exist yet, build it.
160 // Update the form with the data from the inset.
163 // If the form is visible
164 if (dialog_->form_graphics->visible) {
166 fl_raise_form(dialog_->form_graphics);
168 // Otherwise (invisible), show it.
169 fl_show_form(dialog_->form_graphics,
174 // And connect the signals 'updateBufferDependent',
175 // 'hideBufferDependent' and 'hideGraphics'.
176 u_ = d_->updateBufferDependent.connect(slot(this,
177 &FormGraphics::update));
178 h_ = d_->hideBufferDependent.connect(slot(this,
179 &FormGraphics::hide));
183 void FormGraphics::showDialog(InsetGraphics* inset)
185 #ifdef ENABLE_ASSERTIONS
189 // If we are connected to another inset, disconnect.
196 ih_ = inset_->hide.connect(slot(this, &FormGraphics::hide));
202 void FormGraphics::hide()
204 // If the dialog exists, and the form is allocated and visible.
206 && dialog_->form_graphics
207 && dialog_->form_graphics->visible) {
209 fl_hide_form(dialog_->form_graphics);
211 // And disconnect the signals.
219 // Most of the time, the dialog is not needed anymore, we'll free it
220 // now to save memory.
225 void FormGraphics::free()
227 // hide() will disconnect the signals so we need not worry about them.
229 if (dialog_->form_graphics) {
230 // If the dialog is visible, hide it.
231 if (dialog_->form_graphics->visible) {
235 // Remove all associations for the radio buttons
236 widthButtons.reset();
237 heightButtons.reset();
238 displayButtons.reset();
241 fl_free_form(dialog_->form_graphics);
249 void FormGraphics::apply()
251 #ifdef ENABLE_ASSERTIONS
257 // Take all dialog details and insert them to the inset.
259 // Create the parameters structure and fill the data from the dialog.
260 InsetGraphicsParams igp;
262 igp.filename = fl_get_input(dialog_->input_filename);
264 igp.display = static_cast<InsetGraphicsParams::DisplayType>
265 (displayButtons.getButton());
267 igp.widthResize = static_cast<InsetGraphicsParams::Resize>
268 (widthButtons.getButton());
269 igp.widthSize = strToDbl(fl_get_input(dialog_->input_width));
271 igp.heightResize = static_cast<InsetGraphicsParams::Resize>
272 (heightButtons.getButton());
273 igp.heightSize = strToDbl(fl_get_input(dialog_->input_height));
275 igp.rotateAngle = strToInt(fl_get_input(dialog_->input_rotate_angle));
276 if (igp.rotateAngle >= 360)
277 igp.rotateAngle = igp.rotateAngle % 360;
278 if (igp.rotateAngle <= -360)
279 igp.rotateAngle = - ((-igp.rotateAngle) % 360);
281 igp.subcaption = fl_get_button(dialog_->check_subcaption);
282 igp.subcaptionText = fl_get_input(dialog_->input_subcaption);
284 igp.inlineFigure = fl_get_button(dialog_->check_inline);
286 #ifdef ENABLE_ASSERTIONS
290 // Set the parameters in the inset, it also returns true if the new
291 // parameters are different from what was in the inset already.
292 bool changed = inset_->setParams(igp);
294 // Tell LyX we've got a change, and mark the document dirty, if it changed.
295 lv_->view()->updateInset(inset_, changed);
298 void FormGraphics::update()
300 #ifdef ENABLE_ASSERTIONS
306 // Update dialog with details from inset
307 InsetGraphicsParams igp = inset_->getParams();
309 // Update the filename input field
310 fl_set_input(dialog_->input_filename,
311 igp.filename.c_str());
313 // Update the display depth radio buttons
314 displayButtons.setButton(igp.display);
316 // Update the width radio buttons and input field
317 widthButtons.setButton(igp.widthResize);
318 fl_set_input(dialog_->input_width,
319 tostr(igp.widthSize).c_str());
321 // Update the height radio buttons and input field
322 heightButtons.setButton(igp.heightResize);
323 fl_set_input(dialog_->input_height,
324 tostr(igp.heightSize).c_str());
326 // Update the rotate angle
327 fl_set_input(dialog_->input_rotate_angle,
328 tostr(igp.rotateAngle).c_str());
330 // Update the subcaption check button and input field
331 fl_set_button(dialog_->check_subcaption,
333 fl_set_input(dialog_->input_subcaption,
334 igp.subcaptionText.c_str());
336 // Update the inline figure check button
337 fl_set_button(dialog_->check_inline,
340 // Now make sure that the buttons are set correctly.
344 void FormGraphics::input()
346 // Put verifications that the dialog shows some sane values,
347 // if not disallow clicking on ok/apply.
348 // Possibly use a label in the bottom of the dialog to give the reason.
350 // Is all input boxes convey a valid meaning?
353 // Things that we check (meaning they are incorrect states):
354 // 1. No filename specified.
355 // 2. Width radio button is not Default and width text is not a number.
356 // 3. Height radio button is not Default and height text is a not a number
358 // Note: radio button default means that the user asks for the image
359 // to be included as is with no size change, in this case we don't need
360 // any width or height.
362 // We verify now that there is a filename, it exists, it's a file
363 // and it's readable.
364 string filename = fl_get_input(dialog_->input_filename);
365 FileInfo file(filename);
374 // Width radio button not default and no number.
375 if (!fl_get_button(dialog_->radio_width_default)
376 && strToDbl(fl_get_input(dialog_->input_width)) <= 0.0) {
381 // Height radio button not default and no number.
382 if (!fl_get_button(dialog_->radio_height_default)
383 && strToDbl(fl_get_input(dialog_->input_height)) <= 0.0) {
389 // Now set the buttons to the correct state.
390 if (inputOK && ! lv_->buffer()->isReadonly()) {
391 fl_activate_object(dialog_->button_ok);
392 fl_activate_object(dialog_->button_apply);
393 fl_set_object_lcol(dialog_->button_ok, FL_BLACK);
394 fl_set_object_lcol(dialog_->button_apply, FL_BLACK);
396 fl_deactivate_object(dialog_->button_ok);
397 fl_deactivate_object(dialog_->button_apply);
398 fl_set_object_lcol(dialog_->button_ok, FL_INACTIVE);
399 fl_set_object_lcol(dialog_->button_apply, FL_INACTIVE);
404 // We need these in the file browser.
405 extern string system_lyxdir;
406 extern string user_lyxdir;
407 //extern string system_tempdir;
409 // Need to move this to the form_graphics
410 string FormGraphics::browseFile(string const & filename)
412 if (! filename.empty() )
413 last_image_path = OnlyPath(filename);
415 // Does user clipart directory exist?
416 string bufclip = AddName (user_lyxdir, "clipart");
417 FileInfo fileInfo(bufclip);
418 if (!(fileInfo.isOK() && fileInfo.isDir()))
419 // No - bail out to system clipart directory
420 bufclip = AddName (system_lyxdir, "clipart");
423 fileDlg.SetButton(0, _("Clipart"), bufclip);
428 string p = fileDlg.Select(_("Graphics"),
430 "*(ps|png)", filename);
432 if (p.empty()) return p;
434 last_image_path = OnlyPath(p);
436 if (p.find_first_of("#~$% ") != string::npos) {
437 WriteAlert(_("Filename can't contain any "
438 "of these characters:"),
439 // xgettext:no-c-format
440 _("space, '#', '~', '$' or '%'."));
451 void FormGraphics::browse()
453 // Get the filename from the dialog
454 string filename = fl_get_input(dialog_->input_filename);
456 // Show the file browser dialog
457 string new_filename = browseFile(filename);
459 // Save the filename to the dialog
460 if (new_filename != filename && ! new_filename.empty()) {
461 fl_set_input(dialog_->input_filename,
462 new_filename.c_str());
463 // The above set input doesn't cause an input event so we do
464 // it manually. Otherwise the user needs to cause an input event
465 // to get the ok/apply buttons to be activated.
471 int FormGraphics::WMHideCB(FL_FORM * form, void *)
473 // Ensure that the signal h is disconnected even if the
474 // window manager is used to close the dialog.
475 FormGraphics * pre = static_cast<FormGraphics*>(form->u_vdata);
481 void FormGraphics::OKCB(FL_OBJECT * ob, long)
483 FormGraphics * pre = static_cast<FormGraphics*>(ob->form->u_vdata);
488 void FormGraphics::ApplyCB(FL_OBJECT * ob, long)
490 FormGraphics * pre = static_cast<FormGraphics*>(ob->form->u_vdata);
494 void FormGraphics::CancelCB(FL_OBJECT * ob, long)
496 FormGraphics * pre = static_cast<FormGraphics*>(ob->form->u_vdata);
500 void FormGraphics::BrowseCB(FL_OBJECT * ob, long)
502 FormGraphics * pre = static_cast<FormGraphics*>(ob->form->u_vdata);
506 void FormGraphics::AdvancedOptionsCB(FL_OBJECT * /* ob */, long)
508 // FormGraphics * pre = static_cast<FormGraphics*>(ob->form->u_vdata);
509 // pre->showAdvancedOptions();
510 lyxerr << "Advanced Options button depressed, "
511 "show advanced options dialog"
515 void FormGraphics::InputCB(FL_OBJECT * ob, long)
517 FormGraphics * pre = static_cast<FormGraphics*>(ob->form->u_vdata);