diff options
| author | Tavmjong Bah <tavmjong@free.fr> | 2019-06-27 11:52:11 +0000 |
|---|---|---|
| committer | Tavmjong Bah <tavmjong@free.fr> | 2019-06-29 12:01:19 +0000 |
| commit | c57475e562adf85fe6e09a2601d8f46fdc0490b6 (patch) | |
| tree | 404ea4db42eef5087f8807960cb94a4c5753d9bb | |
| parent | Update Ukrainian translation (diff) | |
| download | inkscape-c57475e562adf85fe6e09a2601d8f46fdc0490b6.tar.gz inkscape-c57475e562adf85fe6e09a2601d8f46fdc0490b6.zip | |
Reimplement ruler in C++.
| -rw-r--r-- | share/ui/style.css | 6 | ||||
| -rw-r--r-- | src/ui/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/ui/widget/ink-ruler.cpp | 465 | ||||
| -rw-r--r-- | src/ui/widget/ink-ruler.h | 80 | ||||
| -rw-r--r-- | src/widgets/desktop-widget.cpp | 49 | ||||
| -rw-r--r-- | src/widgets/desktop-widget.h | 4 |
6 files changed, 600 insertions, 6 deletions
diff --git a/share/ui/style.css b/share/ui/style.css index 7eb33f5be..fe379f345 100644 --- a/share/ui/style.css +++ b/share/ui/style.css @@ -296,6 +296,10 @@ SPRuler { color: @theme_fg_color; } +#InkRuler { + font-size: 7pt; +} + ruler-widget { background-color: @theme_bg_color; color: @theme_fg_color; @@ -407,4 +411,4 @@ combobox window.popup scrolledwindow treeview separator {} #InkSpinScale spinbutton entry { padding: 0; outline-style: none; -}
\ No newline at end of file +} 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; |
