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.
15 #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 #include "support/LAssert.h"
45 C_RETURNCB(FormGraphics, WMHideCB)
46 C_GENERICCB(FormGraphics, OKCB)
47 C_GENERICCB(FormGraphics, ApplyCB)
48 C_GENERICCB(FormGraphics, CancelCB)
49 C_GENERICCB(FormGraphics, BrowseCB)
50 C_GENERICCB(FormGraphics, AdvancedOptionsCB)
51 C_GENERICCB(FormGraphics, InputCB)
54 FormGraphics::FormGraphics(LyXView * lv, Dialogs * d)
55 : dialog_(0), lv_(lv), d_(d), inset_(0),
56 // The buttons c-tor values are the number of buttons we use
57 // This is only to reduce memory waste.
58 widthButtons(5), heightButtons(4), displayButtons(4),
62 // let the dialog be shown
63 // This is a permanent connection so we won't bother
64 // storing a copy because we won't be disconnecting.
65 d->showGraphics.connect(slot(this, &FormGraphics::showDialog));
69 FormGraphics::~FormGraphics()
75 void FormGraphics::build()
77 dialog_ = build_graphics();
82 // This is the place to add settings of the dialog that did not go
85 // Set the input widgets to issue a callback to input() whenever
86 // they change, so we can verify their content.
87 fl_set_input_return (dialog_->input_width,
89 fl_set_input_return (dialog_->input_height,
91 fl_set_input_return (dialog_->input_filename,
93 // fl_set_input_return(dialog_->input_rotate_angle,
94 // FL_RETURN_CHANGED);
96 // Set the maximum characters that can be written in the input texts.
97 fl_set_input_maxchars(dialog_->input_width, WIDTH_MAXDIGITS);
98 fl_set_input_maxchars(dialog_->input_height, HEIGHT_MAXDIGITS);
99 fl_set_input_maxchars(dialog_->input_filename, FILENAME_MAXCHARS);
100 fl_set_input_maxchars(dialog_->input_rotate_angle, ROTATE_MAXCHARS);
102 // Set input filter on width and height to make them accept only
104 fl_set_input_filter(dialog_->input_width,
105 fl_unsigned_int_filter);
106 fl_set_input_filter(dialog_->input_height,
107 fl_unsigned_int_filter);
110 // Add the widgets of the width radio buttons to their group
111 widthButtons.reset();
112 widthButtons.registerRadioButton(dialog_->radio_width_default,
113 InsetGraphicsParams::DEFAULT_SIZE);
114 widthButtons.registerRadioButton(dialog_->radio_width_cm,
115 InsetGraphicsParams::CM);
116 widthButtons.registerRadioButton(dialog_->radio_width_inch,
117 InsetGraphicsParams::INCH);
118 widthButtons.registerRadioButton(dialog_->radio_width_percent_page,
119 InsetGraphicsParams::PERCENT_PAGE);
120 widthButtons.registerRadioButton(dialog_->radio_width_percent_column,
121 InsetGraphicsParams::PERCENT_COLUMN);
123 // Add the widgets of the height radio buttons to their group
124 heightButtons.reset();
125 heightButtons.registerRadioButton(dialog_->radio_height_default,
126 InsetGraphicsParams::DEFAULT_SIZE);
127 heightButtons.registerRadioButton(dialog_->radio_height_cm,
128 InsetGraphicsParams::CM);
129 heightButtons.registerRadioButton(dialog_->radio_height_inch,
130 InsetGraphicsParams::INCH);
131 heightButtons.registerRadioButton(dialog_->radio_height_percent_page,
132 InsetGraphicsParams::PERCENT_PAGE);
134 // Add the widgets of the display radio buttons to their group
135 displayButtons.reset();
136 displayButtons.registerRadioButton(dialog_->radio_display_color,
137 InsetGraphicsParams::COLOR);
138 displayButtons.registerRadioButton(dialog_->radio_display_grayscale,
139 InsetGraphicsParams::GRAYSCALE);
140 displayButtons.registerRadioButton(dialog_->radio_display_monochrome,
141 InsetGraphicsParams::MONOCHROME);
142 displayButtons.registerRadioButton(dialog_->radio_no_display,
143 InsetGraphicsParams::NONE);
145 // Connect a signal to hide the window when the window manager orders it.
146 fl_set_form_atclose(dialog_->form,
147 C_FormGraphicsWMHideCB, 0);
150 void FormGraphics::show()
152 // If the dialog doesn't exist yet, build it.
157 // Update the form with the data from the inset.
160 // If the form is visible
161 if (dialog_->form->visible) {
163 fl_raise_form(dialog_->form);
165 // Otherwise (invisible), show it.
166 fl_show_form(dialog_->form,
171 // And connect the signals 'updateBufferDependent',
172 // 'hideBufferDependent' and 'hideGraphics'.
173 u_ = d_->updateBufferDependent.connect(slot(this,
174 &FormGraphics::update));
175 h_ = d_->hideBufferDependent.connect(slot(this,
176 &FormGraphics::hide));
180 void FormGraphics::showDialog(InsetGraphics* inset)
184 // If we are connected to another inset, disconnect.
191 ih_ = inset_->hide.connect(slot(this, &FormGraphics::hide));
197 void FormGraphics::hide()
199 // If the dialog exists, and the form is allocated and visible.
202 && dialog_->form->visible) {
204 fl_hide_form(dialog_->form);
206 // And disconnect the signals.
214 // Most of the time, the dialog is not needed anymore, we'll free it
215 // now to save memory.
220 void FormGraphics::free()
222 // Remove all associations for the radio buttons
223 widthButtons.reset();
224 heightButtons.reset();
225 displayButtons.reset();
232 void FormGraphics::apply()
236 // Take all dialog details and insert them to the inset.
238 // Create the parameters structure and fill the data from the dialog.
239 InsetGraphicsParams igp;
241 igp.filename = fl_get_input(dialog_->input_filename);
243 igp.display = static_cast < InsetGraphicsParams::DisplayType >
244 (displayButtons.getButton());
246 igp.widthResize = static_cast < InsetGraphicsParams::Resize >
247 (widthButtons.getButton());
248 igp.widthSize = strToDbl(fl_get_input(dialog_->input_width));
250 igp.heightResize = static_cast < InsetGraphicsParams::Resize >
251 (heightButtons.getButton());
252 igp.heightSize = strToDbl(fl_get_input(dialog_->input_height));
254 igp.rotateAngle = strToInt(fl_get_input(dialog_->input_rotate_angle));
255 if (igp.rotateAngle >= 360)
256 igp.rotateAngle = igp.rotateAngle % 360;
257 if (igp.rotateAngle <= -360)
258 igp.rotateAngle = - (( -igp.rotateAngle) % 360);
260 igp.subcaption = fl_get_button(dialog_->check_subcaption);
261 igp.subcaptionText = fl_get_input(dialog_->input_subcaption);
263 igp.inlineFigure = fl_get_button(dialog_->check_inline);
267 // Set the parameters in the inset, it also returns true if the new
268 // parameters are different from what was in the inset already.
269 bool changed = inset_->setParams(igp);
271 // Tell LyX we've got a change, and mark the document dirty, if it changed.
272 lv_->view()->updateInset(inset_, changed);
275 void FormGraphics::update()
279 // Update dialog with details from inset
280 InsetGraphicsParams igp = inset_->getParams();
282 // Update the filename input field
283 fl_set_input(dialog_->input_filename,
284 igp.filename.c_str());
286 // Update the display depth radio buttons
287 displayButtons.setButton(igp.display);
289 // Update the width radio buttons and input field
290 widthButtons.setButton(igp.widthResize);
291 fl_set_input(dialog_->input_width,
292 tostr(igp.widthSize).c_str());
294 // Update the height radio buttons and input field
295 heightButtons.setButton(igp.heightResize);
296 fl_set_input(dialog_->input_height,
297 tostr(igp.heightSize).c_str());
299 // Update the rotate angle
300 fl_set_input(dialog_->input_rotate_angle,
301 tostr(igp.rotateAngle).c_str());
303 // Update the subcaption check button and input field
304 fl_set_button(dialog_->check_subcaption,
306 fl_set_input(dialog_->input_subcaption,
307 igp.subcaptionText.c_str());
309 // Update the inline figure check button
310 fl_set_button(dialog_->check_inline,
313 // Now make sure that the buttons are set correctly.
317 void FormGraphics::input()
319 // Put verifications that the dialog shows some sane values,
320 // if not disallow clicking on ok/apply.
321 // Possibly use a label in the bottom of the dialog to give the reason.
323 // Is all input boxes convey a valid meaning?
326 // Things that we check (meaning they are incorrect states):
327 // 1. No filename specified.
328 // 2. Width radio button is not Default and width text is not a number.
329 // 3. Height radio button is not Default and height text is a not a number
331 // Note: radio button default means that the user asks for the image
332 // to be included as is with no size change, in this case we don't need
333 // any width or height.
335 // We verify now that there is a filename, it exists, it's a file
336 // and it's readable.
337 string filename = fl_get_input(dialog_->input_filename);
338 FileInfo file(filename);
347 // Width radio button not default and no number.
348 if (!fl_get_button(dialog_->radio_width_default)
349 && strToDbl(fl_get_input(dialog_->input_width)) <= 0.0) {
354 // Height radio button not default and no number.
355 if (!fl_get_button(dialog_->radio_height_default)
356 && strToDbl(fl_get_input(dialog_->input_height)) <= 0.0) {
362 // Now set the buttons to the correct state.
363 if (inputOK && ! lv_->buffer()->isReadonly()) {
364 fl_activate_object(dialog_->button_ok);
365 fl_activate_object(dialog_->button_apply);
366 fl_set_object_lcol(dialog_->button_ok, FL_BLACK);
367 fl_set_object_lcol(dialog_->button_apply, FL_BLACK);
369 fl_deactivate_object(dialog_->button_ok);
370 fl_deactivate_object(dialog_->button_apply);
371 fl_set_object_lcol(dialog_->button_ok, FL_INACTIVE);
372 fl_set_object_lcol(dialog_->button_apply, FL_INACTIVE);
377 // We need these in the file browser.
378 extern string system_lyxdir;
379 extern string user_lyxdir;
380 //extern string system_tempdir;
382 // Need to move this to the form_graphics
383 string FormGraphics::browseFile(string const & filename)
385 if (! filename.empty() )
386 last_image_path = OnlyPath(filename);
388 // Does user clipart directory exist?
389 string bufclip = AddName (user_lyxdir, "clipart");
390 FileInfo fileInfo(bufclip);
391 if (!(fileInfo.isOK() && fileInfo.isDir()))
392 // No - bail out to system clipart directory
393 bufclip = AddName (system_lyxdir, "clipart");
396 fileDlg.SetButton(0, _("Clipart"), bufclip);
401 string p = fileDlg.Select(_("Graphics"),
403 "*(ps|png)", filename);
405 if (p.empty()) return p;
407 last_image_path = OnlyPath(p);
409 if (p.find_first_of("#~$% ") != string::npos) {
410 WriteAlert(_("Filename can't contain any "
411 "of these characters:"),
412 // xgettext:no-c-format
413 _("space, '#', '~', '$' or '%'."));
424 void FormGraphics::browse()
426 // Get the filename from the dialog
427 string filename = fl_get_input(dialog_->input_filename);
429 // Show the file browser dialog
430 string new_filename = browseFile(filename);
432 // Save the filename to the dialog
433 if (new_filename != filename && ! new_filename.empty()) {
434 fl_set_input(dialog_->input_filename,
435 new_filename.c_str());
436 // The above set input doesn't cause an input event so we do
437 // it manually. Otherwise the user needs to cause an input event
438 // to get the ok/apply buttons to be activated.
444 int FormGraphics::WMHideCB(FL_FORM * form, void *)
446 // Ensure that the signal h is disconnected even if the
447 // window manager is used to close the dialog.
448 FormGraphics * pre = static_cast < FormGraphics* > (form->u_vdata);
454 void FormGraphics::OKCB(FL_OBJECT * ob, long)
456 FormGraphics * pre = static_cast < FormGraphics* > (ob->form->u_vdata);
461 void FormGraphics::ApplyCB(FL_OBJECT * ob, long)
463 FormGraphics * pre = static_cast < FormGraphics* > (ob->form->u_vdata);
467 void FormGraphics::CancelCB(FL_OBJECT * ob, long)
469 FormGraphics * pre = static_cast < FormGraphics* > (ob->form->u_vdata);
473 void FormGraphics::BrowseCB(FL_OBJECT * ob, long)
475 FormGraphics * pre = static_cast < FormGraphics* > (ob->form->u_vdata);
479 void FormGraphics::AdvancedOptionsCB(FL_OBJECT * /* ob */, long)
481 // FormGraphics * pre = static_cast<FormGraphics*>(ob->form->u_vdata);
482 // pre->showAdvancedOptions();
483 lyxerr << "Advanced Options button depressed, "
484 "show advanced options dialog"
488 void FormGraphics::InputCB(FL_OBJECT * ob, long)
490 FormGraphics * pre = static_cast < FormGraphics* > (ob->form->u_vdata);