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"
44 C_RETURNCB(FormGraphics, WMHideCB)
45 C_GENERICCB(FormGraphics, OKCB)
46 C_GENERICCB(FormGraphics, ApplyCB)
47 C_GENERICCB(FormGraphics, CancelCB)
48 C_GENERICCB(FormGraphics, BrowseCB)
49 C_GENERICCB(FormGraphics, AdvancedOptionsCB)
50 C_GENERICCB(FormGraphics, InputCB)
53 FormGraphics::FormGraphics(LyXView * lv, Dialogs * d)
54 : dialog_(0), lv_(lv), d_(d), inset_(0),
55 // The buttons c-tor values are the number of buttons we use
56 // This is only to reduce memory waste.
57 widthButtons(5), heightButtons(4), displayButtons(4),
61 // let the dialog be shown
62 // This is a permanent connection so we won't bother
63 // storing a copy because we won't be disconnecting.
64 d->showGraphics.connect(slot(this, &FormGraphics::showDialog));
68 FormGraphics::~FormGraphics()
74 void FormGraphics::build()
76 dialog_ = build_graphics();
77 #ifdef ENABLE_ASSERTIONS
83 // This is the place to add settings of the dialog that did not go
86 // Set the input widgets to issue a callback to input() whenever
87 // they change, so we can verify their content.
88 fl_set_input_return(dialog_->input_width,
90 fl_set_input_return(dialog_->input_height,
92 fl_set_input_return(dialog_->input_filename,
94 // fl_set_input_return(dialog_->input_rotate_angle,
95 // FL_RETURN_CHANGED);
97 // Set the maximum characters that can be written in the input texts.
98 fl_set_input_maxchars(dialog_->input_width, WIDTH_MAXDIGITS);
99 fl_set_input_maxchars(dialog_->input_height, HEIGHT_MAXDIGITS);
100 fl_set_input_maxchars(dialog_->input_filename, FILENAME_MAXCHARS);
101 fl_set_input_maxchars(dialog_->input_rotate_angle, ROTATE_MAXCHARS);
103 // Set input filter on width and height to make them accept only
105 fl_set_input_filter(dialog_->input_width,
106 fl_unsigned_int_filter);
107 fl_set_input_filter(dialog_->input_height,
108 fl_unsigned_int_filter);
111 // Add the widgets of the width radio buttons to their group
112 widthButtons.reset();
113 widthButtons.registerRadioButton(dialog_->radio_width_default,
114 InsetGraphicsParams::DEFAULT_SIZE);
115 widthButtons.registerRadioButton(dialog_->radio_width_cm,
116 InsetGraphicsParams::CM);
117 widthButtons.registerRadioButton(dialog_->radio_width_inch,
118 InsetGraphicsParams::INCH);
119 widthButtons.registerRadioButton(dialog_->radio_width_percent_page,
120 InsetGraphicsParams::PERCENT_PAGE);
121 widthButtons.registerRadioButton(dialog_->radio_width_percent_column,
122 InsetGraphicsParams::PERCENT_COLUMN);
124 // Add the widgets of the height radio buttons to their group
125 heightButtons.reset();
126 heightButtons.registerRadioButton(dialog_->radio_height_default,
127 InsetGraphicsParams::DEFAULT_SIZE);
128 heightButtons.registerRadioButton(dialog_->radio_height_cm,
129 InsetGraphicsParams::CM);
130 heightButtons.registerRadioButton(dialog_->radio_height_inch,
131 InsetGraphicsParams::INCH);
132 heightButtons.registerRadioButton(dialog_->radio_height_percent_page,
133 InsetGraphicsParams::PERCENT_PAGE);
135 // Add the widgets of the display radio buttons to their group
136 displayButtons.reset();
137 displayButtons.registerRadioButton(dialog_->radio_display_color,
138 InsetGraphicsParams::COLOR);
139 displayButtons.registerRadioButton(dialog_->radio_display_grayscale,
140 InsetGraphicsParams::GRAYSCALE);
141 displayButtons.registerRadioButton(dialog_->radio_display_monochrome,
142 InsetGraphicsParams::MONOCHROME);
143 displayButtons.registerRadioButton(dialog_->radio_no_display,
144 InsetGraphicsParams::NONE);
146 // Connect a signal to hide the window when the window manager orders it.
147 fl_set_form_atclose(dialog_->form_graphics,
148 C_FormGraphicsWMHideCB, 0);
151 void FormGraphics::show()
153 // If the dialog doesn't exist yet, build it.
158 // Update the form with the data from the inset.
161 // If the form is visible
162 if (dialog_->form_graphics->visible) {
164 fl_raise_form(dialog_->form_graphics);
166 // Otherwise (invisible), show it.
167 fl_show_form(dialog_->form_graphics,
172 // And connect the signals 'updateBufferDependent',
173 // 'hideBufferDependent' and 'hideGraphics'.
174 u_ = d_->updateBufferDependent.connect(slot(this,
175 &FormGraphics::update));
176 h_ = d_->hideBufferDependent.connect(slot(this,
177 &FormGraphics::hide));
181 void FormGraphics::showDialog(InsetGraphics* inset)
183 #ifdef ENABLE_ASSERTIONS
187 // If we are connected to another inset, disconnect.
194 ih_ = inset_->hide.connect(slot(this, &FormGraphics::hide));
200 void FormGraphics::hide()
202 // If the dialog exists, and the form is allocated and visible.
204 && dialog_->form_graphics
205 && dialog_->form_graphics->visible) {
207 fl_hide_form(dialog_->form_graphics);
209 // And disconnect the signals.
217 // Most of the time, the dialog is not needed anymore, we'll free it
218 // now to save memory.
223 void FormGraphics::free()
225 // hide() will disconnect the signals so we need not worry about them.
227 if (dialog_->form_graphics) {
228 // If the dialog is visible, hide it.
229 if (dialog_->form_graphics->visible) {
233 // Remove all associations for the radio buttons
234 widthButtons.reset();
235 heightButtons.reset();
236 displayButtons.reset();
239 fl_free_form(dialog_->form_graphics);
247 void FormGraphics::apply()
249 #ifdef ENABLE_ASSERTIONS
255 // Take all dialog details and insert them to the inset.
257 // Create the parameters structure and fill the data from the dialog.
258 InsetGraphicsParams igp;
260 igp.filename = fl_get_input(dialog_->input_filename);
262 igp.display = displayButtons.getButton();
264 igp.widthResize = widthButtons.getButton();
265 igp.widthSize = strToDbl(fl_get_input(dialog_->input_width));
267 igp.heightResize = heightButtons.getButton();
268 igp.heightSize = strToDbl(fl_get_input(dialog_->input_height));
270 igp.rotateAngle = strToInt(fl_get_input(dialog_->input_rotate_angle));
271 if (igp.rotateAngle >= 360)
272 igp.rotateAngle = igp.rotateAngle % 360;
273 if (igp.rotateAngle <= -360)
274 igp.rotateAngle = - ((-igp.rotateAngle) % 360);
276 igp.subcaption = fl_get_button(dialog_->check_subcaption);
277 igp.subcaptionText = fl_get_input(dialog_->input_subcaption);
279 igp.inlineFigure = fl_get_button(dialog_->check_inline);
281 #ifdef ENABLE_ASSERTIONS
285 // Set the parameters in the inset, it also returns true if the new
286 // parameters are different from what was in the inset already.
287 bool changed = inset_->setParams(igp);
289 // Tell LyX we've got a change, and mark the document dirty, if it changed.
290 lv_->view()->updateInset(inset_, changed);
293 void FormGraphics::update()
295 #ifdef ENABLE_ASSERTIONS
301 // Update dialog with details from inset
302 InsetGraphicsParams igp = inset_->getParams();
304 // Update the filename input field
305 fl_set_input(dialog_->input_filename,
306 igp.filename.c_str());
308 // Update the display depth radio buttons
309 displayButtons.setButton(igp.display);
311 // Update the width radio buttons and input field
312 widthButtons.setButton(igp.widthResize);
313 fl_set_input(dialog_->input_width,
314 tostr(igp.widthSize).c_str());
316 // Update the height radio buttons and input field
317 heightButtons.setButton(igp.heightResize);
318 fl_set_input(dialog_->input_height,
319 tostr(igp.heightSize).c_str());
321 // Update the rotate angle
322 fl_set_input(dialog_->input_rotate_angle,
323 tostr(igp.rotateAngle).c_str());
325 // Update the subcaption check button and input field
326 fl_set_button(dialog_->check_subcaption,
328 fl_set_input(dialog_->input_subcaption,
329 igp.subcaptionText.c_str());
331 // Update the inline figure check button
332 fl_set_button(dialog_->check_inline,
335 // Now make sure that the buttons are set correctly.
339 void FormGraphics::input()
341 // Put verifications that the dialog shows some sane values,
342 // if not disallow clicking on ok/apply.
343 // Possibly use a label in the bottom of the dialog to give the reason.
345 // Is all input boxes convey a valid meaning?
348 // Things that we check (meaning they are incorrect states):
349 // 1. No filename specified.
350 // 2. Width radio button is not Default and width text is not a number.
351 // 3. Height radio button is not Default and height text is a not a number
353 // Note: radio button default means that the user asks for the image
354 // to be included as is with no size change, in this case we don't need
355 // any width or height.
357 // We verify now that there is a filename, it exists, it's a file
358 // and it's readable.
359 string filename = fl_get_input(dialog_->input_filename);
360 FileInfo file(filename);
369 // Width radio button not default and no number.
370 if (!fl_get_button(dialog_->radio_width_default)
371 && strToDbl(fl_get_input(dialog_->input_width)) <= 0.0) {
376 // Height radio button not default and no number.
377 if (!fl_get_button(dialog_->radio_height_default)
378 && strToDbl(fl_get_input(dialog_->input_height)) <= 0.0) {
384 // Now set the buttons to the correct state.
385 if (inputOK && ! lv_->buffer()->isReadonly()) {
386 fl_activate_object(dialog_->button_ok);
387 fl_activate_object(dialog_->button_apply);
388 fl_set_object_lcol(dialog_->button_ok, FL_BLACK);
389 fl_set_object_lcol(dialog_->button_apply, FL_BLACK);
391 fl_deactivate_object(dialog_->button_ok);
392 fl_deactivate_object(dialog_->button_apply);
393 fl_set_object_lcol(dialog_->button_ok, FL_INACTIVE);
394 fl_set_object_lcol(dialog_->button_apply, FL_INACTIVE);
399 // We need these in the file browser.
400 extern string system_lyxdir;
401 extern string user_lyxdir;
402 //extern string system_tempdir;
404 // Need to move this to the form_graphics
405 string FormGraphics::browseFile(string const & filename)
407 if (! filename.empty() )
408 last_image_path = OnlyPath(filename);
410 // Does user clipart directory exist?
411 string bufclip = AddName (user_lyxdir, "clipart");
412 FileInfo fileInfo(bufclip);
413 if (!(fileInfo.isOK() && fileInfo.isDir()))
414 // No - bail out to system clipart directory
415 bufclip = AddName (system_lyxdir, "clipart");
418 fileDlg.SetButton(0, _("Clipart"), bufclip);
423 string p = fileDlg.Select(_("Graphics"),
425 "*(ps|png)", filename);
427 if (p.empty()) return p;
429 last_image_path = OnlyPath(p);
431 if (p.find_first_of("#~$% ") != string::npos) {
432 WriteAlert(_("Filename can't contain any "
433 "of these characters:"),
434 // xgettext:no-c-format
435 _("space, '#', '~', '$' or '%'."));
446 void FormGraphics::browse()
448 // Get the filename from the dialog
449 string filename = fl_get_input(dialog_->input_filename);
451 // Show the file browser dialog
452 string new_filename = browseFile(filename);
454 // Save the filename to the dialog
455 if (new_filename != filename && ! new_filename.empty()) {
456 fl_set_input(dialog_->input_filename,
457 new_filename.c_str());
458 // The above set input doesn't cause an input event so we do
459 // it manually. Otherwise the user needs to cause an input event
460 // to get the ok/apply buttons to be activated.
466 int FormGraphics::WMHideCB(FL_FORM * form, void *)
468 // Ensure that the signal h is disconnected even if the
469 // window manager is used to close the dialog.
470 FormGraphics * pre = static_cast<FormGraphics*>(form->u_vdata);
476 void FormGraphics::OKCB(FL_OBJECT * ob, long)
478 FormGraphics * pre = static_cast<FormGraphics*>(ob->form->u_vdata);
483 void FormGraphics::ApplyCB(FL_OBJECT * ob, long)
485 FormGraphics * pre = static_cast<FormGraphics*>(ob->form->u_vdata);
489 void FormGraphics::CancelCB(FL_OBJECT * ob, long)
491 FormGraphics * pre = static_cast<FormGraphics*>(ob->form->u_vdata);
495 void FormGraphics::BrowseCB(FL_OBJECT * ob, long)
497 FormGraphics * pre = static_cast<FormGraphics*>(ob->form->u_vdata);
501 void FormGraphics::AdvancedOptionsCB(FL_OBJECT * /* ob */, long)
503 // FormGraphics * pre = static_cast<FormGraphics*>(ob->form->u_vdata);
504 // pre->showAdvancedOptions();
505 lyxerr << "Advanced Options button depressed, "
506 "show advanced options dialog"
510 void FormGraphics::InputCB(FL_OBJECT * ob, long)
512 FormGraphics * pre = static_cast<FormGraphics*>(ob->form->u_vdata);