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 // Too hard to make concept checks work with this file
14 #ifdef _GLIBCXX_CONCEPT_CHECKS
15 #undef _GLIBCXX_CONCEPT_CHECKS
17 #ifdef _GLIBCPP_CONCEPT_CHECKS
18 #undef _GLIBCPP_CONCEPT_CHECKS
21 #include "GGraphics.h"
22 #include "ControlGraphics.h"
26 #include "controllers/helper_funcs.h"
28 #include "insets/insetgraphicsParams.h"
30 #include "lyxrc.h" // for lyxrc.default_papersize
32 #include "support/convert.h"
33 #include "support/lyxlib.h" // for float_equal
34 #include "support/lstrings.h"
43 using support::float_equal;
49 string defaultUnit("cm");
52 GGraphics::GGraphics(Dialog & parent)
53 : GViewCB<ControlGraphics, GViewGladeB>(parent, _("Graphics"), false)
57 void GGraphics::doBuild()
59 string const gladeName = findGladeFile("graphics");
60 xml_ = Gnome::Glade::Xml::create(gladeName);
63 xml_->get_widget("Close", button);
65 xml_->get_widget("Ok", button);
67 xml_->get_widget("Apply", button);
69 xml_->get_widget("Restore", button);
72 xml_->get_widget("Notebook", notebook_);
75 xml_->get_widget("File", fileentry_);
76 xml_->get_widget("DisplayScale", displayscalespin_);
77 xml_->get_widget("OutputScale", outputscalespin_);
78 xml_->get_widget("Browse", browsebutton_);
79 xml_->get_widget("Edit", editbutton_);
80 xml_->get_widget("Display", displaycombo_);
81 xml_->get_widget("Width", widthspin_);
82 xml_->get_widget("Height", heightspin_);
83 xml_->get_widget("MaintainAspectRatio", aspectcheck_);
86 xml_->get_widget("WidthUnits", box);
87 box->pack_start(widthunitscombo_, true, true, 0);
89 xml_->get_widget("HeightUnits", box);
90 box->pack_start(heightunitscombo_, true, true, 0);
93 xml_->get_widget("SetScaling", setscalingradio_);
94 xml_->get_widget("SetSize", setsizeradio_);
97 xml_->get_widget("ClipToBoundingBox", clipcheck_);
98 xml_->get_widget("RightTopX", righttopxspin_);
99 xml_->get_widget("RightTopY", righttopyspin_);
100 xml_->get_widget("LeftBottomX", leftbottomxspin_);
101 xml_->get_widget("LeftBottomY", leftbottomyspin_);
102 xml_->get_widget("BoundingUnits", bbunitscombo_);
103 xml_->get_widget("GetFromFile", bbfromfilebutton_);
106 xml_->get_widget("Angle", anglespin_);
107 xml_->get_widget("Origin", origincombo_);
108 xml_->get_widget("UseSubfigure", subfigcheck_);
109 xml_->get_widget("SubfigureCaption", subfigentry_);
110 xml_->get_widget("LatexOptions", latexoptsentry_);
111 xml_->get_widget("DraftMode", draftcheck_);
112 xml_->get_widget("UnzipOnExport", unzipcheck_);
114 // Setup the columnrecord we use for combos
115 cols_.add(stringcol_);
119 // Disable for read-only documents.
120 bcview().addReadOnly(browsebutton_);
121 bcview().addReadOnly(aspectcheck_);
123 fileentry_->signal_changed().connect(
124 sigc::mem_fun(*this, &GGraphics::onInput));
125 displayscalespin_->signal_changed().connect(
126 sigc::mem_fun(*this, &GGraphics::onInput));
127 displaycombo_->signal_changed().connect(
128 sigc::mem_fun(*this, &GGraphics::onInput));
129 outputscalespin_->signal_changed().connect(
130 sigc::mem_fun(*this, &GGraphics::onInput));
131 heightspin_->signal_changed().connect(
132 sigc::mem_fun(*this, &GGraphics::onInput));
133 heightunitscombo_.signal_changed().connect(
134 sigc::mem_fun(*this, &GGraphics::onInput));
135 widthspin_->signal_changed().connect(
136 sigc::mem_fun(*this, &GGraphics::onInput));
137 widthunitscombo_.signal_changed().connect(
138 sigc::mem_fun(*this, &GGraphics::onInput));
139 aspectcheck_->signal_toggled().connect(
140 sigc::mem_fun(*this, &GGraphics::onInput));
142 setscalingradio_->signal_toggled().connect(
143 sigc::mem_fun(*this, &GGraphics::onSizingModeChange));
144 setsizeradio_->signal_toggled().connect(
145 sigc::mem_fun(*this, &GGraphics::onSizingModeChange));
147 browsebutton_->signal_clicked().connect(
148 sigc::mem_fun(*this, &GGraphics::onBrowseClicked));
150 editbutton_->signal_clicked().connect(
151 sigc::mem_fun(*this, &GGraphics::onEditClicked));
153 populateUnitCombo(widthunitscombo_, true);
154 populateUnitCombo(heightunitscombo_, true);
156 // the bounding box page
157 leftbottomxspin_->signal_changed().connect(
158 sigc::mem_fun(*this, &GGraphics::onBBChange));
159 leftbottomyspin_->signal_changed().connect(
160 sigc::mem_fun(*this, &GGraphics::onBBChange));
161 righttopxspin_->signal_changed().connect(
162 sigc::mem_fun(*this, &GGraphics::onBBChange));
163 righttopyspin_->signal_changed().connect(
164 sigc::mem_fun(*this, &GGraphics::onBBChange));
165 bbunitscombo_->signal_changed().connect(
166 sigc::mem_fun(*this, &GGraphics::onBBChange));
167 clipcheck_->signal_toggled().connect(
168 sigc::mem_fun(*this, &GGraphics::onBBChange));
170 bbfromfilebutton_->signal_clicked().connect(
171 sigc::mem_fun(*this, &GGraphics::onBBFromFileClicked));
173 // disable for read-only documents
174 bcview().addReadOnly(bbfromfilebutton_);
175 bcview().addReadOnly(clipcheck_);
176 PopulateComboBox(bbunitscombo_, getBBUnits());
181 // disable for read-only documents
182 bcview().addReadOnly(anglespin_);
183 bcview().addReadOnly(origincombo_);
184 bcview().addReadOnly(subfigcheck_);
185 bcview().addReadOnly(latexoptsentry_);
186 bcview().addReadOnly(draftcheck_);
187 bcview().addReadOnly(unzipcheck_);
189 anglespin_->signal_changed().connect(
190 sigc::mem_fun(*this, &GGraphics::onInput));
191 origincombo_->signal_changed().connect(
192 sigc::mem_fun(*this, &GGraphics::onInput));
193 subfigentry_->signal_changed().connect(
194 sigc::mem_fun(*this, &GGraphics::onInput));
195 latexoptsentry_->signal_changed().connect(
196 sigc::mem_fun(*this, &GGraphics::onInput));
197 draftcheck_->signal_toggled().connect(
198 sigc::mem_fun(*this, &GGraphics::onInput));
199 unzipcheck_->signal_toggled().connect(
200 sigc::mem_fun(*this, &GGraphics::onInput));
202 subfigcheck_->signal_toggled().connect(
203 sigc::mem_fun(*this, &GGraphics::onSubFigCheckToggled));
205 vector<RotationOriginPair> origindata = getRotationOriginData();
207 // Store the identifiers for later
208 origins_ = getSecond(origindata);
209 PopulateComboBox(origincombo_, getFirst(origindata));
213 void GGraphics::onSizingModeChange()
215 bool const scalingmode = setscalingradio_->get_active();
217 outputscalespin_->set_sensitive(scalingmode);
218 widthspin_->set_sensitive(!scalingmode);
219 heightspin_->set_sensitive(!scalingmode);
220 widthunitscombo_.set_sensitive(!scalingmode);
221 heightunitscombo_.set_sensitive(!scalingmode);
222 aspectcheck_->set_sensitive(!scalingmode);
223 bc().input(ButtonPolicy::SMI_VALID);
227 void GGraphics::PopulateComboBox(Gtk::ComboBox * combo,
228 vector<string> const & strings)
230 Glib::RefPtr<Gtk::ListStore> model = Gtk::ListStore::create(cols_);
231 vector<string>::const_iterator it = strings.begin();
232 vector<string>::const_iterator end = strings.end();
233 for (int rowindex = 0; it != end; ++it, ++rowindex) {
234 Gtk::TreeModel::iterator row = model->append();
235 (*row)[stringcol_] = *it;
238 combo->set_model(model);
239 Gtk::CellRendererText * cell = Gtk::manage(new Gtk::CellRendererText);
240 combo->pack_start(*cell, true);
241 combo->add_attribute(*cell, "text", 0);
245 void GGraphics::apply()
247 // Create the parameters structure and fill the data from the dialog.
248 InsetGraphicsParams & igp = controller().params();
251 igp.filename.set(fileentry_->get_text(),
252 kernel().bufferFilepath());
255 static_cast<int>(displayscalespin_->get_adjustment()->get_value());
256 if (igp.lyxscale == 0) {
260 switch (displaycombo_->get_active_row_number()) {
262 igp.display = graphics::NoDisplay;
265 igp.display = graphics::ColorDisplay;
268 igp.display = graphics::GrayscaleDisplay;
271 igp.display = graphics::MonochromeDisplay;
274 igp.display = graphics::DefaultDisplay;
277 if (setscalingradio_->get_active()) {
278 float scaleValue = outputscalespin_->get_adjustment()->get_value();
279 igp.scale = convert<string>(scaleValue);
280 if (float_equal(scaleValue, 0.0, 0.05))
281 igp.scale = string();
282 igp.width = LyXLength();
284 igp.scale = string();
285 igp.width = LyXLength(getLengthFromWidgets(*widthspin_->get_adjustment(), widthunitscombo_));
288 igp.height = LyXLength(getLengthFromWidgets(*heightspin_->get_adjustment(), heightunitscombo_));
290 igp.keepAspectRatio = aspectcheck_->get_active();
291 igp.draft = draftcheck_->get_active();
292 igp.noUnzip = !unzipcheck_->get_active();
296 if (!controller().bbChanged) {
297 // don't write anything
300 Glib::ustring const bbunit = (*bbunitscombo_->get_active())[stringcol_];
303 if (leftbottomxspin_->get_text().empty())
306 bb = leftbottomxspin_->get_text() + bbunit;
310 if (leftbottomyspin_->get_text().empty())
313 bb += leftbottomyspin_->get_text() + bbunit;
317 if (righttopxspin_->get_text().empty())
320 bb += righttopxspin_->get_text() + bbunit;
324 if (righttopyspin_->get_text().empty())
327 bb += righttopyspin_->get_text() + bbunit;
329 /// The bounding box with "xLB yLB yRT yRT ", divided by a space!
332 igp.clip = clipcheck_->get_active();
335 igp.rotateAngle = convert<string>(anglespin_->get_adjustment()->get_value());
337 int const origin_pos = origincombo_->get_active_row_number();
338 igp.rotateOrigin = origins_[origin_pos];
340 igp.subcaption = subfigcheck_->get_active();
341 igp.subcaptionText = subfigentry_->get_text();
343 igp.special = latexoptsentry_->get_text();
347 void GGraphics::update() {
348 // set the right default unit
349 defaultUnit = getDefaultUnit();
351 // Update dialog with details from inset
352 InsetGraphicsParams & igp = controller().params();
356 igp.filename.outputFilename(kernel().bufferFilepath());
357 fileentry_->set_text(name);
358 displayscalespin_->get_adjustment()->set_value(igp.lyxscale);
361 switch (igp.display) {
362 case graphics::NoDisplay:
363 displaycombo_->set_active(4);
365 case graphics::ColorDisplay:
366 displaycombo_->set_active(3);
368 case graphics::GrayscaleDisplay:
369 displaycombo_->set_active(2);
371 case graphics::MonochromeDisplay:
372 displaycombo_->set_active(1);
374 case graphics::DefaultDisplay:
375 displaycombo_->set_active(0);
378 outputscalespin_->get_adjustment()->set_value(convert<double>(igp.scale));
380 setWidgetsFromLength(*widthspin_->get_adjustment(), widthunitscombo_, igp.width);
381 setWidgetsFromLength(*heightspin_->get_adjustment(), heightunitscombo_, igp.height);
383 if (!igp.scale.empty()
384 && !float_equal(convert<double>(igp.scale), 0.0, 0.05)) {
385 // scaling sizing mode
386 setscalingradio_->set_active(true);
388 setsizeradio_->set_active(true);
390 onSizingModeChange();
392 aspectcheck_->set_active(igp.keepAspectRatio);
393 draftcheck_->set_active(igp.draft);
394 unzipcheck_->set_active(!igp.noUnzip);
397 // set the bounding box values, if exists. First we need the whole
398 // path, because the controller knows nothing about the doc-dir
399 updateBB(igp.filename.absFilename(), igp.bb);
400 clipcheck_->set_active(igp.clip);
403 anglespin_->get_adjustment()->set_value(convert<double>(igp.rotateAngle));
406 if (igp.rotateOrigin.empty()) {
409 origin_pos = findPos(origins_, igp.rotateOrigin);
411 origincombo_->set_active(origin_pos);
414 subfigcheck_->set_active(igp.subcaption);
415 subfigentry_->set_text(igp.subcaptionText);
416 subfigentry_->set_sensitive(subfigcheck_->get_active());
417 latexoptsentry_->set_text(igp.special);
419 // open dialog in the file-tab, whenever filename is empty
420 if (igp.filename.empty()) {
421 notebook_->set_current_page(0);
425 bc().input(ButtonPolicy::SMI_INVALID);
429 void GGraphics::updateBB(string const & filename, string const & bb_inset)
431 // Update dialog with details from inset
432 // set the bounding box values, if exists. First we need the whole
433 // path, because the controller knows nothing about the doc-dir
435 if (bb_inset.empty()) {
436 lyxerr[Debug::GRAPHICS]
437 << "GGraphics::updateBB() [no BoundingBox]\n";
438 string const bb = controller().readBB(filename);
440 // get the values from the file
441 // in this case we always have the point-unit
442 leftbottomxspin_->set_text(token(bb, ' ', 0));
443 leftbottomyspin_->set_text(token(bb, ' ', 1));
444 righttopxspin_->set_text(token(bb, ' ', 2));
445 righttopyspin_->set_text(token(bb, ' ', 3));
448 leftbottomxspin_->set_text("");
449 leftbottomyspin_->set_text("");
450 righttopxspin_->set_text("");
451 righttopyspin_->set_text("");
453 unitsComboFromLength(bbunitscombo_, stringcol_,
454 LyXLength("bp"), defaultUnit);
456 // get the values from the inset
457 lyxerr[Debug::GRAPHICS]
458 << "FormGraphics::updateBB(): igp has BoundingBox"
459 << " ["<< bb_inset << "]\n";
462 anyLength = LyXLength(token(bb_inset, ' ', 0));
464 unitsComboFromLength(bbunitscombo_, stringcol_, anyLength, defaultUnit);
466 leftbottomxspin_->get_adjustment()->set_value(anyLength.value());
468 anyLength = LyXLength(token(bb_inset, ' ', 1));
469 leftbottomyspin_->get_adjustment()->set_value(anyLength.value());
471 anyLength = LyXLength(token(bb_inset, ' ', 2));
472 righttopxspin_->get_adjustment()->set_value(anyLength.value());
474 anyLength = LyXLength(token(bb_inset, ' ', 3));
475 righttopyspin_->get_adjustment()->set_value(anyLength.value());
477 controller().bbChanged = false;
481 void GGraphics::onBrowseClicked()
483 // Get the filename from the dialog
484 string const in_name = fileentry_->get_text();
485 string const out_name = controller().browse(in_name);
486 lyxerr[Debug::GRAPHICS]
487 << "[FormGraphics]out_name: " << out_name << "\n";
488 if (out_name != in_name && !out_name.empty()) {
489 fileentry_->set_text(out_name);
491 if (controller().isFilenameValid(out_name) &&
492 !controller().bbChanged) {
493 updateBB(out_name, string());
496 bc().input(ButtonPolicy::SMI_VALID);
500 void GGraphics::onBBChange()
502 controller().bbChanged = true;
503 bc().input(ButtonPolicy::SMI_VALID);
507 void GGraphics::onBBFromFileClicked()
509 string const filename = fileentry_->get_text();
510 if (!filename.empty()) {
511 string bb = controller().readBB(filename);
513 leftbottomxspin_->set_text(token(bb, ' ', 0));
514 leftbottomyspin_->set_text(token(bb, ' ', 1));
515 righttopxspin_->set_text(token(bb, ' ', 2));
516 righttopyspin_->set_text(token(bb, ' ', 3));
517 unitsComboFromLength(bbunitscombo_, stringcol_,
518 LyXLength("bp"), defaultUnit);
520 controller().bbChanged = false;
522 leftbottomxspin_->set_text("");
523 leftbottomyspin_->set_text("");
524 righttopxspin_->set_text("");
525 righttopyspin_->set_text("");
526 unitsComboFromLength(bbunitscombo_, stringcol_,
527 LyXLength("bp"), defaultUnit);
529 bc().input(ButtonPolicy::SMI_VALID);
533 void GGraphics::onSubFigCheckToggled()
535 subfigentry_->set_sensitive(subfigcheck_->get_active());
536 bc().input(ButtonPolicy::SMI_VALID);
540 void GGraphics::onEditClicked()
542 controller().editGraphics();
546 void GGraphics::onInput()
548 bc().input(ButtonPolicy::SMI_VALID);
551 } // namespace frontend