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 _GLIBCPP_CONCEPT_CHECKS
15 #undef _GLIBCPP_CONCEPT_CHECKS
18 #include "GGraphics.h"
19 #include "ControlGraphics.h"
23 #include "controllers/helper_funcs.h"
25 #include "insets/insetgraphicsParams.h"
27 #include "lyxrc.h" // for lyxrc.default_papersize
29 #include "support/lyxlib.h" // for float_equal
30 #include "support/lstrings.h"
39 using support::float_equal;
45 string defaultUnit("cm");
48 GGraphics::GGraphics(Dialog & parent)
49 : GViewCB<ControlGraphics, GViewGladeB>(parent, _("Graphics"), false)
53 void GGraphics::doBuild()
55 string const gladeName = findGladeFile("graphics");
56 xml_ = Gnome::Glade::Xml::create(gladeName);
59 xml_->get_widget("Close", button);
61 xml_->get_widget("Ok", button);
63 xml_->get_widget("Apply", button);
65 xml_->get_widget("Restore", button);
68 xml_->get_widget("Notebook", notebook_);
71 xml_->get_widget("File", fileentry_);
72 xml_->get_widget("DisplayScale", displayscalespin_);
73 xml_->get_widget("OutputScale", outputscalespin_);
74 xml_->get_widget("Browse", browsebutton_);
75 xml_->get_widget("Edit", editbutton_);
76 xml_->get_widget("Display", displaycombo_);
77 xml_->get_widget("Width", widthspin_);
78 xml_->get_widget("Height", heightspin_);
79 xml_->get_widget("MaintainAspectRatio", aspectcheck_);
80 xml_->get_widget("WidthUnits", widthunitscombo_);
81 xml_->get_widget("HeightUnits", heightunitscombo_);
82 xml_->get_widget("SetScaling", setscalingradio_);
83 xml_->get_widget("SetSize", setsizeradio_);
86 xml_->get_widget("ClipToBoundingBox", clipcheck_);
87 xml_->get_widget("RightTopX", righttopxspin_);
88 xml_->get_widget("RightTopY", righttopyspin_);
89 xml_->get_widget("LeftBottomX", leftbottomxspin_);
90 xml_->get_widget("LeftBottomY", leftbottomyspin_);
91 xml_->get_widget("BoundingUnits", bbunitscombo_);
92 xml_->get_widget("GetFromFile", bbfromfilebutton_);
95 xml_->get_widget("Angle", anglespin_);
96 xml_->get_widget("Origin", origincombo_);
97 xml_->get_widget("UseSubfigure", subfigcheck_);
98 xml_->get_widget("SubfigureCaption", subfigentry_);
99 xml_->get_widget("LatexOptions", latexoptsentry_);
100 xml_->get_widget("DraftMode", draftcheck_);
101 xml_->get_widget("UnzipOnExport", unzipcheck_);
103 // Setup the columnrecord we use for combos
104 cols_.add(stringcol_);
108 // Disable for read-only documents.
109 bcview().addReadOnly(browsebutton_);
110 bcview().addReadOnly(aspectcheck_);
112 fileentry_->signal_changed().connect(
113 sigc::mem_fun(*this, &GGraphics::onInput));
114 displayscalespin_->signal_changed().connect(
115 sigc::mem_fun(*this, &GGraphics::onInput));
116 displaycombo_->signal_changed().connect(
117 sigc::mem_fun(*this, &GGraphics::onInput));
118 outputscalespin_->signal_changed().connect(
119 sigc::mem_fun(*this, &GGraphics::onInput));
120 heightspin_->signal_changed().connect(
121 sigc::mem_fun(*this, &GGraphics::onInput));
122 heightunitscombo_->signal_changed().connect(
123 sigc::mem_fun(*this, &GGraphics::onInput));
124 widthspin_->signal_changed().connect(
125 sigc::mem_fun(*this, &GGraphics::onInput));
126 widthunitscombo_->signal_changed().connect(
127 sigc::mem_fun(*this, &GGraphics::onInput));
128 aspectcheck_->signal_toggled().connect(
129 sigc::mem_fun(*this, &GGraphics::onInput));
131 setscalingradio_->signal_toggled().connect(
132 sigc::mem_fun(*this, &GGraphics::onSizingModeChange));
133 setsizeradio_->signal_toggled().connect(
134 sigc::mem_fun(*this, &GGraphics::onSizingModeChange));
136 browsebutton_->signal_clicked().connect(
137 sigc::mem_fun(*this, &GGraphics::onBrowseClicked));
139 editbutton_->signal_clicked().connect(
140 sigc::mem_fun(*this, &GGraphics::onEditClicked));
142 vector<string> const unit_list = buildLengthUnitList();
143 PopulateComboBox(heightunitscombo_, unit_list);
144 PopulateComboBox(widthunitscombo_, unit_list);
146 // the bounding box page
147 leftbottomxspin_->signal_changed().connect(
148 sigc::mem_fun(*this, &GGraphics::onBBChange));
149 leftbottomyspin_->signal_changed().connect(
150 sigc::mem_fun(*this, &GGraphics::onBBChange));
151 righttopxspin_->signal_changed().connect(
152 sigc::mem_fun(*this, &GGraphics::onBBChange));
153 righttopyspin_->signal_changed().connect(
154 sigc::mem_fun(*this, &GGraphics::onBBChange));
155 bbunitscombo_->signal_changed().connect(
156 sigc::mem_fun(*this, &GGraphics::onBBChange));
157 clipcheck_->signal_toggled().connect(
158 sigc::mem_fun(*this, &GGraphics::onBBChange));
160 bbfromfilebutton_->signal_clicked().connect(
161 sigc::mem_fun(*this, &GGraphics::onBBFromFileClicked));
163 // disable for read-only documents
164 bcview().addReadOnly(bbfromfilebutton_);
165 bcview().addReadOnly(clipcheck_);
166 PopulateComboBox(bbunitscombo_, getBBUnits());
171 // disable for read-only documents
172 bcview().addReadOnly(anglespin_);
173 bcview().addReadOnly(origincombo_);
174 bcview().addReadOnly(subfigcheck_);
175 bcview().addReadOnly(latexoptsentry_);
176 bcview().addReadOnly(draftcheck_);
177 bcview().addReadOnly(unzipcheck_);
179 anglespin_->signal_changed().connect(
180 sigc::mem_fun(*this, &GGraphics::onInput));
181 origincombo_->signal_changed().connect(
182 sigc::mem_fun(*this, &GGraphics::onInput));
183 subfigentry_->signal_changed().connect(
184 sigc::mem_fun(*this, &GGraphics::onInput));
185 latexoptsentry_->signal_changed().connect(
186 sigc::mem_fun(*this, &GGraphics::onInput));
187 draftcheck_->signal_toggled().connect(
188 sigc::mem_fun(*this, &GGraphics::onInput));
189 unzipcheck_->signal_toggled().connect(
190 sigc::mem_fun(*this, &GGraphics::onInput));
192 subfigcheck_->signal_toggled().connect(
193 sigc::mem_fun(*this, &GGraphics::onSubFigCheckToggled));
195 vector<RotationOriginPair> origindata = getRotationOriginData();
197 // Store the identifiers for later
198 origins_ = getSecond(origindata);
199 PopulateComboBox(origincombo_, getFirst(origindata));
203 void GGraphics::onSizingModeChange()
205 bool const scalingmode = setscalingradio_->get_active();
207 outputscalespin_->set_sensitive(scalingmode);
208 widthspin_->set_sensitive(!scalingmode);
209 heightspin_->set_sensitive(!scalingmode);
210 widthunitscombo_->set_sensitive(!scalingmode);
211 heightunitscombo_->set_sensitive(!scalingmode);
212 aspectcheck_->set_sensitive(!scalingmode);
213 bc().input(ButtonPolicy::SMI_VALID);
217 void GGraphics::PopulateComboBox(Gtk::ComboBox * combo,
218 vector<string> const & strings)
220 Glib::RefPtr<Gtk::ListStore> model = Gtk::ListStore::create(cols_);
221 vector<string>::const_iterator it = strings.begin();
222 vector<string>::const_iterator end = strings.end();
223 for (int rowindex = 0; it != end; ++it, ++rowindex) {
224 Gtk::TreeModel::iterator row = model->append();
225 (*row)[stringcol_] = *it;
228 combo->set_model(model);
229 Gtk::CellRendererText * cell = Gtk::manage(new Gtk::CellRendererText);
230 combo->pack_start(*cell, true);
231 combo->add_attribute(*cell, "text", 0);
235 void GGraphics::apply()
237 // Create the parameters structure and fill the data from the dialog.
238 InsetGraphicsParams & igp = controller().params();
241 igp.filename.set(fileentry_->get_text(),
242 kernel().bufferFilepath());
245 static_cast<int>(displayscalespin_->get_adjustment()->get_value());
246 if (igp.lyxscale == 0) {
250 switch (displaycombo_->get_active_row_number()) {
252 igp.display = graphics::NoDisplay;
255 igp.display = graphics::ColorDisplay;
258 igp.display = graphics::GrayscaleDisplay;
261 igp.display = graphics::MonochromeDisplay;
264 igp.display = graphics::DefaultDisplay;
267 if (setscalingradio_->get_active()) {
268 igp.scale = outputscalespin_->get_adjustment()->get_value();
269 if (float_equal(igp.scale, 0.0, 0.05))
271 igp.width = LyXLength();
274 Glib::ustring const widthunit =
275 (*widthunitscombo_->get_active())[stringcol_];
276 igp.width = LyXLength(widthspin_->get_text() + widthunit);
280 Glib::ustring const heightunit =
281 (*heightunitscombo_->get_active())[stringcol_];
282 igp.height = LyXLength(heightspin_->get_text() + heightunit);
284 igp.keepAspectRatio = aspectcheck_->get_active();
285 igp.draft = draftcheck_->get_active();
286 igp.noUnzip = !unzipcheck_->get_active();
290 if (!controller().bbChanged) {
291 // don't write anything
294 Glib::ustring const bbunit = (*bbunitscombo_->get_active())[stringcol_];
297 if (leftbottomxspin_->get_text().empty())
300 bb = leftbottomxspin_->get_text() + bbunit;
304 if (leftbottomyspin_->get_text().empty())
307 bb += leftbottomyspin_->get_text() + bbunit;
311 if (righttopxspin_->get_text().empty())
314 bb += righttopxspin_->get_text() + bbunit;
318 if (righttopyspin_->get_text().empty())
321 bb += righttopyspin_->get_text() + bbunit;
323 /// The bounding box with "xLB yLB yRT yRT ", divided by a space!
326 igp.clip = clipcheck_->get_active();
329 igp.rotateAngle = anglespin_->get_adjustment()->get_value();
331 int const origin_pos = origincombo_->get_active_row_number();
332 igp.rotateOrigin = origins_[origin_pos];
334 igp.subcaption = subfigcheck_->get_active();
335 igp.subcaptionText = subfigentry_->get_text();
337 igp.special = latexoptsentry_->get_text();
341 void GGraphics::update() {
342 // set the right default unit
343 defaultUnit = getDefaultUnit();
345 // Update dialog with details from inset
346 InsetGraphicsParams & igp = controller().params();
350 igp.filename.outputFilename(kernel().bufferFilepath());
351 fileentry_->set_text(name);
352 displayscalespin_->get_adjustment()->set_value(igp.lyxscale);
355 switch (igp.display) {
356 case graphics::NoDisplay:
357 displaycombo_->set_active(4);
359 case graphics::ColorDisplay:
360 displaycombo_->set_active(3);
362 case graphics::GrayscaleDisplay:
363 displaycombo_->set_active(2);
365 case graphics::MonochromeDisplay:
366 displaycombo_->set_active(1);
368 case graphics::DefaultDisplay:
369 displaycombo_->set_active(0);
372 outputscalespin_->get_adjustment()->set_value(igp.scale);
373 widthspin_->get_adjustment()->set_value(igp.width.value());
374 unitsComboFromLength(widthunitscombo_, stringcol_,
375 igp.width, defaultUnit);
376 heightspin_->get_adjustment()->set_value(igp.height.value());
377 unitsComboFromLength(heightunitscombo_, stringcol_,
378 igp.height, defaultUnit);
380 if (!float_equal(igp.scale, 0.0, 0.05)) {
381 // scaling sizing mode
382 setscalingradio_->set_active(true);
384 setsizeradio_->set_active(true);
386 onSizingModeChange();
388 aspectcheck_->set_active(igp.keepAspectRatio);
389 draftcheck_->set_active(igp.draft);
390 unzipcheck_->set_active(!igp.noUnzip);
393 // set the bounding box values, if exists. First we need the whole
394 // path, because the controller knows nothing about the doc-dir
395 updateBB(igp.filename.absFilename(), igp.bb);
396 clipcheck_->set_active(igp.clip);
399 anglespin_->get_adjustment()->set_value(igp.rotateAngle);
402 if (igp.rotateOrigin.empty()) {
405 origin_pos = findPos(origins_, igp.rotateOrigin);
407 origincombo_->set_active(origin_pos);
410 subfigcheck_->set_active(igp.subcaption);
411 subfigentry_->set_text(igp.subcaptionText);
412 subfigentry_->set_sensitive(subfigcheck_->get_active());
413 latexoptsentry_->set_text(igp.special);
415 // open dialog in the file-tab, whenever filename is empty
416 if (igp.filename.empty()) {
417 notebook_->set_current_page(0);
421 bc().input(ButtonPolicy::SMI_INVALID);
425 void GGraphics::updateBB(string const & filename, string const & bb_inset)
427 // Update dialog with details from inset
428 // set the bounding box values, if exists. First we need the whole
429 // path, because the controller knows nothing about the doc-dir
431 if (bb_inset.empty()) {
432 lyxerr[Debug::GRAPHICS]
433 << "GGraphics::updateBB() [no BoundingBox]\n";
434 string const bb = controller().readBB(filename);
436 // get the values from the file
437 // in this case we always have the point-unit
438 leftbottomxspin_->set_text(token(bb, ' ', 0));
439 leftbottomyspin_->set_text(token(bb, ' ', 1));
440 righttopxspin_->set_text(token(bb, ' ', 2));
441 righttopyspin_->set_text(token(bb, ' ', 3));
444 leftbottomxspin_->set_text("");
445 leftbottomyspin_->set_text("");
446 righttopxspin_->set_text("");
447 righttopyspin_->set_text("");
449 unitsComboFromLength(bbunitscombo_, stringcol_,
450 LyXLength("bp"), defaultUnit);
452 // get the values from the inset
453 lyxerr[Debug::GRAPHICS]
454 << "FormGraphics::updateBB(): igp has BoundingBox"
455 << " ["<< bb_inset << "]\n";
458 anyLength = LyXLength(token(bb_inset, ' ', 0));
460 unitsComboFromLength(bbunitscombo_, stringcol_, anyLength, defaultUnit);
462 leftbottomxspin_->get_adjustment()->set_value(anyLength.value());
464 anyLength = LyXLength(token(bb_inset, ' ', 1));
465 leftbottomyspin_->get_adjustment()->set_value(anyLength.value());
467 anyLength = LyXLength(token(bb_inset, ' ', 2));
468 righttopxspin_->get_adjustment()->set_value(anyLength.value());
470 anyLength = LyXLength(token(bb_inset, ' ', 3));
471 righttopyspin_->get_adjustment()->set_value(anyLength.value());
473 controller().bbChanged = false;
477 void GGraphics::onBrowseClicked()
479 // Get the filename from the dialog
480 string const in_name = fileentry_->get_text();
481 string const out_name = controller().browse(in_name);
482 lyxerr[Debug::GRAPHICS]
483 << "[FormGraphics]out_name: " << out_name << "\n";
484 if (out_name != in_name && !out_name.empty()) {
485 fileentry_->set_text(out_name);
487 if (controller().isFilenameValid(out_name) &&
488 !controller().bbChanged) {
489 updateBB(out_name, string());
492 bc().input(ButtonPolicy::SMI_VALID);
496 void GGraphics::onBBChange()
498 controller().bbChanged = true;
499 bc().input(ButtonPolicy::SMI_VALID);
503 void GGraphics::onBBFromFileClicked()
505 string const filename = fileentry_->get_text();
506 if (!filename.empty()) {
507 string bb = controller().readBB(filename);
509 leftbottomxspin_->set_text(token(bb, ' ', 0));
510 leftbottomyspin_->set_text(token(bb, ' ', 1));
511 righttopxspin_->set_text(token(bb, ' ', 2));
512 righttopyspin_->set_text(token(bb, ' ', 3));
513 unitsComboFromLength(bbunitscombo_, stringcol_,
514 LyXLength("bp"), defaultUnit);
516 controller().bbChanged = false;
518 leftbottomxspin_->set_text("");
519 leftbottomyspin_->set_text("");
520 righttopxspin_->set_text("");
521 righttopyspin_->set_text("");
522 unitsComboFromLength(bbunitscombo_, stringcol_,
523 LyXLength("bp"), defaultUnit);
525 bc().input(ButtonPolicy::SMI_VALID);
529 void GGraphics::onSubFigCheckToggled()
531 subfigentry_->set_sensitive(subfigcheck_->get_active());
532 bc().input(ButtonPolicy::SMI_VALID);
536 void GGraphics::onEditClicked()
538 controller().editGraphics();
542 void GGraphics::onInput()
544 bc().input(ButtonPolicy::SMI_VALID);
547 } // namespace frontend