summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaximilian Albert <maximilian.albert@gmail.com>2008-09-04 16:44:24 +0000
committercilix42 <cilix42@users.sourceforge.net>2008-09-04 16:44:24 +0000
commit512fb4db32cc18cb1c286f7cdae0664e657d4684 (patch)
tree0ba34429153fec58f043876111d8e67ed13c7fb4
parentadd lpe param: VectorParam<float> and VectorParam<double> (diff)
downloadinkscape-512fb4db32cc18cb1c286f7cdae0664e657d4684.tar.gz
inkscape-512fb4db32cc18cb1c286f7cdae0664e657d4684.zip
Add a zoom correction option to preferences (used when zooming to 1:1 etc. to display items in their true sizes)
(bzr r6758)
-rw-r--r--src/preferences-skeleton.h1
-rw-r--r--src/ui/dialog/inkscape-preferences.cpp12
-rw-r--r--src/ui/dialog/inkscape-preferences.h1
-rw-r--r--src/ui/widget/preferences-widget.cpp206
-rw-r--r--src/ui/widget/preferences-widget.h44
-rw-r--r--src/verbs.cpp9
6 files changed, 266 insertions, 7 deletions
diff --git a/src/preferences-skeleton.h b/src/preferences-skeleton.h
index 78c79ebd1..3ca113e85 100644
--- a/src/preferences-skeleton.h
+++ b/src/preferences-skeleton.h
@@ -222,6 +222,7 @@ static char const preferences_skeleton[] =
" <group id=\"defaultscale\" value=\"2\"/>\n"
" <group id=\"maxrecentdocuments\" value=\"36\"/>\n"
" <group id=\"zoomincrement\" value=\"1.414213562\"/>\n"
+" <group id=\"zoomcorrection\" value=\"1.0\" unit=\"mm\"/>\n"
" <group id=\"keyscroll\" value=\"15\"/>\n"
" <group id=\"wheelscroll\" value=\"40\"/>\n"
" <group id=\"spacepans\" value=\"0\"/>\n"
diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp
index ef6c030e8..dcfc4e575 100644
--- a/src/ui/dialog/inkscape-preferences.cpp
+++ b/src/ui/dialog/inkscape-preferences.cpp
@@ -960,19 +960,23 @@ void InkscapePreferences::initPageUI()
_misc_small_toolbar.init( "toolbox", "small", sizeLabels, sizeValues, G_N_ELEMENTS(sizeLabels), 0 );
_page_ui.add_line( false, _("Commands bar icon size"), _misc_small_toolbar, "",
- _("Set the size for the commands toolbar to use (requires restart)"), false);
+ _("Set the size for the commands toolbar to use (requires restart)"), false);
_misc_small_secondary.init( "toolbox", "secondary", sizeLabels, sizeValues, G_N_ELEMENTS(sizeLabels), 1 );
_page_ui.add_line( false, _("Tool controls bar icon size"), _misc_small_secondary, "",
- _("Set the size for the secondary toolbar to use (requires restart)"), false);
+ _("Set the size for the secondary toolbar to use (requires restart)"), false);
_misc_small_tools.init( "toolbox.tools", "small", sizeLabels, sizeValues, G_N_ELEMENTS(sizeLabels), 0 );
_page_ui.add_line( false, _("Main toolbar icon size"), _misc_small_tools, "",
- _("Set the size for the main tools to use (requires restart)"), false);
+ _("Set the size for the main tools to use (requires restart)"), false);
_misc_recent.init("options.maxrecentdocuments", "value", 0.0, 1000.0, 1.0, 1.0, 1.0, true, false);
_page_ui.add_line( false, _("Maximum documents in Open Recent:"), _misc_recent, "",
- _("The maximum length of the Open Recent list in the File menu"), false);
+ _("The maximum length of the Open Recent list in the File menu"), false);
+
+ _ui_zoom_correction.init(300, 30, 1.00, 200.0, 1.0, 10.0, 1.0);
+ _page_ui.add_line( false, _("Zoom correction factor (in %):"), _ui_zoom_correction, "",
+ _("Adjust the slider until the length of the ruler on your screen matches its real length. This information is used when zooming to 1:1, 1:2, etc., to display objects in their true sizes"), true);
this->AddPage(_page_ui, _("Interface"), PREFS_PAGE_UI);
}
diff --git a/src/ui/dialog/inkscape-preferences.h b/src/ui/dialog/inkscape-preferences.h
index 2dd0ca4df..a6fc96a3f 100644
--- a/src/ui/dialog/inkscape-preferences.h
+++ b/src/ui/dialog/inkscape-preferences.h
@@ -166,6 +166,7 @@ protected:
PrefCheckButton _sel_layer_deselects;
PrefSpinButton _importexport_export, _misc_recent, _misc_simpl;
+ ZoomCorrRulerSlider _ui_zoom_correction;
PrefSpinButton _misc_latency_skew;
PrefCheckButton _misc_comment, _misc_forkvectors, _misc_scripts, _misc_namedicon_delay;
PrefCombo _misc_small_toolbar;
diff --git a/src/ui/widget/preferences-widget.cpp b/src/ui/widget/preferences-widget.cpp
index 6c5473caa..d4164864b 100644
--- a/src/ui/widget/preferences-widget.cpp
+++ b/src/ui/widget/preferences-widget.cpp
@@ -242,6 +242,212 @@ void PrefSpinButton::on_value_changed()
}
}
+const double ZoomCorrRuler::textsize = 7;
+const double ZoomCorrRuler::textpadding = 5;
+
+ZoomCorrRuler::ZoomCorrRuler(int width, int height) :
+ _unitconv(1.0),
+ _border(5)
+{
+ set_size(width, height);
+}
+
+void ZoomCorrRuler::set_size(int x, int y)
+{
+ _min_width = x;
+ _height = y;
+ set_size_request(x + _border*2, y + _border*2);
+}
+
+// The following two functions are borrowed from 2geom's toy-framework-2; if they are useful in
+// other locations, we should perhaps make them (or adapted versions of them) publicly available
+static void
+draw_text(cairo_t *cr, Geom::Point loc, const char* txt, bool bottom = "false",
+ double fontsize = ZoomCorrRuler::textsize, std::string fontdesc = "Sans") {
+ PangoLayout* layout = pango_cairo_create_layout (cr);
+ pango_layout_set_text(layout, txt, -1);
+
+ // set font and size
+ std::ostringstream sizestr;
+ sizestr << fontsize;
+ fontdesc = fontdesc + " " + sizestr.str();
+ PangoFontDescription *font_desc = pango_font_description_from_string(fontdesc.c_str());
+ pango_layout_set_font_description(layout, font_desc);
+ pango_font_description_free (font_desc);
+
+ PangoRectangle logical_extent;
+ pango_layout_get_pixel_extents(layout, NULL, &logical_extent);
+ cairo_move_to(cr, loc[Geom::X], loc[Geom::Y] - (bottom ? logical_extent.height : 0));
+ pango_cairo_show_layout(cr, layout);
+}
+
+static void
+draw_number(cairo_t *cr, Geom::Point pos, double num) {
+ std::ostringstream number;
+ number << num;
+ draw_text(cr, pos, number.str().c_str(), true);
+}
+
+/*
+ * \arg dist The distance between consecutive minor marks
+ * \arg major_interval Number of marks after which to draw a major mark
+ */
+void
+ZoomCorrRuler::draw_marks(Cairo::RefPtr<Cairo::Context> cr, double dist, int major_interval) {
+ const double zoomcorr = prefs_get_double_attribute("options.zoomcorrection", "value", 1.0);
+ double mark = 0;
+ int i = 0;
+ while (mark <= _drawing_width) {
+ cr->move_to(mark, _height);
+ if ((i % major_interval) == 0) {
+ // major mark
+ cr->line_to(mark, 0);
+ Geom::Point textpos(mark + 3, ZoomCorrRuler::textsize + ZoomCorrRuler::textpadding);
+ draw_number(cr->cobj(), textpos, dist * i);
+ } else {
+ // minor mark
+ cr->line_to(mark, ZoomCorrRuler::textsize + 2 * ZoomCorrRuler::textpadding);
+ }
+ mark += dist * zoomcorr / _unitconv;
+ ++i;
+ }
+}
+
+void
+ZoomCorrRuler::redraw() {
+ Glib::RefPtr<Gdk::Window> window = get_window();
+ Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context();
+
+ int w, h;
+ window->get_size(w, h);
+ _drawing_width = w - _border * 2;
+
+ cr->set_source_rgb(1.0, 1.0, 1.0);
+ cr->set_fill_rule(Cairo::FILL_RULE_WINDING);
+ cr->rectangle(0, 0, w, _height + _border*2);
+ cr->fill();
+
+ cr->set_source_rgb(0.0, 0.0, 0.0);
+ cr->set_line_width(0.5);
+
+ cr->translate(_border, _border); // so that we have a small white border around the ruler
+ cr->move_to (0, _height);
+ cr->line_to (_drawing_width, _height);
+
+ const char *abbr = prefs_get_string_attribute("options.zoomcorrection", "unit");
+ if (!strcmp(abbr, "cm")) {
+ draw_marks(cr, 0.1, 10);
+ } else if (!strcmp(abbr, "ft")) {
+ draw_marks(cr, 1/12.0, 12);
+ } else if (!strcmp(abbr, "in")) {
+ draw_marks(cr, 0.25, 4);
+ } else if (!strcmp(abbr, "m")) {
+ draw_marks(cr, 1/10.0, 10);
+ } else if (!strcmp(abbr, "mm")) {
+ draw_marks(cr, 10, 10);
+ } else if (!strcmp(abbr, "pc")) {
+ draw_marks(cr, 1, 10);
+ } else if (!strcmp(abbr, "pt")) {
+ draw_marks(cr, 10, 10);
+ } else if (!strcmp(abbr, "px")) {
+ draw_marks(cr, 10, 10);
+ } else {
+ draw_marks(cr, 1, 1);
+ }
+ cr->stroke();
+}
+
+bool
+ZoomCorrRuler::on_expose_event(GdkEventExpose *event) {
+ this->redraw();
+ return true;
+}
+
+void
+ZoomCorrRulerSlider::on_slider_value_changed()
+{
+ if (this->is_visible() || freeze) //only take action if user changed value
+ {
+ freeze = true;
+ prefs_set_double_attribute ("options.zoomcorrection", "value", _slider.get_value() / 100.0);
+ _sb.set_value(_slider.get_value());
+ _ruler.redraw();
+ freeze = false;
+ }
+}
+
+void
+ZoomCorrRulerSlider::on_spinbutton_value_changed()
+{
+ if (this->is_visible() || freeze) //only take action if user changed value
+ {
+ freeze = true;
+ prefs_set_double_attribute ("options.zoomcorrection", "value", _sb.get_value() / 100.0);
+ _slider.set_value(_sb.get_value());
+ _ruler.redraw();
+ freeze = false;
+ }
+}
+
+void
+ZoomCorrRulerSlider::on_unit_changed() {
+ if (GPOINTER_TO_INT(_unit.get_data("sensitive")) == 0) {
+ // when the unit menu is initialized, the unit is set to the default but
+ // it needs to be reset later so we don't perform the change in this case
+ return;
+ }
+ prefs_set_string_attribute ("options.zoomcorrection", "unit", _unit.getUnitAbbr().c_str());
+ double conv = _unit.getConversion(_unit.getUnitAbbr(), "px");
+ _ruler.set_unit_conversion(conv);
+ if (_ruler.is_visible()) {
+ _ruler.redraw();
+ }
+}
+
+void
+ZoomCorrRulerSlider::init(int ruler_width, int ruler_height, double lower, double upper,
+ double step_increment, double page_increment, double default_value)
+{
+ double value = prefs_get_double_attribute_limited ("options.zoomcorrection", "value", default_value, lower, upper) * 100.0;
+
+ freeze = false;
+
+ _ruler.set_size(ruler_width, ruler_height);
+
+ _slider.set_size_request(_ruler.width(), -1);
+ _slider.set_range (lower, upper);
+ _slider.set_increments (step_increment, page_increment);
+ _slider.set_value (value);
+ _slider.set_digits(2);
+
+ _slider.signal_value_changed().connect(sigc::mem_fun(*this, &ZoomCorrRulerSlider::on_slider_value_changed));
+ _sb.signal_value_changed().connect(sigc::mem_fun(*this, &ZoomCorrRulerSlider::on_spinbutton_value_changed));
+ _unit.signal_changed().connect(sigc::mem_fun(*this, &ZoomCorrRulerSlider::on_unit_changed));
+
+ _sb.set_range (lower, upper);
+ _sb.set_increments (step_increment, page_increment);
+ _sb.set_value (value);
+ _sb.set_digits(2);
+
+ _unit.set_data("sensitive", GINT_TO_POINTER(0));
+ _unit.setUnitType(UNIT_TYPE_LINEAR);
+ _unit.set_data("sensitive", GINT_TO_POINTER(1));
+ _unit.setUnit(prefs_get_string_attribute ("options.zoomcorrection", "unit"));
+
+ Gtk::Table *table = Gtk::manage(new Gtk::Table());
+ Gtk::Alignment *alignment1 = Gtk::manage(new Gtk::Alignment(0.5,1,0,0));
+ Gtk::Alignment *alignment2 = Gtk::manage(new Gtk::Alignment(0.5,1,0,0));
+ alignment1->add(_sb);
+ alignment2->add(_unit);
+
+ table->attach(_slider, 0, 1, 0, 1);
+ table->attach(*alignment1, 1, 2, 0, 1, static_cast<Gtk::AttachOptions>(0));
+ table->attach(_ruler, 0, 1, 1, 2);
+ table->attach(*alignment2, 1, 2, 1, 2, static_cast<Gtk::AttachOptions>(0));
+
+ this->pack_start(*table, Gtk::PACK_EXPAND_WIDGET);
+}
+
void PrefCombo::init(const std::string& prefs_path, const std::string& attr,
Glib::ustring labels[], int values[], int num_items, int default_value)
{
diff --git a/src/ui/widget/preferences-widget.h b/src/ui/widget/preferences-widget.h
index 0b907ae34..9f10f8ca8 100644
--- a/src/ui/widget/preferences-widget.h
+++ b/src/ui/widget/preferences-widget.h
@@ -22,6 +22,8 @@
#include <gtkmm/treeview.h>
#include <gtkmm/radiobutton.h>
#include <gtkmm/box.h>
+#include <gtkmm/scale.h>
+#include <gtkmm/drawingarea.h>
#include <gtkmm/frame.h>
#include <gtkmm/filechooserbutton.h>
#include <sigc++/sigc++.h>
@@ -82,6 +84,48 @@ protected:
void on_value_changed();
};
+class ZoomCorrRuler : public Gtk::DrawingArea {
+public:
+ ZoomCorrRuler(int width = 100, int height = 20);
+ void set_size(int x, int y);
+ void set_unit_conversion(double conv) { _unitconv = conv; }
+ void set_cairo_context(Cairo::RefPtr<Cairo::Context> cr);
+ void redraw();
+
+ int width() { return _min_width + _border*2; }
+
+ static const double textsize;
+ static const double textpadding;
+
+private:
+ bool on_expose_event(GdkEventExpose *event);
+ void draw_marks(Cairo::RefPtr<Cairo::Context> cr, double dist, int major_interval);
+
+ double _unitconv;
+ int _min_width;
+ int _height;
+ int _border;
+ int _drawing_width;
+};
+
+class ZoomCorrRulerSlider : public Gtk::VBox
+{
+public:
+ void init(int ruler_width, int ruler_height, double lower, double upper,
+ double step_increment, double page_increment, double default_value);
+
+private:
+ void on_slider_value_changed();
+ void on_spinbutton_value_changed();
+ void on_unit_changed();
+
+ Gtk::SpinButton _sb;
+ UnitMenu _unit;
+ Gtk::HScale _slider;
+ ZoomCorrRuler _ruler;
+ bool freeze; // used to block recursive updates of slider and spinbutton
+};
+
class PrefCombo : public Gtk::ComboBoxText
{
public:
diff --git a/src/verbs.cpp b/src/verbs.cpp
index a19ac7753..6b8d0a1fa 100644
--- a/src/verbs.cpp
+++ b/src/verbs.cpp
@@ -1645,20 +1645,23 @@ ZoomVerb::perform(SPAction *action, void *data, void */*pdata*/)
}
case SP_VERB_ZOOM_1_1:
{
+ double zcorr = prefs_get_double_attribute ("options.zoomcorrection", "value", 1.0);
NR::Rect const d = dt->get_display_area();
- dt->zoom_absolute( d.midpoint()[NR::X], d.midpoint()[NR::Y], 1.0 );
+ dt->zoom_absolute( d.midpoint()[NR::X], d.midpoint()[NR::Y], 1.0 * zcorr );
break;
}
case SP_VERB_ZOOM_1_2:
{
+ double zcorr = prefs_get_double_attribute ("options.zoomcorrection", "value", 1.0);
NR::Rect const d = dt->get_display_area();
- dt->zoom_absolute( d.midpoint()[NR::X], d.midpoint()[NR::Y], 0.5);
+ dt->zoom_absolute( d.midpoint()[NR::X], d.midpoint()[NR::Y], 0.5 * zcorr );
break;
}
case SP_VERB_ZOOM_2_1:
{
+ double zcorr = prefs_get_double_attribute ("options.zoomcorrection", "value", 1.0);
NR::Rect const d = dt->get_display_area();
- dt->zoom_absolute( d.midpoint()[NR::X], d.midpoint()[NR::Y], 2.0 );
+ dt->zoom_absolute( d.midpoint()[NR::X], d.midpoint()[NR::Y], 2.0 * zcorr );
break;
}
case SP_VERB_ZOOM_PAGE: