summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTavmjong Bah <tavmjong@free.fr>2019-06-27 11:52:11 +0000
committerTavmjong Bah <tavmjong@free.fr>2019-06-29 12:01:19 +0000
commitc57475e562adf85fe6e09a2601d8f46fdc0490b6 (patch)
tree404ea4db42eef5087f8807960cb94a4c5753d9bb /src
parentUpdate Ukrainian translation (diff)
downloadinkscape-c57475e562adf85fe6e09a2601d8f46fdc0490b6.tar.gz
inkscape-c57475e562adf85fe6e09a2601d8f46fdc0490b6.zip
Reimplement ruler in C++.
Diffstat (limited to 'src')
-rw-r--r--src/ui/CMakeLists.txt2
-rw-r--r--src/ui/widget/ink-ruler.cpp465
-rw-r--r--src/ui/widget/ink-ruler.h80
-rw-r--r--src/widgets/desktop-widget.cpp49
-rw-r--r--src/widgets/desktop-widget.h4
5 files changed, 595 insertions, 5 deletions
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt
index c72f4c695..8bd586c4b 100644
--- a/src/ui/CMakeLists.txt
+++ b/src/ui/CMakeLists.txt
@@ -181,6 +181,7 @@ set(ui_SRC
widget/imagetoggler.cpp
widget/ink-color-wheel.cpp
widget/ink-flow-box.cpp
+ widget/ink-ruler.cpp
widget/ink-spinscale.cpp
widget/insertordericon.cpp
widget/label-tool-item.cpp
@@ -417,6 +418,7 @@ set(ui_SRC
widget/imagetoggler.h
widget/ink-color-wheel.h
widget/ink-flow-box.h
+ widget/ink-ruler.h
widget/ink-spinscale.h
widget/label-tool-item.h
widget/labelled.h
diff --git a/src/ui/widget/ink-ruler.cpp b/src/ui/widget/ink-ruler.cpp
new file mode 100644
index 000000000..258add614
--- /dev/null
+++ b/src/ui/widget/ink-ruler.cpp
@@ -0,0 +1,465 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Ruler widget. Indicates horizontal or vertical position of a cursor in a specified widget.
+ *
+ * Copyright (C) 2019 Tavmjong Bah
+ *
+ * The contents of this file may be used under the GNU General Public License Version 2 or later.
+ *
+ */
+
+#include "ink-ruler.h"
+
+#include <iostream>
+#include <cmath>
+
+#include "util/units.h"
+
+struct SPRulerMetric
+{
+ gdouble ruler_scale[16];
+ gint subdivide[5];
+};
+
+// Ruler metric for general use.
+static SPRulerMetric const ruler_metric_general = {
+ { 1, 2, 5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000, 25000, 50000, 100000 },
+ { 1, 5, 10, 50, 100 }
+};
+
+// Ruler metric for inch scales.
+static SPRulerMetric const ruler_metric_inches = {
+ { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768 },
+ { 1, 2, 4, 8, 16 }
+};
+
+// Half width of pointer triangle.
+static double half_width = 5.0;
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+Ruler::Ruler(Gtk::Orientation orientation)
+ : _orientation(orientation)
+ , _backing_store(nullptr)
+ , _lower(0)
+ , _upper(1000)
+ , _max_size(1000)
+ , _unit(nullptr)
+ , _backing_store_valid(false)
+{
+ set_name("InkRuler");
+
+ set_events(Gdk::POINTER_MOTION_MASK);
+
+ signal_motion_notify_event().connect(sigc::mem_fun(*this, &Ruler::draw_marker_callback));
+}
+
+// Set display unit for ruler.
+void
+Ruler::set_unit(Inkscape::Util::Unit const *unit)
+{
+ if (_unit != unit) {
+ _unit = unit;
+
+ draw_scale(); // Update backing store.
+ queue_draw();
+ }
+}
+
+// Set range for ruler, update ticks.
+void
+Ruler::set_range(const double& lower, const double& upper)
+{
+ if (_lower != lower || _upper != upper) {
+
+ _lower = lower;
+ _upper = upper;
+ _max_size = _upper - _lower;
+ if (_max_size == 0) {
+ _max_size = 1;
+ }
+
+ draw_scale(); // Update backing store.
+ queue_draw();
+ }
+}
+
+
+void
+Ruler::add_track_widget(Gtk::Widget& widget)
+{
+ widget.signal_motion_notify_event().connect(sigc::mem_fun(*this, &Ruler::draw_marker_callback), false); // false => connect first
+}
+
+
+// Draws marker in response to motion events from canvas. Position is defined in ruler pixel
+// coordinates. The routine assumes that the ruler is the same width (height) as the canvas. If
+// not, one could use Gtk::Widget::translate_coordinates() to convert the coordinates.
+bool
+Ruler::draw_marker_callback(GdkEventMotion* motion_event)
+{
+ double position = 0;
+ if (_orientation == Gtk::ORIENTATION_HORIZONTAL) {
+ position = motion_event->x;
+ } else {
+ position = motion_event->y;
+ }
+
+ if (position != _position) {
+
+ _position = position;
+
+ // Find region to repaint (old and new marker positions).
+ Cairo::RectangleInt new_rect = marker_rect();
+ Cairo::RefPtr<Cairo::Region> region = Cairo::Region::create(new_rect);
+ region->do_union(_rect);
+
+ // Queue repaint
+ queue_draw_region(region);
+
+ _rect = new_rect;
+ }
+
+ return false;
+}
+
+
+// Find smallest dimension of ruler based on font size.
+void
+Ruler::size_request (Gtk::Requisition& requisition) const
+{
+ // Get border size
+ Glib::RefPtr<Gtk::StyleContext> style_context = get_style_context();
+ Gtk::Border border = style_context->get_border(get_state_flags());
+
+ // Get font size
+ Pango::FontDescription font = style_context->get_font(get_state_flags());
+ int font_size = font.get_size();
+ if (!font.get_size_is_absolute()) {
+ font_size /= Pango::SCALE;
+ }
+
+ int size = 2 + font_size * 2.0; // Room for labels and ticks
+
+ int width = border.get_left() + border.get_right();
+ int height = border.get_top() + border.get_bottom();
+
+ if (_orientation == Gtk::ORIENTATION_HORIZONTAL) {
+ width += 1;
+ height += size;
+ } else {
+ width += size;
+ height += 1;
+ }
+
+ // Only valid for orientation in question (smallest dimension)!
+ requisition.width = width;
+ requisition.height = height;
+}
+
+void
+Ruler::get_preferred_width_vfunc (int& minimum_width, int& natural_width) const
+{
+ Gtk::Requisition requisition;
+ size_request(requisition);
+ minimum_width = natural_width = requisition.width;
+}
+
+void
+Ruler::get_preferred_height_vfunc (int& minimum_height, int& natural_height) const
+{
+ Gtk::Requisition requisition;
+ size_request(requisition);
+ minimum_height = natural_height = requisition.height;
+}
+
+// Update backing store when scale changes.
+// Note: in principle, there should not be a border (ruler ends should match canvas ends). If there
+// is a border, We calculate tick position ignoring border width at ends of ruler but move the
+// ticks and position marker inside the border.
+bool
+Ruler::draw_scale()
+{
+ // Get style information
+ Glib::RefPtr<Gtk::StyleContext> style_context = get_style_context();
+ Gtk::Border border = style_context->get_border(get_state_flags());
+ Gdk::RGBA foreground = style_context->get_color(get_state_flags());
+
+ Pango::FontDescription font = style_context->get_font(get_state_flags());
+ int font_size = font.get_size();
+ if (!font.get_size_is_absolute()) {
+ font_size /= Pango::SCALE;
+ }
+
+ Gtk::Allocation allocation = get_allocation();
+ int awidth = allocation.get_width();
+ int aheight = allocation.get_height();
+ // if (allocation.get_x() != 0 || allocation.get_y() != 0) {
+ // std::cerr << "Ruler::draw_scale: maybe we do have to handle allocation x and y! "
+ // << " x: " << allocation.get_x() << " y: " << allocation.get_y() << std::endl;
+ // }
+
+ // Create backing store
+ _backing_store = Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, awidth, aheight);
+
+ // Get context
+ Cairo::RefPtr<::Cairo::Context> cr = ::Cairo::Context::create(_backing_store);
+ style_context->render_background(cr, 0, 0, awidth, aheight);
+
+ cr->set_line_width(1.0);
+ Gdk::Cairo::set_source_rgba(cr, foreground);
+
+ // Ruler size (only smallest dimension used later).
+ int rwidth = awidth - (border.get_left() + border.get_right());
+ int rheight = aheight - (border.get_top() + border.get_bottom());
+
+ // Draw bottom/right line of ruler
+ if (_orientation == Gtk::ORIENTATION_HORIZONTAL) {
+ cr->rectangle( 0, aheight - border.get_bottom() - 1, awidth, 1);
+ } else {
+ cr->rectangle( awidth - border.get_left() - 1, 0, 1, aheight);
+ std::swap(awidth, aheight);
+ std::swap(rwidth, rheight);
+ }
+ cr->fill();
+
+ // From here on, awidth is the longest dimension of the ruler, rheight is the shortest.
+
+ // Figure out scale. Largest ticks must be far enough apart to fit largest text in vertical ruler.
+ // We actually require twice the distance.
+ unsigned int scale = std::ceil (_max_size); // Largest number
+ Glib::ustring scale_text = std::to_string(scale);
+ unsigned int digits = scale_text.length() + 1; // Add one for negative sign.
+ unsigned int minimum = digits * font_size * 2;
+
+ double pixels_per_unit = awidth/_max_size; // pixel per distance
+
+ SPRulerMetric ruler_metric = ruler_metric_general;
+ if (_unit == Inkscape::Util::unit_table.getUnit("in")) {
+ ruler_metric = ruler_metric_inches;
+ }
+
+ unsigned scale_index;
+ for (scale_index = 0; scale_index < G_N_ELEMENTS (ruler_metric.ruler_scale)-1; ++scale_index) {
+ if (ruler_metric.ruler_scale[scale_index] * std::abs (pixels_per_unit) > minimum) break;
+ }
+
+ // Now we find out what is the subdivide index for the closest ticks we can draw
+ unsigned divide_index;
+ for (divide_index = 0; divide_index < G_N_ELEMENTS (ruler_metric.subdivide)-1; ++divide_index) {
+ if (ruler_metric.ruler_scale[scale_index] * std::abs (pixels_per_unit) < 5 * ruler_metric.subdivide[divide_index+1]) break;
+ }
+
+ // We'll loop over all ticks.
+ double pixels_per_tick = pixels_per_unit *
+ ruler_metric.ruler_scale[scale_index] / ruler_metric.subdivide[divide_index];
+
+ double units_per_tick = pixels_per_tick/pixels_per_unit;
+ double ticks_per_unit = 1.0/units_per_tick;
+
+ // Find first and last ticks
+ int start = 0;
+ int end = 0;
+ if (_lower < _upper) {
+ start = std::floor (_lower * ticks_per_unit);
+ end = std::ceil (_upper * ticks_per_unit);
+ } else {
+ start = std::floor (_upper * ticks_per_unit);
+ end = std::ceil (_lower * ticks_per_unit);
+ }
+
+ // std::cout << " start: " << start
+ // << " end: " << end
+ // << " pixels_per_unit: " << pixels_per_unit
+ // << " pixels_per_tick: " << pixels_per_tick
+ // << std::endl;
+
+ // Loop over all ticks
+ for (int i = start; i < end+1; ++i) {
+
+ // Position of tick (add 0.5 to center tick on pixel).
+ double position = std::round(i*pixels_per_tick - _lower*pixels_per_unit) + 0.5;
+
+ // Height of tick
+ int height = rheight;
+ for (int j = divide_index; j > 0; --j) {
+ if (i%ruler_metric.subdivide[j] == 0) break;
+ height = height/2 + 1;
+ }
+
+ // Draw text for major ticks.
+ if (i%ruler_metric.subdivide[divide_index] == 0) {
+
+ int label_value = std::round(i*units_per_tick);
+ Glib::ustring label = std::to_string(label_value);
+
+ Glib::RefPtr<Pango::Layout> layout = create_pango_layout("");
+ layout->set_font_description(font);
+
+ if (_orientation == Gtk::ORIENTATION_HORIZONTAL) {
+ layout->set_text(label);
+ cr->move_to (position+2, border.get_top());
+ layout->show_in_cairo_context(cr);
+ } else {
+ cr->move_to (border.get_left(), position);
+ int n = 0;
+ for (char const &c : label) {
+ std::string s(1, c);
+ layout->set_text(s);
+ int text_width;
+ int text_height;
+ layout->get_pixel_size(text_width, text_height);
+ cr->move_to(border.get_left() + (aheight-text_width)/2.0 - 1,
+ position + n*0.7*text_height - 1);
+ layout->show_in_cairo_context(cr);
+ ++n;
+ }
+ // Glyphs are not centered in vertical text... should specify fixed width numbers.
+ // Glib::RefPtr<Pango::Context> context = layout->get_context();
+ // if (_orientation == Gtk::ORIENTATION_VERTICAL) {
+ // context->set_base_gravity(Pango::GRAVITY_EAST);
+ // context->set_gravity_hint(Pango::GRAVITY_HINT_STRONG);
+ // cr->move_to(...)
+ // cr->save();
+ // cr->rotate(M_PI_2);
+ // layout->show_in_cairo_context(cr);
+ // cr->restore();
+ // }
+ }
+ }
+
+ // Draw ticks
+ if (_orientation == Gtk::ORIENTATION_HORIZONTAL) {
+ cr->move_to(position, rheight + border.get_top() - height);
+ cr->line_to(position, rheight + border.get_top());
+ } else {
+ cr->move_to(rheight + border.get_left() - height, position);
+ cr->line_to(rheight + border.get_left(), position);
+ }
+ cr->stroke();
+ }
+
+ _backing_store_valid = true;
+
+ return true;
+}
+
+// Draw position marker, we use doubles here.
+void
+Ruler::draw_marker(const Cairo::RefPtr<::Cairo::Context>& cr)
+{
+
+ // Get style information
+ Glib::RefPtr<Gtk::StyleContext> style_context = get_style_context();
+ Gtk::Border border = style_context->get_border(get_state_flags());
+ Gdk::RGBA foreground = style_context->get_color(get_state_flags());
+
+ Gtk::Allocation allocation = get_allocation();
+ const int awidth = allocation.get_width();
+ const int aheight = allocation.get_height();
+
+ // Temp (to verify our rectangle encloses position marker).
+ // Cairo::RectangleInt rect = marker_rect();
+ // cr->set_source_rgb(0, 1.0, 0);
+ // cr->rectangle (rect.x, rect.y, rect.width, rect.height);
+ // cr->fill();
+
+ Gdk::Cairo::set_source_rgba(cr, foreground);
+ if (_orientation == Gtk::ORIENTATION_HORIZONTAL) {
+ double offset = aheight - border.get_bottom();
+ cr->move_to(_position, offset);
+ cr->line_to(_position - half_width, offset - half_width);
+ cr->line_to(_position + half_width, offset - half_width);
+ cr->close_path();
+ } else {
+ double offset = awidth - border.get_right();
+ cr->move_to(offset, _position);
+ cr->line_to(offset - half_width, _position - half_width);
+ cr->line_to(offset - half_width, _position + half_width);
+ cr->close_path();
+ }
+ cr->fill();
+}
+
+// This is a pixel aligned integer rectangle that encloses the position marker. Used to define the
+// redraw area.
+Cairo::RectangleInt
+Ruler::marker_rect()
+{
+ // Get border size
+ Glib::RefPtr<Gtk::StyleContext> style_context = get_style_context();
+ Gtk::Border border = style_context->get_border(get_state_flags());
+
+ Gtk::Allocation allocation = get_allocation();
+ const int awidth = allocation.get_width();
+ const int aheight = allocation.get_height();
+
+ int rwidth = awidth - border.get_left() - border.get_right();
+ int rheight = aheight - border.get_top() - border.get_bottom();
+
+ Cairo::RectangleInt rect;
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = 0;
+ rect.height = 0;
+
+ // Find size of rectangle to enclose triangle.
+ if (_orientation == Gtk::ORIENTATION_HORIZONTAL) {
+ rect.x = std::floor(_position - half_width);
+ rect.y = std::floor(border.get_top() + rheight - half_width);
+ rect.width = std::ceil(half_width * 2.0 + 1);
+ rect.height = std::ceil(half_width);
+ } else {
+ rect.x = std::floor(border.get_left() + rwidth - half_width);
+ rect.y = std::floor(_position - half_width);
+ rect.width = std::ceil(half_width);
+ rect.height = std::ceil(half_width * 2.0 + 1);
+ }
+
+ return rect;
+}
+
+// Draw the ruler using the tick backing store.
+bool
+Ruler::on_draw(const::Cairo::RefPtr<::Cairo::Context>& cr) {
+
+ if (!_backing_store_valid) {
+ draw_scale();
+ }
+
+ cr->set_source (_backing_store, 0, 0);
+ cr->paint();
+
+ draw_marker (cr);
+
+ return true;
+}
+
+// Update ruler on style change (font-size, etc.)
+void
+Ruler::on_style_updated() {
+
+ Gtk::DrawingArea::on_style_updated();
+
+ _backing_store_valid = false; // If font-size changed we need to regenerate store.
+
+ queue_resize();
+ queue_draw();
+}
+
+} // 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 :
diff --git a/src/ui/widget/ink-ruler.h b/src/ui/widget/ink-ruler.h
new file mode 100644
index 000000000..6009d727a
--- /dev/null
+++ b/src/ui/widget/ink-ruler.h
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Ruler widget. Indicates horizontal or vertical position of a cursor in a specified widget.
+ *
+ * Copyright (C) 2019 Tavmjong Bah
+ *
+ * The contents of this file may be used under the GNU General Public License Version 2 or later.
+ *
+ */
+
+#ifndef INK_RULER_H
+#define INK_RULER_H
+
+/* Rewrite of the C Ruler. */
+
+#include <gtkmm.h>
+
+namespace Inkscape {
+namespace Util {
+class Unit;
+}
+}
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class Ruler : public Gtk::DrawingArea
+{
+public:
+ Ruler(Gtk::Orientation orientation);
+
+ void set_unit(Inkscape::Util::Unit const *unit);
+ void set_range(const double& lower, const double& upper);
+
+ void add_track_widget(Gtk::Widget& widget);
+ bool draw_marker_callback(GdkEventMotion* motion_event);
+
+ void size_request(Gtk::Requisition& requisition) const;
+ void get_preferred_width_vfunc( int& minimum_width, int& natural_width ) const override;
+ void get_preferred_height_vfunc(int& minimum_height, int& natural_height) const override;
+
+protected:
+ bool draw_scale();
+ void draw_marker(const Cairo::RefPtr<::Cairo::Context>& cr);
+ Cairo::RectangleInt marker_rect();
+ bool on_draw(const::Cairo::RefPtr<::Cairo::Context>& cr) override;
+ void on_style_updated() override;
+
+private:
+ Gtk::Orientation _orientation;
+
+ Inkscape::Util::Unit const* _unit;
+ double _lower;
+ double _upper;
+ double _position;
+ double _max_size;
+ double _font_scale;
+
+ bool _backing_store_valid;
+
+ Cairo::RefPtr<::Cairo::ImageSurface> _backing_store;
+ Cairo::RectangleInt _rect;
+};
+
+} // Namespace Inkscape
+}
+}
+#endif // INK_RULER_H
+
+/*
+ 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 :
diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp
index 885cd5ed6..60b2c4673 100644
--- a/src/widgets/desktop-widget.cpp
+++ b/src/widgets/desktop-widget.cpp
@@ -60,6 +60,7 @@
#include "ui/uxmanager.h"
#include "ui/widget/button.h"
#include "ui/widget/dock.h"
+#include "ui/widget/ink-ruler.h"
#include "ui/widget/layer-selector.h"
#include "ui/widget/selected-style.h"
#include "ui/widget/spin-button-tool-item.h"
@@ -287,10 +288,20 @@ sp_desktop_widget_class_init (SPDesktopWidgetClass *klass)
*
* This adjusts the range of the rulers when the dock container is adjusted
* (fixes lp:950552)
+ *
+ * This fix was causing the rulers to be completely redrawn when not needed.
+ * Added check to see if allocation really changed.
+ *
+ *(Question, why is the callback being called when allocation not changed?)
*/
void
-SPDesktopWidget::canvas_tbl_size_allocate(Gtk::Allocation& /*allocation*/)
+SPDesktopWidget::canvas_tbl_size_allocate(Gtk::Allocation& allocation)
{
+ if (_allocation == allocation) {
+ return;
+ }
+
+ _allocation = allocation;
update_rulers();
}
@@ -376,14 +387,26 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
dtw->_guides_lock->signal_toggled().connect(sigc::mem_fun(dtw, &SPDesktopWidget::update_guides_lock));
dtw->_canvas_tbl->attach(*dtw->_guides_lock, 0, 0, 1, 1);
+ /* Rulers */
+ Inkscape::Util::Unit const *pt = unit_table.getUnit("pt");
+
/* Horizontal ruler */
+ dtw->_hruler2 = Gtk::manage(new Inkscape::UI::Widget::Ruler(Gtk::ORIENTATION_HORIZONTAL));
+ dtw->_hruler2->set_unit(pt);
+
dtw->_hruler = Glib::wrap(sp_ruler_new(GTK_ORIENTATION_HORIZONTAL));
dtw->_hruler->set_name("HorizontalRuler");
- dtw->_hruler_box = Gtk::manage(new Gtk::EventBox());
- Inkscape::Util::Unit const *pt = unit_table.getUnit("pt");
sp_ruler_set_unit(SP_RULER(dtw->_hruler->gobj()), pt);
+
+ dtw->_hruler_box = Gtk::manage(new Gtk::EventBox());
dtw->_hruler_box->set_tooltip_text(gettext(pt->name_plural.c_str()));
- dtw->_hruler_box->add(*dtw->_hruler);
+ // dtw->_hruler_box->add(*dtw->_hruler);
+
+ auto vbox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
+
+ vbox->pack_start(*dtw->_hruler, true, true);
+ vbox->pack_start(*dtw->_hruler2, true, true);
+ dtw->_hruler_box->add(*vbox);
dtw->_hruler_box->signal_button_press_event().connect(sigc::bind(sigc::mem_fun(*dtw, &SPDesktopWidget::on_ruler_box_button_press_event), dtw->_hruler_box, true));
dtw->_hruler_box->signal_button_release_event().connect(sigc::bind(sigc::mem_fun(*dtw, &SPDesktopWidget::on_ruler_box_button_release_event), dtw->_hruler_box, true));
@@ -397,7 +420,16 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
dtw->_vruler_box = Gtk::manage(new Gtk::EventBox());
sp_ruler_set_unit (SP_RULER (dtw->_vruler->gobj()), pt);
dtw->_vruler_box->set_tooltip_text(gettext(pt->name_plural.c_str()));
- dtw->_vruler_box->add(*dtw->_vruler);
+ // dtw->_vruler_box->add(*dtw->_vruler);
+
+ auto hbox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL));
+ dtw->_vruler2 = Gtk::manage(new Inkscape::UI::Widget::Ruler(Gtk::ORIENTATION_VERTICAL));
+ dtw->_vruler2->set_unit(pt);
+
+ hbox->pack_start(*dtw->_vruler, true, true);
+ hbox->pack_start(*dtw->_vruler2, true, true);
+ dtw->_vruler_box->add(*hbox);
+
dtw->_vruler_box->signal_button_press_event().connect(sigc::bind(sigc::mem_fun(*dtw, &SPDesktopWidget::on_ruler_box_button_press_event), dtw->_vruler_box, false));
dtw->_vruler_box->signal_button_release_event().connect(sigc::bind(sigc::mem_fun(*dtw, &SPDesktopWidget::on_ruler_box_button_release_event), dtw->_vruler_box, false));
@@ -484,6 +516,9 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
sp_ruler_add_track_widget(SP_RULER(dtw->_hruler->gobj()), GTK_WIDGET(dtw->_canvas));
sp_ruler_add_track_widget(SP_RULER(dtw->_vruler->gobj()), GTK_WIDGET(dtw->_canvas));
+ dtw->_hruler2->add_track_widget(*Glib::wrap(GTK_WIDGET(dtw->_canvas)));
+ dtw->_vruler2->add_track_widget(*Glib::wrap(GTK_WIDGET(dtw->_canvas)));
+
auto css_provider = gtk_css_provider_new();
auto style_context = gtk_widget_get_style_context(GTK_WIDGET(dtw->_canvas));
@@ -1739,6 +1774,7 @@ SPDesktopWidget::update_rulers()
lower_x,
upper_x,
upper_x - lower_x);
+ _hruler2->set_range(lower_x, upper_x);
double lower_y = _dt2r * (viewbox.bottom() - _ruler_origin[Geom::Y]);
double upper_y = _dt2r * (viewbox.top() - _ruler_origin[Geom::Y]);
@@ -1749,6 +1785,7 @@ SPDesktopWidget::update_rulers()
lower_y,
upper_y,
upper_y - lower_y);
+ _vruler2->set_range(lower_y, upper_y);
}
@@ -1762,6 +1799,8 @@ void SPDesktopWidget::namedviewModified(SPObject *obj, guint flags)
sp_ruler_set_unit(SP_RULER(_vruler->gobj()), nv->getDisplayUnit());
sp_ruler_set_unit(SP_RULER(_hruler->gobj()), nv->getDisplayUnit());
+ _vruler2->set_unit(nv->getDisplayUnit());
+ _hruler2->set_unit(nv->getDisplayUnit());
/* This loops through all the grandchildren of aux toolbox,
* and for each that it finds, it performs an sp_search_by_data_recursive(),
diff --git a/src/widgets/desktop-widget.h b/src/widgets/desktop-widget.h
index 59c031120..bca226889 100644
--- a/src/widgets/desktop-widget.h
+++ b/src/widgets/desktop-widget.h
@@ -48,6 +48,7 @@ namespace Widget {
class Button;
class LayerSelector;
class SelectedStyle;
+class Ruler;
} // namespace Widget
} // namespace UI
} // namespace Inkscape
@@ -149,6 +150,9 @@ private:
/* Rulers */
Gtk::Widget *_hruler;
Gtk::Widget *_vruler;
+ Inkscape::UI::Widget::Ruler *_hruler2;
+ Inkscape::UI::Widget::Ruler *_vruler2;
+ Gtk::Allocation _allocation;
unsigned int _interaction_disabled_counter;