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"
19 #include "input_validators.h"
20 #include "FormGraphics.h"
21 #include "form_graphics.h"
24 #include "BufferView.h"
26 #include "debug.h" // for lyxerr
28 #include "support/lstrings.h" // for strToDbl & tostr
29 #include "support/FileInfo.h" // for FileInfo
30 #include "filedlg.h" // for LyXFileDlg
31 #include "support/filetools.h" // for AddName
32 #include "insets/insetgraphics.h"
33 #include "insets/insetgraphicsParams.h"
35 #include "RadioButtonGroup.h"
37 #include "support/LAssert.h"
42 FormGraphics::FormGraphics(LyXView * lv, Dialogs * d)
43 : FormInset(lv, d, _("Graphics"), new NoRepeatedApplyReadOnlyPolicy),
44 dialog_(0), inset_(0),
45 // The buttons c-tor values are the number of buttons we use
46 // This is only to reduce memory waste.
47 widthButtons(5), heightButtons(4), displayButtons(4),
50 // let the dialog be shown
51 // This is a permanent connection so we won't bother
52 // storing a copy because we won't be disconnecting.
53 d->showGraphics.connect(slot(this, &FormGraphics::showDialog));
57 FormGraphics::~FormGraphics()
59 // Remove all associations for the radio buttons
61 heightButtons.reset();
62 displayButtons.reset();
69 void FormGraphics::build()
71 dialog_ = build_graphics();
74 lyxerr << "ERROR: Failed to create the Graphics Inset dialog." << endl;
78 // Workaround dumb xforms sizing bug
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 // Manage the ok, apply, restore and cancel/close buttons
146 bc_.setOK(dialog_->button_ok);
147 bc_.setApply(dialog_->button_apply);
148 bc_.setCancel(dialog_->button_cancel);
149 bc_.setUndoAll(dialog_->button_restore);
152 bc_.addReadOnly(dialog_->input_filename);
153 bc_.addReadOnly(dialog_->button_browse);
154 bc_.addReadOnly(dialog_->input_width);
155 bc_.addReadOnly(dialog_->input_height);
156 bc_.addReadOnly(dialog_->radio_button_group_width);
157 bc_.addReadOnly(dialog_->radio_button_group_height);
158 bc_.addReadOnly(dialog_->radio_button_group_display);
159 bc_.addReadOnly(dialog_->input_rotate_angle);
160 bc_.addReadOnly(dialog_->check_inline);
161 bc_.addReadOnly(dialog_->input_subcaption);
162 bc_.addReadOnly(dialog_->check_subcaption);
166 FL_FORM * FormGraphics::form() const
168 if (dialog_ ) return dialog_->form;
173 void FormGraphics::disconnect()
176 FormInset::disconnect();
180 void FormGraphics::showDialog(InsetGraphics * inset)
182 // If we are connected to another inset, disconnect.
188 ih_ = inset_->hide.connect(slot(this, &FormGraphics::hide));
193 void FormGraphics::apply()
197 // Take all dialog details and insert them to the inset.
199 // Create the parameters structure and fill the data from the dialog.
200 InsetGraphicsParams igp;
202 igp.filename = fl_get_input(dialog_->input_filename);
204 igp.display = static_cast < InsetGraphicsParams::DisplayType >
205 (displayButtons.getButton());
207 igp.widthResize = static_cast < InsetGraphicsParams::Resize >
208 (widthButtons.getButton());
209 igp.widthSize = strToDbl(fl_get_input(dialog_->input_width));
211 igp.heightResize = static_cast < InsetGraphicsParams::Resize >
212 (heightButtons.getButton());
213 igp.heightSize = strToDbl(fl_get_input(dialog_->input_height));
215 igp.rotateAngle = strToInt(fl_get_input(dialog_->input_rotate_angle));
216 if (igp.rotateAngle >= 360)
217 igp.rotateAngle = igp.rotateAngle % 360;
218 if (igp.rotateAngle <= -360)
219 igp.rotateAngle = - (( -igp.rotateAngle) % 360);
221 igp.subcaption = fl_get_button(dialog_->check_subcaption);
222 igp.subcaptionText = fl_get_input(dialog_->input_subcaption);
224 igp.inlineFigure = fl_get_button(dialog_->check_inline);
228 // Set the parameters in the inset, it also returns true if the new
229 // parameters are different from what was in the inset already.
230 bool changed = inset_->setParams(igp);
232 // Tell LyX we've got a change, and mark the document dirty, if it changed.
233 lv_->view()->updateInset(inset_, changed);
237 void FormGraphics::update()
241 // Update dialog with details from inset
242 InsetGraphicsParams igp = inset_->getParams();
244 // Update the filename input field
245 fl_set_input(dialog_->input_filename,
246 igp.filename.c_str());
248 // Update the display depth radio buttons
249 displayButtons.setButton(igp.display);
251 // Update the width radio buttons and input field
252 widthButtons.setButton(igp.widthResize);
253 fl_set_input(dialog_->input_width,
254 tostr(igp.widthSize).c_str());
256 // Update the height radio buttons and input field
257 heightButtons.setButton(igp.heightResize);
258 fl_set_input(dialog_->input_height,
259 tostr(igp.heightSize).c_str());
261 // Update the rotate angle
262 fl_set_input(dialog_->input_rotate_angle,
263 tostr(igp.rotateAngle).c_str());
265 // Update the subcaption check button and input field
266 fl_set_button(dialog_->check_subcaption,
268 fl_set_input(dialog_->input_subcaption,
269 igp.subcaptionText.c_str());
271 // Update the inline figure check button
272 fl_set_button(dialog_->check_inline,
275 // update the dialog's read only / read-write status
276 bc_.readOnly(lv_->buffer()->isReadonly());
278 // Now make sure that the buttons are set correctly.
283 bool FormGraphics::input(FL_OBJECT *, long data )
285 State cb = static_cast<State>( data );
291 inputOK = checkInput();
297 lyxerr << "Advanced Options button depressed, "
298 << "show advanced options dialog"
309 bool FormGraphics::checkInput()
311 // Put verifications that the dialog shows some sane values,
312 // if not disallow clicking on ok/apply.
313 // Possibly use a label in the bottom of the dialog to give the reason.
315 // Is all input boxes convey a valid meaning?
318 // Things that we check (meaning they are incorrect states):
319 // 1. No filename specified.
320 // 2. Width radio button is not Default and width text is not a number.
321 // 3. Height radio button is not Default and height text is a not a number
323 // Note: radio button default means that the user asks for the image
324 // to be included as is with no size change, in this case we don't need
325 // any width or height.
327 // We verify now that there is a filename, it exists, it's a file
328 // and it's readable.
329 string filename = fl_get_input(dialog_->input_filename);
330 FileInfo file(filename);
339 // Width radio button not default and no number.
340 if (!fl_get_button(dialog_->radio_width_default)
341 && strToDbl(fl_get_input(dialog_->input_width)) <= 0.0) {
346 // Height radio button not default and no number.
347 if (!fl_get_button(dialog_->radio_height_default)
348 && strToDbl(fl_get_input(dialog_->input_height)) <= 0.0) {
357 // We need these in the file browser.
358 extern string system_lyxdir;
359 extern string user_lyxdir;
360 //extern string system_tempdir;
363 // Need to move this to the form_graphics
364 string FormGraphics::browseFile(string const & filename)
366 if (! filename.empty() )
367 last_image_path = OnlyPath(filename);
369 // Does user clipart directory exist?
370 string bufclip = AddName (user_lyxdir, "clipart");
371 FileInfo fileInfo(bufclip);
372 if (!(fileInfo.isOK() && fileInfo.isDir()))
373 // No - bail out to system clipart directory
374 bufclip = AddName (system_lyxdir, "clipart");
377 fileDlg.SetButton(0, _("Clipart"), bufclip);
382 string p = fileDlg.Select(_("Graphics"),
384 "*(ps|png)", filename);
386 if (p.empty()) return p;
388 last_image_path = OnlyPath(p);
390 if (p.find_first_of("#~$% ") != string::npos) {
391 WriteAlert(_("Filename can't contain any "
392 "of these characters:"),
393 // xgettext:no-c-format
394 _("space, '#', '~', '$' or '%'."));
406 void FormGraphics::browse()
408 // Get the filename from the dialog
409 string const filename = fl_get_input(dialog_->input_filename);
411 // Show the file browser dialog
412 string const new_filename = browseFile(filename);
414 // Save the filename to the dialog
415 if (new_filename != filename && ! new_filename.empty()) {
416 fl_set_input(dialog_->input_filename,
417 new_filename.c_str());
418 // The above set input doesn't cause an input event so we do
419 // it manually. Otherwise the user needs to cause an input event
420 // to get the ok/apply buttons to be activated.