3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
8 * Full author contact details are available in file CREDITS.
13 #include "GGraphics.h"
14 #include "ControlGraphics.h"
18 #include "controllers/helper_funcs.h"
20 #include "insets/insetgraphicsParams.h"
22 #include "lyxrc.h" // for lyxrc.default_papersize
24 #include "support/lyxlib.h" // for float_equal
25 #include "support/lstrings.h"
34 using support::float_equal;
40 string defaultUnit("cm");
43 GGraphics::GGraphics(Dialog & parent)
44 : GViewCB<ControlGraphics, GViewGladeB>(parent, _("Graphics"), false)
48 void GGraphics::doBuild()
50 string const gladeName = findGladeFile("graphics");
51 xml_ = Gnome::Glade::Xml::create(gladeName);
54 xml_->get_widget("Close", button);
56 xml_->get_widget("Ok", button);
58 xml_->get_widget("Apply", button);
60 xml_->get_widget("Restore", button);
63 xml_->get_widget("Notebook", notebook_);
66 xml_->get_widget("File", fileentry_);
67 xml_->get_widget("DisplayScale", displayscalespin_);
68 xml_->get_widget("OutputScale", outputscalespin_);
69 xml_->get_widget("Browse", browsebutton_);
70 xml_->get_widget("Edit", editbutton_);
71 xml_->get_widget("Display", displaycombo_);
72 xml_->get_widget("Width", widthspin_);
73 xml_->get_widget("Height", heightspin_);
74 xml_->get_widget("MaintainAspectRatio", aspectcheck_);
75 xml_->get_widget("WidthUnits", widthunitscombo_);
76 xml_->get_widget("HeightUnits", heightunitscombo_);
77 xml_->get_widget("SetScaling", setscalingradio_);
78 xml_->get_widget("SetSize", setsizeradio_);
81 xml_->get_widget("ClipToBoundingBox", clipcheck_);
82 xml_->get_widget("RightTopX", righttopxspin_);
83 xml_->get_widget("RightTopY", righttopyspin_);
84 xml_->get_widget("LeftBottomX", leftbottomxspin_);
85 xml_->get_widget("LeftBottomY", leftbottomyspin_);
86 xml_->get_widget("BoundingUnits", bbunitscombo_);
87 xml_->get_widget("GetFromFile", bbfromfilebutton_);
90 xml_->get_widget("Angle", anglespin_);
91 xml_->get_widget("Origin", origincombo_);
92 xml_->get_widget("UseSubfigure", subfigcheck_);
93 xml_->get_widget("SubfigureCaption", subfigentry_);
94 xml_->get_widget("LatexOptions", latexoptsentry_);
95 xml_->get_widget("DraftMode", draftcheck_);
96 xml_->get_widget("UnzipOnExport", unzipcheck_);
98 // Setup the columnrecord we use for combos
99 cols_.add(stringcol_);
103 // Disable for read-only documents.
104 bcview().addReadOnly(browsebutton_);
105 bcview().addReadOnly(aspectcheck_);
107 fileentry_->signal_changed().connect(
108 sigc::mem_fun(*this, &GGraphics::onInput));
109 displayscalespin_->signal_changed().connect(
110 sigc::mem_fun(*this, &GGraphics::onInput));
111 displaycombo_->signal_changed().connect(
112 sigc::mem_fun(*this, &GGraphics::onInput));
113 outputscalespin_->signal_changed().connect(
114 sigc::mem_fun(*this, &GGraphics::onInput));
115 heightspin_->signal_changed().connect(
116 sigc::mem_fun(*this, &GGraphics::onInput));
117 heightunitscombo_->signal_changed().connect(
118 sigc::mem_fun(*this, &GGraphics::onInput));
119 widthspin_->signal_changed().connect(
120 sigc::mem_fun(*this, &GGraphics::onInput));
121 widthunitscombo_->signal_changed().connect(
122 sigc::mem_fun(*this, &GGraphics::onInput));
123 aspectcheck_->signal_toggled().connect(
124 sigc::mem_fun(*this, &GGraphics::onInput));
126 setscalingradio_->signal_toggled().connect(
127 sigc::mem_fun(*this, &GGraphics::onSizingModeChange));
128 setsizeradio_->signal_toggled().connect(
129 sigc::mem_fun(*this, &GGraphics::onSizingModeChange));
131 browsebutton_->signal_clicked().connect(
132 sigc::mem_fun(*this, &GGraphics::onBrowseClicked));
134 editbutton_->signal_clicked().connect(
135 sigc::mem_fun(*this, &GGraphics::onEditClicked));
137 vector<string> const unit_list = buildLengthUnitList();
138 PopulateComboBox(heightunitscombo_, unit_list);
139 PopulateComboBox(widthunitscombo_, unit_list);
141 // the bounding box page
142 leftbottomxspin_->signal_changed().connect(
143 sigc::mem_fun(*this, &GGraphics::onBBChange));
144 leftbottomyspin_->signal_changed().connect(
145 sigc::mem_fun(*this, &GGraphics::onBBChange));
146 righttopxspin_->signal_changed().connect(
147 sigc::mem_fun(*this, &GGraphics::onBBChange));
148 righttopyspin_->signal_changed().connect(
149 sigc::mem_fun(*this, &GGraphics::onBBChange));
150 bbunitscombo_->signal_changed().connect(
151 sigc::mem_fun(*this, &GGraphics::onBBChange));
152 clipcheck_->signal_toggled().connect(
153 sigc::mem_fun(*this, &GGraphics::onBBChange));
155 bbfromfilebutton_->signal_clicked().connect(
156 sigc::mem_fun(*this, &GGraphics::onBBFromFileClicked));
158 // disable for read-only documents
159 bcview().addReadOnly(bbfromfilebutton_);
160 bcview().addReadOnly(clipcheck_);
161 PopulateComboBox(bbunitscombo_, getBBUnits());
166 // disable for read-only documents
167 bcview().addReadOnly(anglespin_);
168 bcview().addReadOnly(origincombo_);
169 bcview().addReadOnly(subfigcheck_);
170 bcview().addReadOnly(latexoptsentry_);
171 bcview().addReadOnly(draftcheck_);
172 bcview().addReadOnly(unzipcheck_);
174 anglespin_->signal_changed().connect(
175 sigc::mem_fun(*this, &GGraphics::onInput));
176 origincombo_->signal_changed().connect(
177 sigc::mem_fun(*this, &GGraphics::onInput));
178 subfigentry_->signal_changed().connect(
179 sigc::mem_fun(*this, &GGraphics::onInput));
180 latexoptsentry_->signal_changed().connect(
181 sigc::mem_fun(*this, &GGraphics::onInput));
182 draftcheck_->signal_toggled().connect(
183 sigc::mem_fun(*this, &GGraphics::onInput));
184 unzipcheck_->signal_toggled().connect(
185 sigc::mem_fun(*this, &GGraphics::onInput));
187 subfigcheck_->signal_toggled().connect(
188 sigc::mem_fun(*this, &GGraphics::onSubFigCheckToggled));
190 vector<RotationOriginPair> origindata = getRotationOriginData();
192 // Store the identifiers for later
193 origins_ = getSecond(origindata);
194 PopulateComboBox(origincombo_, getFirst(origindata));
198 void GGraphics::onSizingModeChange()
200 bool const scalingmode = setscalingradio_->get_active();
202 outputscalespin_->set_sensitive(scalingmode);
203 widthspin_->set_sensitive(!scalingmode);
204 heightspin_->set_sensitive(!scalingmode);
205 widthunitscombo_->set_sensitive(!scalingmode);
206 heightunitscombo_->set_sensitive(!scalingmode);
207 aspectcheck_->set_sensitive(!scalingmode);
208 bc().input(ButtonPolicy::SMI_VALID);
212 void GGraphics::PopulateComboBox(Gtk::ComboBox * combo,
213 vector<string> const & strings)
215 Glib::RefPtr<Gtk::ListStore> model = Gtk::ListStore::create(cols_);
216 vector<string>::const_iterator it = strings.begin();
217 vector<string>::const_iterator end = strings.end();
218 for (int rowindex = 0; it != end; ++it, ++rowindex) {
219 Gtk::TreeModel::iterator row = model->append();
220 (*row)[stringcol_] = *it;
223 combo->set_model(model);
224 Gtk::CellRendererText * cell = Gtk::manage(new Gtk::CellRendererText);
225 combo->pack_start(*cell, true);
226 combo->add_attribute(*cell, "text", 0);
230 void GGraphics::apply()
232 // Create the parameters structure and fill the data from the dialog.
233 InsetGraphicsParams & igp = controller().params();
236 igp.filename.set(fileentry_->get_text(),
237 kernel().bufferFilepath());
240 static_cast<int>(displayscalespin_->get_adjustment()->get_value());
241 if (igp.lyxscale == 0) {
245 switch (displaycombo_->get_active_row_number()) {
247 igp.display = graphics::NoDisplay;
250 igp.display = graphics::ColorDisplay;
253 igp.display = graphics::GrayscaleDisplay;
256 igp.display = graphics::MonochromeDisplay;
259 igp.display = graphics::DefaultDisplay;
262 if (setscalingradio_->get_active()) {
263 igp.scale = outputscalespin_->get_adjustment()->get_value();
264 if (float_equal(igp.scale, 0.0, 0.05))
266 igp.width = LyXLength();
269 Glib::ustring const widthunit =
270 (*widthunitscombo_->get_active())[stringcol_];
271 igp.width = LyXLength(widthspin_->get_text() + widthunit);
275 Glib::ustring const heightunit =
276 (*heightunitscombo_->get_active())[stringcol_];
277 igp.height = LyXLength(heightspin_->get_text() + heightunit);
279 igp.keepAspectRatio = aspectcheck_->get_active();
280 igp.draft = draftcheck_->get_active();
281 igp.noUnzip = !unzipcheck_->get_active();
285 if (!controller().bbChanged) {
286 // don't write anything
289 Glib::ustring const bbunit = (*bbunitscombo_->get_active())[stringcol_];
292 if (leftbottomxspin_->get_text().empty())
295 bb = leftbottomxspin_->get_text() + bbunit;
299 if (leftbottomyspin_->get_text().empty())
302 bb += leftbottomyspin_->get_text() + bbunit;
306 if (righttopxspin_->get_text().empty())
309 bb += righttopxspin_->get_text() + bbunit;
313 if (righttopyspin_->get_text().empty())
316 bb += righttopyspin_->get_text() + bbunit;
318 /// The bounding box with "xLB yLB yRT yRT ", divided by a space!
321 igp.clip = clipcheck_->get_active();
324 igp.rotateAngle = anglespin_->get_adjustment()->get_value();
326 int const origin_pos = origincombo_->get_active_row_number();
327 igp.rotateOrigin = origins_[origin_pos];
329 igp.subcaption = subfigcheck_->get_active();
330 igp.subcaptionText = subfigentry_->get_text();
332 igp.special = latexoptsentry_->get_text();
336 void GGraphics::update() {
337 // set the right default unit
338 defaultUnit = getDefaultUnit();
340 // Update dialog with details from inset
341 InsetGraphicsParams & igp = controller().params();
345 igp.filename.outputFilename(kernel().bufferFilepath());
346 fileentry_->set_text(name);
347 displayscalespin_->get_adjustment()->set_value(igp.lyxscale);
350 switch (igp.display) {
351 case graphics::NoDisplay:
352 displaycombo_->set_active(4);
354 case graphics::ColorDisplay:
355 displaycombo_->set_active(3);
357 case graphics::GrayscaleDisplay:
358 displaycombo_->set_active(2);
360 case graphics::MonochromeDisplay:
361 displaycombo_->set_active(1);
363 case graphics::DefaultDisplay:
364 displaycombo_->set_active(0);
367 outputscalespin_->get_adjustment()->set_value(igp.scale);
368 widthspin_->get_adjustment()->set_value(igp.width.value());
369 unitsComboFromLength(widthunitscombo_, stringcol_,
370 igp.width, defaultUnit);
371 heightspin_->get_adjustment()->set_value(igp.height.value());
372 unitsComboFromLength(heightunitscombo_, stringcol_,
373 igp.height, defaultUnit);
375 if (!float_equal(igp.scale, 0.0, 0.05)) {
376 // scaling sizing mode
377 setscalingradio_->set_active(true);
379 setsizeradio_->set_active(true);
381 onSizingModeChange();
383 aspectcheck_->set_active(igp.keepAspectRatio);
384 draftcheck_->set_active(igp.draft);
385 unzipcheck_->set_active(!igp.noUnzip);
388 // set the bounding box values, if exists. First we need the whole
389 // path, because the controller knows nothing about the doc-dir
390 updateBB(igp.filename.absFilename(), igp.bb);
391 clipcheck_->set_active(igp.clip);
394 anglespin_->get_adjustment()->set_value(igp.rotateAngle);
397 if (igp.rotateOrigin.empty()) {
400 origin_pos = findPos(origins_, igp.rotateOrigin);
402 origincombo_->set_active(origin_pos);
405 subfigcheck_->set_active(igp.subcaption);
406 subfigentry_->set_text(igp.subcaptionText);
407 subfigentry_->set_sensitive(subfigcheck_->get_active());
408 latexoptsentry_->set_text(igp.special);
410 // open dialog in the file-tab, whenever filename is empty
411 if (igp.filename.empty()) {
412 notebook_->set_current_page(0);
416 bc().input(ButtonPolicy::SMI_INVALID);
420 void GGraphics::updateBB(string const & filename, string const & bb_inset)
422 // Update dialog with details from inset
423 // set the bounding box values, if exists. First we need the whole
424 // path, because the controller knows nothing about the doc-dir
426 if (bb_inset.empty()) {
427 lyxerr[Debug::GRAPHICS]
428 << "GGraphics::updateBB() [no BoundingBox]\n";
429 string const bb = controller().readBB(filename);
431 // get the values from the file
432 // in this case we always have the point-unit
433 leftbottomxspin_->set_text(token(bb, ' ', 0));
434 leftbottomyspin_->set_text(token(bb, ' ', 1));
435 righttopxspin_->set_text(token(bb, ' ', 2));
436 righttopyspin_->set_text(token(bb, ' ', 3));
439 leftbottomxspin_->set_text("");
440 leftbottomyspin_->set_text("");
441 righttopxspin_->set_text("");
442 righttopyspin_->set_text("");
444 unitsComboFromLength(bbunitscombo_, stringcol_,
445 LyXLength("bp"), defaultUnit);
447 // get the values from the inset
448 lyxerr[Debug::GRAPHICS]
449 << "FormGraphics::updateBB(): igp has BoundingBox"
450 << " ["<< bb_inset << "]\n";
453 anyLength = LyXLength(token(bb_inset, ' ', 0));
455 unitsComboFromLength(bbunitscombo_, stringcol_, anyLength, defaultUnit);
457 leftbottomxspin_->get_adjustment()->set_value(anyLength.value());
459 anyLength = LyXLength(token(bb_inset, ' ', 1));
460 leftbottomyspin_->get_adjustment()->set_value(anyLength.value());
462 anyLength = LyXLength(token(bb_inset, ' ', 2));
463 righttopxspin_->get_adjustment()->set_value(anyLength.value());
465 anyLength = LyXLength(token(bb_inset, ' ', 3));
466 righttopyspin_->get_adjustment()->set_value(anyLength.value());
468 controller().bbChanged = false;
472 void GGraphics::onBrowseClicked()
474 // Get the filename from the dialog
475 string const in_name = fileentry_->get_text();
476 string const out_name = controller().browse(in_name);
477 lyxerr[Debug::GRAPHICS]
478 << "[FormGraphics]out_name: " << out_name << "\n";
479 if (out_name != in_name && !out_name.empty()) {
480 fileentry_->set_text(out_name);
482 if (controller().isFilenameValid(out_name) &&
483 !controller().bbChanged) {
484 updateBB(out_name, string());
487 bc().input(ButtonPolicy::SMI_VALID);
491 void GGraphics::onBBChange()
493 controller().bbChanged = true;
494 bc().input(ButtonPolicy::SMI_VALID);
498 void GGraphics::onBBFromFileClicked()
500 string const filename = fileentry_->get_text();
501 if (!filename.empty()) {
502 string bb = controller().readBB(filename);
504 leftbottomxspin_->set_text(token(bb, ' ', 0));
505 leftbottomyspin_->set_text(token(bb, ' ', 1));
506 righttopxspin_->set_text(token(bb, ' ', 2));
507 righttopyspin_->set_text(token(bb, ' ', 3));
508 unitsComboFromLength(bbunitscombo_, stringcol_,
509 LyXLength("bp"), defaultUnit);
511 controller().bbChanged = false;
513 leftbottomxspin_->set_text("");
514 leftbottomyspin_->set_text("");
515 righttopxspin_->set_text("");
516 righttopyspin_->set_text("");
517 unitsComboFromLength(bbunitscombo_, stringcol_,
518 LyXLength("bp"), defaultUnit);
520 bc().input(ButtonPolicy::SMI_VALID);
524 void GGraphics::onSubFigCheckToggled()
526 subfigentry_->set_sensitive(subfigcheck_->get_active());
527 bc().input(ButtonPolicy::SMI_VALID);
531 void GGraphics::onEditClicked()
533 controller().editGraphics();
537 void GGraphics::onInput()
539 bc().input(ButtonPolicy::SMI_VALID);
542 } // namespace frontend