diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:29:01 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:29:01 +0000 |
commit | 35a96bde514a8897f6f0fcc41c5833bf63df2e2a (patch) | |
tree | 657d15a03cc46bd099fc2c6546a7a4ad43815d9f /src/ui/widget/page-sizer.cpp | |
parent | Initial commit. (diff) | |
download | inkscape-upstream.tar.xz inkscape-upstream.zip |
Adding upstream version 1.0.2.upstream/1.0.2upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/ui/widget/page-sizer.cpp')
-rw-r--r-- | src/ui/widget/page-sizer.cpp | 781 |
1 files changed, 781 insertions, 0 deletions
diff --git a/src/ui/widget/page-sizer.cpp b/src/ui/widget/page-sizer.cpp new file mode 100644 index 0000000..d869a1c --- /dev/null +++ b/src/ui/widget/page-sizer.cpp @@ -0,0 +1,781 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/** + * @file + * + * Paper-size widget and helper functions + */ +/* + * Authors: + * bulia byak <buliabyak@users.sf.net> + * Lauris Kaplinski <lauris@kaplinski.com> + * Jon Phillips <jon@rejon.org> + * Ralf Stephan <ralf@ark.in-berlin.de> (Gtkmm) + * Bob Jamison <ishmal@users.sf.net> + * Abhishek Sharma + * + * Copyright (C) 2000 - 2006 Authors + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include "page-sizer.h" +#include "pages-skeleton.h" +#include <glib.h> +#include <glibmm/i18n.h> +#include "verbs.h" +#include "helper/action.h" +#include "object/sp-root.h" +#include "io/resource.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + + +//######################################################################## +//# P A G E S I Z E R +//######################################################################## + +/** + * Constructor + */ +PageSizer::PageSizer(Registry & _wr) + : Gtk::VBox(false,4), + _dimensionUnits( _("U_nits:"), "units", _wr ), + _dimensionWidth( _("_Width:"), _("Width of paper"), "width", _dimensionUnits, _wr ), + _dimensionHeight( _("_Height:"), _("Height of paper"), "height", _dimensionUnits, _wr ), + _marginLock( _("Loc_k margins"), _("Lock margins"), "lock-margins", _wr, false, nullptr, nullptr), + _lock_icon(), + _marginTop( _("T_op:"), _("Top margin"), "fit-margin-top", _wr ), + _marginLeft( _("L_eft:"), _("Left margin"), "fit-margin-left", _wr), + _marginRight( _("Ri_ght:"), _("Right margin"), "fit-margin-right", _wr), + _marginBottom( _("Botto_m:"), _("Bottom margin"), "fit-margin-bottom", _wr), + _lockMarginUpdate(false), + _scaleX(_("Scale _x:"), _("Scale X"), "scale-x", _wr), + _scaleY(_("Scale _y:"), _("While SVG allows non-uniform scaling it is recommended to use only uniform scaling in Inkscape. To set a non-uniform scaling, set the 'viewBox' directly."), "scale-y", _wr), + _lockScaleUpdate(false), + _viewboxX(_("X:"), _("X"), "viewbox-x", _wr), + _viewboxY(_("Y:"), _("Y"), "viewbox-y", _wr), + _viewboxW(_("Width:"), _("Width"), "viewbox-width", _wr), + _viewboxH(_("Height:"), _("Height"), "viewbox-height", _wr), + _lockViewboxUpdate(false), + _widgetRegistry(&_wr) +{ + // set precision of scalar entry boxes + _wr.setUpdating (true); + _dimensionWidth.setDigits(5); + _dimensionHeight.setDigits(5); + _marginTop.setDigits(5); + _marginLeft.setDigits(5); + _marginRight.setDigits(5); + _marginBottom.setDigits(5); + _scaleX.setDigits(5); + _scaleY.setDigits(5); + _viewboxX.setDigits(5); + _viewboxY.setDigits(5); + _viewboxW.setDigits(5); + _viewboxH.setDigits(5); + _dimensionWidth.setRange( 0.00001, 10000000 ); + _dimensionHeight.setRange( 0.00001, 10000000 ); + _scaleX.setRange( 0.00001, 100000 ); + _scaleY.setRange( 0.00001, 100000 ); + _viewboxX.setRange( -10000000, 10000000 ); + _viewboxY.setRange( -10000000, 10000000 ); + _viewboxW.setRange( 0.00001, 10000000 ); + _viewboxH.setRange( 0.00001, 10000000 ); + + _scaleY.set_sensitive (false); // We only want to display Y scale. + + _wr.setUpdating (false); + + //# Set up the Paper Size combo box + _paperSizeListStore = Gtk::ListStore::create(_paperSizeListColumns); + _paperSizeList.set_model(_paperSizeListStore); + _paperSizeList.append_column(_("Name"), + _paperSizeListColumns.nameColumn); + _paperSizeList.append_column(_("Description"), + _paperSizeListColumns.descColumn); + _paperSizeList.set_headers_visible(false); + _paperSizeListSelection = _paperSizeList.get_selection(); + _paper_size_list_connection = + _paperSizeListSelection->signal_changed().connect ( + sigc::mem_fun (*this, &PageSizer::on_paper_size_list_changed)); + _paperSizeListScroller.add(_paperSizeList); + _paperSizeListScroller.set_shadow_type(Gtk::SHADOW_IN); + _paperSizeListScroller.set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_ALWAYS); + _paperSizeListScroller.set_size_request(-1, 130); + + + char *path = Inkscape::IO::Resource::profile_path("pages.csv"); + if (!g_file_test(path, G_FILE_TEST_EXISTS)) { + if (!g_file_set_contents(path, pages_skeleton, -1, nullptr)) { + g_warning("%s", _("Failed to create the page file.")); + } + } + + gchar *content = nullptr; + if (g_file_get_contents(path, &content, nullptr, nullptr)) { + + gchar **lines = g_strsplit_set(content, "\n", 0); + + for (int i = 0; lines && lines[i]; ++i) { + gchar **line = g_strsplit_set(lines[i], ",", 5); + if (!line[0] || !line[1] || !line[2] || !line[3] || line[0][0]=='#') + continue; + //name, width, height, unit + double width = g_ascii_strtod(line[1], nullptr); + double height = g_ascii_strtod(line[2], nullptr); + g_strstrip(line[0]); + g_strstrip(line[3]); + Glib::ustring name = line[0]; + char formatBuf[80]; + snprintf(formatBuf, 79, "%0.1f x %0.1f", width, height); + Glib::ustring desc = formatBuf; + desc.append(" " + std::string(line[3])); + PaperSize paper(name, width, height, Inkscape::Util::unit_table.getUnit(line[3])); + _paperSizeTable[name] = paper; + Gtk::TreeModel::Row row = *(_paperSizeListStore->append()); + row[_paperSizeListColumns.nameColumn] = name; + row[_paperSizeListColumns.descColumn] = desc; + g_strfreev(line); + } + g_strfreev(lines); + g_free(content); + } + g_free(path); + + pack_start (_paperSizeListScroller, true, true, 0); + + //## Set up orientation radio buttons + pack_start (_orientationBox, false, false, 0); + _orientationLabel.set_label(_("Orientation:")); + _orientationBox.pack_start(_orientationLabel, false, false, 0); + _landscapeButton.set_use_underline(); + _landscapeButton.set_label(_("_Landscape")); + _landscapeButton.set_active(true); + Gtk::RadioButton::Group group = _landscapeButton.get_group(); + _orientationBox.pack_end (_landscapeButton, false, false, 5); + _portraitButton.set_use_underline(); + _portraitButton.set_label(_("_Portrait")); + _portraitButton.set_active(true); + _orientationBox.pack_end (_portraitButton, false, false, 5); + _portraitButton.set_group (group); + _portraitButton.set_active (true); + + // Setting default custom unit to document unit + SPDesktop *dt = SP_ACTIVE_DESKTOP; + SPNamedView *nv = dt->getNamedView(); + _wr.setUpdating (true); + if (nv->page_size_units) { + _dimensionUnits.setUnit(nv->page_size_units->abbr); + } else if (nv->display_units) { + _dimensionUnits.setUnit(nv->display_units->abbr); + } + _wr.setUpdating (false); + + + //## Set up custom size frame + _customFrame.set_label(_("Custom size")); + pack_start (_customFrame, false, false, 0); + _customFrame.add(_customDimTable); + + _customDimTable.set_border_width(4); + _customDimTable.set_row_spacing(4); + _customDimTable.set_column_spacing(4); + + _dimensionHeight.set_halign(Gtk::ALIGN_CENTER); + _dimensionUnits.set_halign(Gtk::ALIGN_END); + _customDimTable.attach(_dimensionWidth, 0, 0, 1, 1); + _customDimTable.attach(_dimensionHeight, 1, 0, 1, 1); + _customDimTable.attach(_dimensionUnits, 2, 0, 1, 1); + + _customDimTable.attach(_fitPageMarginExpander, 0, 1, 3, 1); + + //## Set up fit page expander + _fitPageMarginExpander.set_use_underline(); + _fitPageMarginExpander.set_label(_("Resi_ze page to content...")); + _fitPageMarginExpander.add(_marginTable); + + _marginTable.set_border_width(4); + _marginTable.set_row_spacing(4); + _marginTable.set_column_spacing(4); + + //### margin label and lock button + _marginLabel.set_markup(Glib::ustring("<b><i>") + _("Margins") + "</i></b>"); + _marginLabel.set_halign(Gtk::ALIGN_CENTER); + + _lock_icon.set_from_icon_name("object-unlocked", Gtk::ICON_SIZE_LARGE_TOOLBAR); + _lock_icon.show(); + _marginLock.set_active(false); + _marginLock.add(_lock_icon); + + _marginBox.set_spacing(4); + _marginBox.add(_marginLabel); + _marginBox.add(_marginLock); + _marginBox.set_halign(Gtk::ALIGN_CENTER); + _marginTable.attach(_marginBox, 1, 1, 1, 1); + + //### margins + _marginTop.set_halign(Gtk::ALIGN_CENTER); + _marginLeft.set_halign(Gtk::ALIGN_START); + _marginRight.set_halign(Gtk::ALIGN_END); + _marginBottom.set_halign(Gtk::ALIGN_CENTER); + + _marginTable.attach(_marginTop, 0, 0, 3, 1); + _marginTable.attach(_marginLeft, 0, 1, 1, 1); + _marginTable.attach(_marginRight, 2, 1, 1, 1); + _marginTable.attach(_marginBottom, 0, 2, 3, 1); + + //### fit page to drawing button + _fitPageButton.set_use_underline(); + _fitPageButton.set_label(_("_Resize page to drawing or selection (Ctrl+Shift+R)")); + _fitPageButton.set_tooltip_text(_("Resize the page to fit the current selection, or the entire drawing if there is no selection")); + + _fitPageButton.set_hexpand(); + _fitPageButton.set_halign(Gtk::ALIGN_CENTER); + _marginTable.attach(_fitPageButton, 0, 3, 3, 1); + + + //## Set up scale frame + _scaleFrame.set_label(_("Scale")); + pack_start (_scaleFrame, false, false, 0); + _scaleFrame.add(_scaleTable); + + _scaleTable.set_border_width(4); + _scaleTable.set_row_spacing(4); + _scaleTable.set_column_spacing(4); + + _scaleTable.attach(_scaleX, 0, 0, 1, 1); + _scaleTable.attach(_scaleY, 1, 0, 1, 1); + _scaleTable.attach(_scaleLabel, 2, 0, 1, 1); + + _viewboxExpander.set_hexpand(); + _scaleTable.attach(_viewboxExpander, 0, 2, 3, 1); + + _viewboxExpander.set_use_underline(); + _viewboxExpander.set_label(_("_Viewbox...")); + _viewboxExpander.add(_viewboxTable); + + _viewboxTable.set_border_width(4); + _viewboxTable.set_row_spacing(4); + _viewboxTable.set_column_spacing(4); + + _viewboxX.set_halign(Gtk::ALIGN_END); + _viewboxY.set_halign(Gtk::ALIGN_END); + _viewboxW.set_halign(Gtk::ALIGN_END); + _viewboxH.set_halign(Gtk::ALIGN_END); + _viewboxSpacer.set_hexpand(); + _viewboxTable.attach(_viewboxX, 0, 0, 1, 1); + _viewboxTable.attach(_viewboxY, 1, 0, 1, 1); + _viewboxTable.attach(_viewboxW, 0, 1, 1, 1); + _viewboxTable.attach(_viewboxH, 1, 1, 1, 1); + _viewboxTable.attach(_viewboxSpacer, 2, 0, 3, 1); + + _wr.setUpdating (true); + updateScaleUI(); + _wr.setUpdating (false); +} + + +/** + * Destructor + */ +PageSizer::~PageSizer() += default; + + + +/** + * Initialize or reset this widget + */ +void +PageSizer::init () +{ + _landscape_connection = _landscapeButton.signal_toggled().connect (sigc::mem_fun (*this, &PageSizer::on_landscape)); + _portrait_connection = _portraitButton.signal_toggled().connect (sigc::mem_fun (*this, &PageSizer::on_portrait)); + _changedw_connection = _dimensionWidth.signal_value_changed().connect (sigc::mem_fun (*this, &PageSizer::on_value_changed)); + _changedh_connection = _dimensionHeight.signal_value_changed().connect (sigc::mem_fun (*this, &PageSizer::on_value_changed)); + _changedu_connection = _dimensionUnits.getUnitMenu()->signal_changed().connect (sigc::mem_fun (*this, &PageSizer::on_units_changed)); + _fitPageButton.signal_clicked().connect(sigc::mem_fun(*this, &PageSizer::fire_fit_canvas_to_selection_or_drawing)); + _changeds_connection = _scaleX.signal_value_changed().connect (sigc::mem_fun (*this, &PageSizer::on_scale_changed)); + _changedvx_connection = _viewboxX.signal_value_changed().connect (sigc::mem_fun (*this, &PageSizer::on_viewbox_changed)); + _changedvy_connection = _viewboxY.signal_value_changed().connect (sigc::mem_fun (*this, &PageSizer::on_viewbox_changed)); + _changedvw_connection = _viewboxW.signal_value_changed().connect (sigc::mem_fun (*this, &PageSizer::on_viewbox_changed)); + _changedvh_connection = _viewboxH.signal_value_changed().connect (sigc::mem_fun (*this, &PageSizer::on_viewbox_changed)); + _changedlk_connection = _marginLock.signal_toggled().connect (sigc::mem_fun (*this, &PageSizer::on_margin_lock_changed)); + _changedmt_connection = _marginTop.signal_value_changed().connect (sigc::bind<RegisteredScalar*>(sigc::mem_fun (*this, &PageSizer::on_margin_changed), &_marginTop)); + _changedmb_connection = _marginBottom.signal_value_changed().connect (sigc::bind<RegisteredScalar*>(sigc::mem_fun (*this, &PageSizer::on_margin_changed), &_marginBottom)); + _changedml_connection = _marginLeft.signal_value_changed().connect (sigc::bind<RegisteredScalar*>(sigc::mem_fun (*this, &PageSizer::on_margin_changed), &_marginLeft)); + _changedmr_connection = _marginRight.signal_value_changed().connect (sigc::bind<RegisteredScalar*>(sigc::mem_fun (*this, &PageSizer::on_margin_changed), &_marginRight)); + show_all_children(); +} + + +/** + * Set document dimensions (if not called by Doc prop's update()) and + * set the PageSizer's widgets and text entries accordingly. If + * 'changeList' is true, then adjust the paperSizeList to show the closest + * standard page size. + * + * \param w, h + * \param changeList whether to modify the paper size list + */ +void +PageSizer::setDim (Inkscape::Util::Quantity w, Inkscape::Util::Quantity h, bool changeList, bool changeSize) +{ + static bool _called = false; + if (_called) { + return; + } + + _called = true; + + _paper_size_list_connection.block(); + _landscape_connection.block(); + _portrait_connection.block(); + _changedw_connection.block(); + _changedh_connection.block(); + + _unit = w.unit->abbr; + + if (SP_ACTIVE_DESKTOP && !_widgetRegistry->isUpdating()) { + SPDocument *doc = SP_ACTIVE_DESKTOP->getDocument(); + Inkscape::Util::Quantity const old_height = doc->getHeight(); + doc->setWidthAndHeight (w, h, changeSize); + // The origin for the user is in the lower left corner; this point should remain stationary when + // changing the page size. The SVG's origin however is in the upper left corner, so we must compensate for this + if (changeSize && !doc->is_yaxisdown()) { + Geom::Translate const vert_offset(Geom::Point(0, (old_height.value("px") - h.value("px")))); + doc->getRoot()->translateChildItems(vert_offset); + } + DocumentUndo::done(doc, SP_VERB_NONE, _("Set page size")); + } + + if ( w != h ) { + _landscapeButton.set_sensitive(true); + _portraitButton.set_sensitive (true); + _landscape = ( w > h ); + _landscapeButton.set_active(_landscape ? true : false); + _portraitButton.set_active (_landscape ? false : true); + } else { + _landscapeButton.set_sensitive(false); + _portraitButton.set_sensitive (false); + } + + if (changeList) + { + Gtk::TreeModel::Row row = (*find_paper_size(w, h)); + if (row) + _paperSizeListSelection->select(row); + } + + _dimensionWidth.setUnit(w.unit->abbr); + _dimensionWidth.setValue (w.quantity); + _dimensionHeight.setUnit(h.unit->abbr); + _dimensionHeight.setValue (h.quantity); + + + _paper_size_list_connection.unblock(); + _landscape_connection.unblock(); + _portrait_connection.unblock(); + _changedw_connection.unblock(); + _changedh_connection.unblock(); + + _called = false; +} + +/** + * Updates the scalar widgets for the fit margins. (Just changes the value + * of the ui widgets to match the xml). + */ +void +PageSizer::updateFitMarginsUI(Inkscape::XML::Node *nv_repr) +{ + if (!_lockMarginUpdate) { + double value = 0.0; + if (sp_repr_get_double(nv_repr, "fit-margin-top", &value)) { + _marginTop.setValue(value); + } + if (sp_repr_get_double(nv_repr, "fit-margin-left", &value)) { + _marginLeft.setValue(value); + } + if (sp_repr_get_double(nv_repr, "fit-margin-right", &value)) { + _marginRight.setValue(value); + } + if (sp_repr_get_double(nv_repr, "fit-margin-bottom", &value)) { + _marginBottom.setValue(value); + } + } +} + + +/** + * Returns an iterator pointing to a row in paperSizeListStore which + * contains a paper of the specified size, or + * paperSizeListStore->children().end() if no such paper exists. + * + * The code is not tested for the case where w and h have different units. + */ +Gtk::ListStore::iterator +PageSizer::find_paper_size (Inkscape::Util::Quantity w, Inkscape::Util::Quantity h) const +{ + // The code below assumes that w < h, so make sure that's the case: + if ( h < w ) { + std::swap(h,w); + } + + std::map<Glib::ustring, PaperSize>::const_iterator iter; + for (iter = _paperSizeTable.begin() ; + iter != _paperSizeTable.end() ; ++iter) { + PaperSize paper = iter->second; + Inkscape::Util::Quantity smallX (paper.smaller, paper.unit); + Inkscape::Util::Quantity largeX (paper.larger, paper.unit); + + // account for landscape formats (e.g. business cards) + if (largeX < smallX) { + std::swap(largeX, smallX); + } + + if ( are_near(w, smallX, 0.1) && are_near(h, largeX, 0.1) ) { + Gtk::ListStore::iterator p = _paperSizeListStore->children().begin(); + Gtk::ListStore::iterator pend = _paperSizeListStore->children().end(); + // We need to search paperSizeListStore explicitly for the + // specified paper size because it is sorted in a different + // way than paperSizeTable (which is sorted alphabetically) + for ( ; p != pend; ++p) { + if ((*p)[_paperSizeListColumns.nameColumn] == paper.name) { + return p; + } + } + } + } + return _paperSizeListStore->children().end(); +} + + + +/** + * Tell the desktop to fit the page size to the selection or drawing. + */ +void +PageSizer::fire_fit_canvas_to_selection_or_drawing() +{ + SPDesktop *dt = SP_ACTIVE_DESKTOP; + if (!dt) { + return; + } + SPDocument *doc; + SPNamedView *nv; + Inkscape::XML::Node *nv_repr; + + if ((doc = SP_ACTIVE_DESKTOP->getDocument()) + && (nv = sp_document_namedview(doc, nullptr)) + && (nv_repr = nv->getRepr())) { + _lockMarginUpdate = true; + sp_repr_set_svg_double(nv_repr, "fit-margin-top", _marginTop.getValue()); + sp_repr_set_svg_double(nv_repr, "fit-margin-left", _marginLeft.getValue()); + sp_repr_set_svg_double(nv_repr, "fit-margin-right", _marginRight.getValue()); + sp_repr_set_svg_double(nv_repr, "fit-margin-bottom", _marginBottom.getValue()); + _lockMarginUpdate = false; + } + + Verb *verb = Verb::get( SP_VERB_FIT_CANVAS_TO_SELECTION_OR_DRAWING ); + if (verb) { + SPAction *action = verb->get_action(Inkscape::ActionContext(dt)); + if (action) { + sp_action_perform(action, nullptr); + } + } +} + + + +/** + * Paper Size list callback for when a user changes the selection + */ +void +PageSizer::on_paper_size_list_changed() +{ + //Glib::ustring name = _paperSizeList.get_active_text(); + Gtk::TreeModel::iterator miter = _paperSizeListSelection->get_selected(); + if(!miter) + { + //error? + return; + } + Gtk::TreeModel::Row row = *miter; + Glib::ustring name = row[_paperSizeListColumns.nameColumn]; + std::map<Glib::ustring, PaperSize>::const_iterator piter = + _paperSizeTable.find(name); + if (piter == _paperSizeTable.end()) { + g_warning("paper size '%s' not found in table", name.c_str()); + return; + } + PaperSize paper = piter->second; + Inkscape::Util::Quantity w = Inkscape::Util::Quantity(paper.smaller, paper.unit); + Inkscape::Util::Quantity h = Inkscape::Util::Quantity(paper.larger, paper.unit); + + if ( w > h ) { + // enforce landscape mode if this is desired for the given page format + _landscape = true; + } else { + // otherwise we keep the current mode + _landscape = _landscapeButton.get_active(); + } + + if ((_landscape && (w < h)) || (!_landscape && (w > h))) + setDim (h, w, false); + else + setDim (w, h, false); + +} + + +/** + * Portrait button callback + */ +void +PageSizer::on_portrait() +{ + if (!_portraitButton.get_active()) + return; + Inkscape::Util::Quantity w = Inkscape::Util::Quantity(_dimensionWidth.getValue(""), _dimensionWidth.getUnit()); + Inkscape::Util::Quantity h = Inkscape::Util::Quantity(_dimensionHeight.getValue(""), _dimensionHeight.getUnit()); + if (h < w) { + setDim (h, w); + } +} + + +/** + * Landscape button callback + */ +void +PageSizer::on_landscape() +{ + if (!_landscapeButton.get_active()) + return; + Inkscape::Util::Quantity w = Inkscape::Util::Quantity(_dimensionWidth.getValue(""), _dimensionWidth.getUnit()); + Inkscape::Util::Quantity h = Inkscape::Util::Quantity(_dimensionHeight.getValue(""), _dimensionHeight.getUnit()); + if (w < h) { + setDim (h, w); + } +} + + +/** + * Update scale widgets + */ +void +PageSizer::updateScaleUI() +{ + + static bool _called = false; + if (_called) { + return; + } + + _called = true; + + _changeds_connection.block(); + _changedvx_connection.block(); + _changedvy_connection.block(); + _changedvw_connection.block(); + _changedvh_connection.block(); + + SPDesktop *dt = SP_ACTIVE_DESKTOP; + if (dt) { + SPDocument *doc = dt->getDocument(); + + // Update scale + Geom::Scale scale = doc->getDocumentScale(); + SPNamedView *nv = dt->getNamedView(); + + std::stringstream ss; + ss << _("User units per ") << nv->display_units->abbr << "." ; + _scaleLabel.set_text( ss.str() ); + + if( !_lockScaleUpdate ) { + + double scaleX_inv = + Inkscape::Util::Quantity::convert( scale[Geom::X], "px", nv->display_units ); + if( scaleX_inv > 0 ) { + _scaleX.setValue(1.0/scaleX_inv); + } else { + // Should never happen + std::cerr << "PageSizer::updateScaleUI(): Invalid scale value: " << scaleX_inv << std::endl; + _scaleX.setValue(1.0); + } + } + + { // Don't need to lock as scaleY widget not linked to callback. + double scaleY_inv = + Inkscape::Util::Quantity::convert( scale[Geom::Y], "px", nv->display_units ); + if( scaleY_inv > 0 ) { + _scaleY.setValue(1.0/scaleY_inv); + } else { + // Should never happen + std::cerr << "PageSizer::updateScaleUI(): Invalid scale value: " << scaleY_inv << std::endl; + _scaleY.setValue(1.0); + } + } + + if( !_lockViewboxUpdate ) { + Geom::Rect viewBox = doc->getViewBox(); + _viewboxX.setValue( viewBox.min()[Geom::X] ); + _viewboxY.setValue( viewBox.min()[Geom::Y] ); + _viewboxW.setValue( viewBox.width() ); + _viewboxH.setValue( viewBox.height() ); + } + + } else { + // Should never happen + std::cerr << "PageSizer::updateScaleUI(): No active desktop." << std::endl; + _scaleLabel.set_text( "Unknown scale" ); + } + + _changeds_connection.unblock(); + _changedvx_connection.unblock(); + _changedvy_connection.unblock(); + _changedvw_connection.unblock(); + _changedvh_connection.unblock(); + + _called = false; +} + + +/** + * Callback for the dimension widgets + */ +void +PageSizer::on_value_changed() +{ + if (_widgetRegistry->isUpdating()) return; + if (_unit != _dimensionUnits.getUnit()->abbr) return; + setDim (Inkscape::Util::Quantity(_dimensionWidth.getValue(""), _dimensionUnits.getUnit()), + Inkscape::Util::Quantity(_dimensionHeight.getValue(""), _dimensionUnits.getUnit())); +} + +void +PageSizer::on_units_changed() +{ + if (_widgetRegistry->isUpdating()) return; + _unit = _dimensionUnits.getUnit()->abbr; + setDim (Inkscape::Util::Quantity(_dimensionWidth.getValue(""), _dimensionUnits.getUnit()), + Inkscape::Util::Quantity(_dimensionHeight.getValue(""), _dimensionUnits.getUnit()), + true, false); +} + +/** + * Callback for scale widgets + */ +void +PageSizer::on_scale_changed() +{ + if (_widgetRegistry->isUpdating()) return; + + double value = _scaleX.getValue(); + if( value > 0 ) { + + SPDesktop *dt = SP_ACTIVE_DESKTOP; + if (dt) { + SPDocument *doc = dt->getDocument(); + SPNamedView *nv = dt->getNamedView(); + + double scaleX_inv = Inkscape::Util::Quantity(1.0/value, nv->display_units ).value("px"); + + _lockScaleUpdate = true; + doc->setDocumentScale( 1.0/scaleX_inv ); + updateScaleUI(); + _lockScaleUpdate = false; + DocumentUndo::done(doc, SP_VERB_NONE, _("Set page scale")); + } + } +} + +/** + * Callback for viewbox widgets + */ +void +PageSizer::on_viewbox_changed() +{ + if (_widgetRegistry->isUpdating()) return; + + double viewboxX = _viewboxX.getValue(); + double viewboxY = _viewboxY.getValue(); + double viewboxW = _viewboxW.getValue(); + double viewboxH = _viewboxH.getValue(); + + if( viewboxW > 0 && viewboxH > 0) { + SPDesktop *dt = SP_ACTIVE_DESKTOP; + if (dt) { + SPDocument *doc = dt->getDocument(); + _lockViewboxUpdate = true; + doc->setViewBox( Geom::Rect::from_xywh( viewboxX, viewboxY, viewboxW, viewboxH ) ); + updateScaleUI(); + _lockViewboxUpdate = false; + DocumentUndo::done(doc, SP_VERB_NONE, _("Set 'viewBox'")); + } + } else { + std::cerr + << "PageSizer::on_viewbox_changed(): width and height must both be greater than zero." + << std::endl; + } +} + +void +PageSizer::on_margin_lock_changed() +{ + if (_marginLock.get_active()) { + _lock_icon.set_from_icon_name("object-locked", Gtk::ICON_SIZE_LARGE_TOOLBAR); + double left = _marginLeft.getValue(); + double right = _marginRight.getValue(); + double top = _marginTop.getValue(); + //double bottom = _marginBottom.getValue(); + if (Geom::are_near(left,right)) { + if (Geom::are_near(left, top)) { + on_margin_changed(&_marginBottom); + } else { + on_margin_changed(&_marginTop); + } + } else { + if (Geom::are_near(left, top)) { + on_margin_changed(&_marginRight); + } else { + on_margin_changed(&_marginLeft); + } + } + } else { + _lock_icon.set_from_icon_name("object-unlocked", Gtk::ICON_SIZE_LARGE_TOOLBAR); + } +} + +void +PageSizer::on_margin_changed(RegisteredScalar* widg) +{ + double value = widg->getValue(); + if (_widgetRegistry->isUpdating()) return; + if (_marginLock.get_active() && !_lockMarginUpdate) { + _lockMarginUpdate = true; + _marginLeft.setValue(value); + _marginRight.setValue(value); + _marginTop.setValue(value); + _marginBottom.setValue(value); + _lockMarginUpdate = false; + } +} + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : |