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),
59 bc_(new ButtonController
60 (new NoRepeatedApplyReadOnlyPolicy, _("Cancel"), _("Close") )
69 // let the dialog be shown
70 // This is a permanent connection so we won't bother
71 // storing a copy because we won't be disconnecting.
72 d->showGraphics.connect(slot(this, &FormGraphics::showDialog));
76 FormGraphics::~FormGraphics()
80 // Free the button controller.
85 void FormGraphics::build()
87 dialog_ = build_graphics();
90 lyxerr << "ERROR: Failed to create the Graphics Inset dialog." << endl;
94 // This is the place to add settings of the dialog that did not go
97 // Set the input widgets to issue a callback to input() whenever
98 // they change, so we can verify their content.
99 fl_set_input_return (dialog_->input_width,
101 fl_set_input_return (dialog_->input_height,
103 fl_set_input_return (dialog_->input_filename,
105 // fl_set_input_return(dialog_->input_rotate_angle,
106 // FL_RETURN_CHANGED);
108 // Set the maximum characters that can be written in the input texts.
109 fl_set_input_maxchars(dialog_->input_width, WIDTH_MAXDIGITS);
110 fl_set_input_maxchars(dialog_->input_height, HEIGHT_MAXDIGITS);
111 fl_set_input_maxchars(dialog_->input_filename, FILENAME_MAXCHARS);
112 fl_set_input_maxchars(dialog_->input_rotate_angle, ROTATE_MAXCHARS);
114 // Set input filter on width and height to make them accept only
116 fl_set_input_filter(dialog_->input_width,
117 fl_unsigned_int_filter);
118 fl_set_input_filter(dialog_->input_height,
119 fl_unsigned_int_filter);
122 // Add the widgets of the width radio buttons to their group
123 widthButtons.reset();
124 widthButtons.registerRadioButton(dialog_->radio_width_default,
125 InsetGraphicsParams::DEFAULT_SIZE);
126 widthButtons.registerRadioButton(dialog_->radio_width_cm,
127 InsetGraphicsParams::CM);
128 widthButtons.registerRadioButton(dialog_->radio_width_inch,
129 InsetGraphicsParams::INCH);
130 widthButtons.registerRadioButton(dialog_->radio_width_percent_page,
131 InsetGraphicsParams::PERCENT_PAGE);
132 widthButtons.registerRadioButton(dialog_->radio_width_percent_column,
133 InsetGraphicsParams::PERCENT_COLUMN);
135 // Add the widgets of the height radio buttons to their group
136 heightButtons.reset();
137 heightButtons.registerRadioButton(dialog_->radio_height_default,
138 InsetGraphicsParams::DEFAULT_SIZE);
139 heightButtons.registerRadioButton(dialog_->radio_height_cm,
140 InsetGraphicsParams::CM);
141 heightButtons.registerRadioButton(dialog_->radio_height_inch,
142 InsetGraphicsParams::INCH);
143 heightButtons.registerRadioButton(dialog_->radio_height_percent_page,
144 InsetGraphicsParams::PERCENT_PAGE);
146 // Add the widgets of the display radio buttons to their group
147 displayButtons.reset();
148 displayButtons.registerRadioButton(dialog_->radio_display_color,
149 InsetGraphicsParams::COLOR);
150 displayButtons.registerRadioButton(dialog_->radio_display_grayscale,
151 InsetGraphicsParams::GRAYSCALE);
152 displayButtons.registerRadioButton(dialog_->radio_display_monochrome,
153 InsetGraphicsParams::MONOCHROME);
154 displayButtons.registerRadioButton(dialog_->radio_no_display,
155 InsetGraphicsParams::NONE);
157 // Connect a signal to hide the window when the window manager orders it.
158 fl_set_form_atclose(dialog_->form,
159 C_FormGraphicsWMHideCB, 0);
161 bc_->setOK(dialog_->button_ok);
162 bc_->setApply(dialog_->button_apply);
163 bc_->setCancel(dialog_->button_cancel);
168 void FormGraphics::show()
170 // If the dialog doesn't exist yet, build it.
175 // Update the form with the data from the inset.
178 // If the form is visible
179 if (dialog_->form->visible) {
181 fl_raise_form(dialog_->form);
183 // Otherwise (invisible), show it.
184 fl_show_form(dialog_->form,
189 // And connect the signals 'updateBufferDependent',
190 // 'hideBufferDependent' and 'hideGraphics'.
191 u_ = d_->updateBufferDependent.connect(slot(this,
192 &FormGraphics::update));
193 h_ = d_->hideBufferDependent.connect(slot(this,
194 &FormGraphics::hide));
198 void FormGraphics::showDialog(InsetGraphics* inset)
202 // If we are connected to another inset, disconnect.
209 ih_ = inset_->hide.connect(slot(this, &FormGraphics::hide));
215 void FormGraphics::hide()
217 // If the dialog exists, and the form is allocated and visible.
220 && dialog_->form->visible) {
222 fl_hide_form(dialog_->form);
224 // And disconnect the signals.
235 void FormGraphics::free()
237 // Remove all associations for the radio buttons
238 widthButtons.reset();
239 heightButtons.reset();
240 displayButtons.reset();
248 void FormGraphics::apply()
252 // Take all dialog details and insert them to the inset.
254 // Create the parameters structure and fill the data from the dialog.
255 InsetGraphicsParams igp;
257 igp.filename = fl_get_input(dialog_->input_filename);
259 igp.display = static_cast < InsetGraphicsParams::DisplayType >
260 (displayButtons.getButton());
262 igp.widthResize = static_cast < InsetGraphicsParams::Resize >
263 (widthButtons.getButton());
264 igp.widthSize = strToDbl(fl_get_input(dialog_->input_width));
266 igp.heightResize = static_cast < InsetGraphicsParams::Resize >
267 (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);
283 // Set the parameters in the inset, it also returns true if the new
284 // parameters are different from what was in the inset already.
285 bool changed = inset_->setParams(igp);
287 // Tell LyX we've got a change, and mark the document dirty, if it changed.
288 lv_->view()->updateInset(inset_, changed);
292 // it doesn't look this is capable of updating on a buffer switch
293 // inset_ would be accessible but it's not in the new buffer so
294 // ok or apply will call something that won't like it. ARRae.
295 void FormGraphics::update(bool switched)
304 // Update dialog with details from inset
305 InsetGraphicsParams igp = inset_->getParams();
307 // Update the filename input field
308 fl_set_input(dialog_->input_filename,
309 igp.filename.c_str());
311 // Update the display depth radio buttons
312 displayButtons.setButton(igp.display);
314 // Update the width radio buttons and input field
315 widthButtons.setButton(igp.widthResize);
316 fl_set_input(dialog_->input_width,
317 tostr(igp.widthSize).c_str());
319 // Update the height radio buttons and input field
320 heightButtons.setButton(igp.heightResize);
321 fl_set_input(dialog_->input_height,
322 tostr(igp.heightSize).c_str());
324 // Update the rotate angle
325 fl_set_input(dialog_->input_rotate_angle,
326 tostr(igp.rotateAngle).c_str());
328 // Update the subcaption check button and input field
329 fl_set_button(dialog_->check_subcaption,
331 fl_set_input(dialog_->input_subcaption,
332 igp.subcaptionText.c_str());
334 // Update the inline figure check button
335 fl_set_button(dialog_->check_inline,
338 // Now make sure that the buttons are set correctly.
342 bool FormGraphics::checkInput()
344 // Put verifications that the dialog shows some sane values,
345 // if not disallow clicking on ok/apply.
346 // Possibly use a label in the bottom of the dialog to give the reason.
348 // Is all input boxes convey a valid meaning?
351 // Things that we check (meaning they are incorrect states):
352 // 1. No filename specified.
353 // 2. Width radio button is not Default and width text is not a number.
354 // 3. Height radio button is not Default and height text is a not a number
356 // Note: radio button default means that the user asks for the image
357 // to be included as is with no size change, in this case we don't need
358 // any width or height.
360 // We verify now that there is a filename, it exists, it's a file
361 // and it's readable.
362 string filename = fl_get_input(dialog_->input_filename);
363 FileInfo file(filename);
372 // Width radio button not default and no number.
373 if (!fl_get_button(dialog_->radio_width_default)
374 && strToDbl(fl_get_input(dialog_->input_width)) <= 0.0) {
379 // Height radio button not default and no number.
380 if (!fl_get_button(dialog_->radio_height_default)
381 && strToDbl(fl_get_input(dialog_->input_height)) <= 0.0) {
390 // We need these in the file browser.
391 extern string system_lyxdir;
392 extern string user_lyxdir;
393 //extern string system_tempdir;
395 // Need to move this to the form_graphics
396 string FormGraphics::browseFile(string const & filename)
398 if (! filename.empty() )
399 last_image_path = OnlyPath(filename);
401 // Does user clipart directory exist?
402 string bufclip = AddName (user_lyxdir, "clipart");
403 FileInfo fileInfo(bufclip);
404 if (!(fileInfo.isOK() && fileInfo.isDir()))
405 // No - bail out to system clipart directory
406 bufclip = AddName (system_lyxdir, "clipart");
409 fileDlg.SetButton(0, _("Clipart"), bufclip);
414 string p = fileDlg.Select(_("Graphics"),
416 "*(ps|png)", filename);
418 if (p.empty()) return p;
420 last_image_path = OnlyPath(p);
422 if (p.find_first_of("#~$% ") != string::npos) {
423 WriteAlert(_("Filename can't contain any "
424 "of these characters:"),
425 // xgettext:no-c-format
426 _("space, '#', '~', '$' or '%'."));
437 void FormGraphics::browse()
439 // Get the filename from the dialog
440 string const filename = fl_get_input(dialog_->input_filename);
442 // Show the file browser dialog
443 string const new_filename = browseFile(filename);
445 // Save the filename to the dialog
446 if (new_filename != filename && ! new_filename.empty()) {
447 fl_set_input(dialog_->input_filename,
448 new_filename.c_str());
449 // The above set input doesn't cause an input event so we do
450 // it manually. Otherwise the user needs to cause an input event
451 // to get the ok/apply buttons to be activated.
457 int FormGraphics::WMHideCB(FL_FORM * form, void *)
459 // Ensure that the signal h is disconnected even if the
460 // window manager is used to close the dialog.
461 FormGraphics * pre = static_cast < FormGraphics* > (form->u_vdata);
470 void FormGraphics::OKCB(FL_OBJECT * ob, long)
472 FormGraphics * pre = static_cast < FormGraphics* > (ob->form->u_vdata);
479 void FormGraphics::ApplyCB(FL_OBJECT * ob, long)
481 FormGraphics * pre = static_cast < FormGraphics* > (ob->form->u_vdata);
487 void FormGraphics::CancelCB(FL_OBJECT * ob, long)
489 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);
513 pre->bc_->valid(pre->checkInput());