summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAlexander Valavanis <valavanisalex@gmail.com>2018-12-06 11:49:19 +0000
committerAlexander Valavanis <valavanisalex@gmail.com>2018-12-06 11:49:19 +0000
commit1a0a649abdbfe2920397707380b876769fba24f2 (patch)
tree188a77e85890ea99357b68df963de0f88f2f5b8c /src
parentdesktop-widget: Make ruler origin private (diff)
downloadinkscape-1a0a649abdbfe2920397707380b876769fba24f2.tar.gz
inkscape-1a0a649abdbfe2920397707380b876769fba24f2.zip
desktop-widget: Make canvas private
Diffstat (limited to 'src')
-rw-r--r--src/desktop-events.cpp241
-rw-r--r--src/desktop-events.h5
-rw-r--r--src/desktop.cpp6
-rw-r--r--src/ui/tools/tool-base.cpp4
-rw-r--r--src/widgets/desktop-widget.cpp353
-rw-r--r--src/widgets/desktop-widget.h24
6 files changed, 322 insertions, 311 deletions
diff --git a/src/desktop-events.cpp b/src/desktop-events.cpp
index aee445d18..f48dbf8da 100644
--- a/src/desktop-events.cpp
+++ b/src/desktop-events.cpp
@@ -40,7 +40,6 @@
#include "sp-cursor.h"
#include "verbs.h"
-#include "display/canvas-axonomgrid.h"
#include "display/canvas-grid.h"
#include "display/guideline.h"
#include "display/snap-indicator.h"
@@ -67,7 +66,6 @@ using Inkscape::DocumentUndo;
static void snoop_extended(GdkEvent* event, SPDesktop *desktop);
static void init_extended();
-void sp_dt_ruler_snap_new_guide(SPDesktop *desktop, SPCanvasItem *guide, Geom::Point &event_dt, Geom::Point &normal);
/* Root item handler */
@@ -92,210 +90,7 @@ int sp_desktop_root_handler(SPCanvasItem */*item*/, GdkEvent *event, SPDesktop *
return sp_event_context_root_handler(desktop->event_context, event);
}
-static gint sp_dt_ruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidget *dtw, bool horiz)
-{
- static bool clicked = false;
- static bool dragged = false;
- static SPCanvasItem *guide = nullptr;
- static Geom::Point normal;
- int wx, wy;
- static gint xp = 0, yp = 0; // where drag started
-
- SPDesktop *desktop = dtw->desktop;
- GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(dtw->canvas));
-
- gint width, height;
-
- auto device = gdk_event_get_device(event);
- gdk_window_get_device_position(window, device, &wx, &wy, nullptr);
- gdk_window_get_geometry(window, nullptr /*x*/, nullptr /*y*/, &width, &height);
-
- Geom::Point const event_win(wx, wy);
-
- switch (event->type) {
- case GDK_BUTTON_PRESS:
- if (event->button.button == 1) {
- clicked = true;
- dragged = false;
- // save click origin
- xp = (gint) event->button.x;
- yp = (gint) event->button.y;
-
- Geom::Point const event_w(sp_canvas_window_to_world(dtw->canvas, event_win));
- Geom::Point const event_dt(desktop->w2d(event_w));
-
- // calculate the normal of the guidelines when dragged from the edges of rulers.
- auto const y_dir = desktop->yaxisdir();
- Geom::Point normal_bl_to_tr(1., y_dir); //bottomleft to topright
- Geom::Point normal_tr_to_bl(-1., y_dir); //topright to bottomleft
- normal_bl_to_tr.normalize();
- normal_tr_to_bl.normalize();
- Inkscape::CanvasGrid * grid = sp_namedview_get_first_enabled_grid(desktop->namedview);
- if (grid){
- if (grid->getGridType() == Inkscape::GRID_AXONOMETRIC ) {
- Inkscape::CanvasAxonomGrid *axonomgrid = dynamic_cast<Inkscape::CanvasAxonomGrid *>(grid);
- if (event->button.state & GDK_CONTROL_MASK) {
- // guidelines normal to gridlines
- normal_bl_to_tr = Geom::Point::polar(-axonomgrid->angle_rad[0], 1.0);
- normal_tr_to_bl = Geom::Point::polar(axonomgrid->angle_rad[2], 1.0);
- } else {
- normal_bl_to_tr = rot90(Geom::Point::polar(axonomgrid->angle_rad[2], 1.0));
- normal_tr_to_bl = rot90(Geom::Point::polar(-axonomgrid->angle_rad[0], 1.0));
- }
- }
- }
- if (horiz) {
- if (wx < 50) {
- normal = normal_bl_to_tr;
- } else if (wx > width - 50) {
- normal = normal_tr_to_bl;
- } else {
- normal = Geom::Point(0.,1.);
- }
- } else {
- if (wy < 50) {
- normal = normal_bl_to_tr;
- } else if (wy > height - 50) {
- normal = normal_tr_to_bl;
- } else {
- normal = Geom::Point(1.,0.);
- }
- }
-
- guide = sp_guideline_new(desktop->guides, nullptr, event_dt, normal);
- sp_guideline_set_color(SP_GUIDELINE(guide), desktop->namedview->guidehicolor);
-
- auto window = gtk_widget_get_window(widget);
-
-#if GTK_CHECK_VERSION(3,20,0)
- auto seat = gdk_device_get_seat(device);
- gdk_seat_grab(seat,
- window,
- GDK_SEAT_CAPABILITY_ALL_POINTING,
- FALSE,
- nullptr,
- event,
- nullptr,
- nullptr);
-#else
- gdk_device_grab(device,
- window,
- GDK_OWNERSHIP_NONE,
- FALSE,
- (GdkEventMask)(GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK ),
- NULL,
- event->button.time);
-#endif
- }
- break;
- case GDK_MOTION_NOTIFY:
- if (clicked) {
- Geom::Point const event_w(sp_canvas_window_to_world(dtw->canvas, event_win));
- Geom::Point event_dt(desktop->w2d(event_w));
-
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- gint tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100);
- if ( ( abs( (gint) event->motion.x - xp ) < tolerance )
- && ( abs( (gint) event->motion.y - yp ) < tolerance ) ) {
- break;
- }
-
- dragged = true;
-
- // explicitly show guidelines; if I draw a guide, I want them on
- if ((horiz ? wy : wx) >= 0) {
- desktop->namedview->setGuides(true);
- }
-
- if (!(event->motion.state & GDK_SHIFT_MASK)) {
- sp_dt_ruler_snap_new_guide(desktop, guide, event_dt, normal);
- }
- sp_guideline_set_normal(SP_GUIDELINE(guide), normal);
- sp_guideline_set_position(SP_GUIDELINE(guide), event_dt);
-
- desktop->set_coordinate_status(event_dt);
- }
- break;
- case GDK_BUTTON_RELEASE:
- if (clicked && event->button.button == 1) {
- sp_event_context_discard_delayed_snap_event(desktop->event_context);
-#if GTK_CHECK_VERSION(3,20,0)
- auto seat = gdk_device_get_seat(device);
- gdk_seat_ungrab(seat);
-#else
- gdk_device_ungrab(device, event->button.time);
-#endif
-
- Geom::Point const event_w(sp_canvas_window_to_world(dtw->canvas, event_win));
- Geom::Point event_dt(desktop->w2d(event_w));
-
- if (!(event->button.state & GDK_SHIFT_MASK)) {
- sp_dt_ruler_snap_new_guide(desktop, guide, event_dt, normal);
- }
-
- sp_canvas_item_destroy(guide);
- guide = nullptr;
- if ((horiz ? wy : wx) >= 0) {
- Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc();
- Inkscape::XML::Node *repr = xml_doc->createElement("sodipodi:guide");
-
- // If root viewBox set, interpret guides in terms of viewBox (90/96)
- double newx = event_dt.x();
- double newy = event_dt.y();
-
- // <sodipodi:guide> stores inverted y-axis coordinates
- if (desktop->is_yaxisdown()) {
- newy = desktop->doc()->getHeight().value("px") - newy;
- normal[Geom::Y] *= -1.0;
- }
-
- SPRoot *root = desktop->doc()->getRoot();
- if( root->viewBox_set ) {
- newx = newx * root->viewBox.width() / root->width.computed;
- newy = newy * root->viewBox.height() / root->height.computed;
- }
- sp_repr_set_point(repr, "position", Geom::Point( newx, newy ));
- sp_repr_set_point(repr, "orientation", normal);
- desktop->namedview->appendChild(repr);
- Inkscape::GC::release(repr);
- DocumentUndo::done(desktop->getDocument(), SP_VERB_NONE,
- _("Create guide"));
- }
- desktop->set_coordinate_status(event_dt);
-
- if (!dragged) {
- // Ruler click (without drag) toggle the guide visibility on and off
- Inkscape::XML::Node *repr = desktop->namedview->getRepr();
- sp_namedview_toggle_guides(desktop->getDocument(), repr);
-
- }
-
- clicked = false;
- dragged = false;
- }
- default:
- break;
- }
-
- return FALSE;
-}
-
-int sp_dt_hruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidget *dtw)
-{
- if (event->type == GDK_MOTION_NOTIFY) {
- sp_event_context_snap_delay_handler(dtw->desktop->event_context, (gpointer) widget, (gpointer) dtw, (GdkEventMotion *)event, Inkscape::UI::Tools::DelayedSnapEvent::GUIDE_HRULER);
- }
- return sp_dt_ruler_event(widget, event, dtw, true);
-}
-
-int sp_dt_vruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidget *dtw)
-{
- if (event->type == GDK_MOTION_NOTIFY) {
- sp_event_context_snap_delay_handler(dtw->desktop->event_context, (gpointer) widget, (gpointer) dtw, (GdkEventMotion *)event, Inkscape::UI::Tools::DelayedSnapEvent::GUIDE_VRULER);
- }
- return sp_dt_ruler_event(widget, event, dtw, false);
-}
static Geom::Point drag_origin;
static SPGuideDragType drag_type = SP_DRAG_NONE;
@@ -748,42 +543,6 @@ void snoop_extended(GdkEvent* event, SPDesktop *desktop)
}
}
}
-
-
-void sp_dt_ruler_snap_new_guide(SPDesktop *desktop, SPCanvasItem * /*guide*/, Geom::Point &event_dt, Geom::Point &normal)
-{
- SnapManager &m = desktop->namedview->snap_manager;
- m.setup(desktop);
- // We're dragging a brand new guide, just pulled of the rulers seconds ago. When snapping to a
- // path this guide will change it slope to become either tangential or perpendicular to that path. It's
- // therefore not useful to try tangential or perpendicular snapping, so this will be disabled temporarily
- bool pref_perp = m.snapprefs.getSnapPerp();
- bool pref_tang = m.snapprefs.getSnapTang();
- m.snapprefs.setSnapPerp(false);
- m.snapprefs.setSnapTang(false);
- // We only have a temporary guide which is not stored in our document yet.
- // Because the guide snapper only looks in the document for guides to snap to,
- // we don't have to worry about a guide snapping to itself here
- Geom::Point normal_orig = normal;
- m.guideFreeSnap(event_dt, normal, false, false);
- // After snapping, both event_dt and normal have been modified accordingly; we'll take the normal (of the
- // curve we snapped to) to set the normal the guide. And rotate it by 90 deg. if needed
- if (pref_perp) { // Perpendicular snapping to paths is requested by the user, so let's do that
- if (normal != normal_orig) {
- normal = Geom::rot90(normal);
- }
- }
- if (!(pref_tang || pref_perp)) { // if we don't want to snap either perpendicularly or tangentially, then
- normal = normal_orig; // we must restore the normal to it's original state
- }
- // Restore the preferences
- m.snapprefs.setSnapPerp(pref_perp);
- m.snapprefs.setSnapTang(pref_tang);
- m.unSetup();
-}
-
-
-
/*
Local Variables:
mode:c++
diff --git a/src/desktop-events.h b/src/desktop-events.h
index 71799fe6f..8ef9d2f23 100644
--- a/src/desktop-events.h
+++ b/src/desktop-events.h
@@ -35,11 +35,6 @@ gint sp_canvas_enter_notify (GtkWidget *widget, GdkEventCrossing *event, SPDeskt
gint sp_canvas_leave_notify (GtkWidget *widget, GdkEventCrossing *event, SPDesktop *desktop);
gint sp_canvas_motion_notify (GtkWidget *widget,GdkEventMotion *motion, SPDesktop *desktop);
-/* Rulers */
-
-int sp_dt_hruler_event (GtkWidget *widget, GdkEvent *event, SPDesktopWidget *dtw);
-int sp_dt_vruler_event (GtkWidget *widget, GdkEvent *event, SPDesktopWidget *dtw);
-
/* Guides */
gint sp_dt_guide_event (SPCanvasItem *item, GdkEvent *event, gpointer data);
diff --git a/src/desktop.cpp b/src/desktop.cpp
index fccee47bc..d9fb83ab7 100644
--- a/src/desktop.cpp
+++ b/src/desktop.cpp
@@ -1558,8 +1558,7 @@ void SPDesktop::toggleSplitMode()
if (parent) {
_split_canvas = !_split_canvas;
SPDesktopWidget *dtw = static_cast<SPDesktopWidget *>(parent->get_data("desktopwidget"));
- GtkAllocation allocation;
- gtk_widget_get_allocation(GTK_WIDGET(dtw->canvas), &allocation);
+ auto allocation = dtw->get_canvas_allocation();
SPCanvas *canvas = getCanvas();
canvas->requestRedraw(canvas->_x0, canvas->_y0, canvas->_x0 + allocation.width,
canvas->_y0 + allocation.height);
@@ -1575,8 +1574,7 @@ void SPDesktop::toggleXRay()
return toggleSplitMode();
}
SPDesktopWidget *dtw = static_cast<SPDesktopWidget *>(parent->get_data("desktopwidget"));
- GtkAllocation allocation;
- gtk_widget_get_allocation(GTK_WIDGET(dtw->canvas), &allocation);
+ auto allocation = dtw->get_canvas_allocation();
SPCanvas *canvas = getCanvas();
canvas->requestRedraw(canvas->_x0, canvas->_y0, canvas->_x0 + allocation.width,
canvas->_y0 + allocation.height);
diff --git a/src/ui/tools/tool-base.cpp b/src/ui/tools/tool-base.cpp
index 624c4df4a..0037aeead 100644
--- a/src/ui/tools/tool-base.cpp
+++ b/src/ui/tools/tool-base.cpp
@@ -1479,9 +1479,9 @@ gboolean sp_event_context_snap_watchdog_callback(gpointer data) {
g_assert(GTK_IS_WIDGET(item));
g_assert(SP_IS_DESKTOP_WIDGET(item2));
if (dse->getOrigin() == DelayedSnapEvent::GUIDE_HRULER) {
- sp_dt_hruler_event(GTK_WIDGET(item), dse->getEvent(), SP_DESKTOP_WIDGET(item2));
+ SPDesktopWidget::hruler_event(GTK_WIDGET(item), dse->getEvent(), SP_DESKTOP_WIDGET(item2));
} else {
- sp_dt_vruler_event(GTK_WIDGET(item), dse->getEvent(), SP_DESKTOP_WIDGET(item2));
+ SPDesktopWidget::vruler_event(GTK_WIDGET(item), dse->getEvent(), SP_DESKTOP_WIDGET(item2));
}
}
}
diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp
index 057bd1231..aede0c817 100644
--- a/src/widgets/desktop-widget.cpp
+++ b/src/widgets/desktop-widget.cpp
@@ -50,12 +50,15 @@
#include "desktop-events.h"
#include "desktop-widget.h"
#include "desktop.h"
+#include "document-undo.h"
#include "ege-color-prof-tracker.h"
#include "file.h"
#include "inkscape-version.h"
#include "verbs.h"
#include "display/canvas-arena.h"
+#include "display/canvas-axonomgrid.h"
+#include "display/guideline.h"
#include "display/sp-canvas.h"
#include "extension/db.h"
@@ -91,6 +94,7 @@
#include "widget-sizes.h"
+using Inkscape::DocumentUndo;
using Inkscape::UI::Widget::UnitTracker;
using Inkscape::UI::UXManager;
using Inkscape::UI::ToolboxFactory;
@@ -106,9 +110,6 @@ static void sp_desktop_widget_class_init (SPDesktopWidgetClass *klass);
static void sp_desktop_widget_size_allocate (GtkWidget *widget, GtkAllocation *allocation);
static void sp_desktop_widget_realize (GtkWidget *widget);
-static gint sp_desktop_widget_event (GtkWidget *widget, GdkEvent *event, SPDesktopWidget *dtw);
-
-static void sp_dtw_color_profile_event(EgeColorProfTracker *widget, SPDesktopWidget *dtw);
static void sp_desktop_widget_adjustment_value_changed (GtkAdjustment *adj, SPDesktopWidget *dtw);
static gdouble sp_dtw_zoom_value_to_display (gdouble value);
@@ -237,7 +238,7 @@ Geom::Point
SPDesktopWidget::window_get_pointer()
{
int x, y;
- auto window = Glib::wrap(GTK_WIDGET(canvas))->get_window();
+ auto window = Glib::wrap(GTK_WIDGET(_canvas))->get_window();
auto display = window->get_display();
#if GTK_CHECK_VERSION(3,20,0)
@@ -400,9 +401,9 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
dtw->_hruler_box->set_tooltip_text(gettext(pt->name_plural.c_str()));
dtw->_hruler_box->add(*dtw->_hruler);
- g_signal_connect (G_OBJECT (dtw->_hruler_box->gobj()), "button_press_event", G_CALLBACK (sp_dt_hruler_event), dtw);
- g_signal_connect (G_OBJECT (dtw->_hruler_box->gobj()), "button_release_event", G_CALLBACK (sp_dt_hruler_event), dtw);
- g_signal_connect (G_OBJECT (dtw->_hruler_box->gobj()), "motion_notify_event", G_CALLBACK (sp_dt_hruler_event), dtw);
+ g_signal_connect (G_OBJECT (dtw->_hruler_box->gobj()), "button_press_event", G_CALLBACK (SPDesktopWidget::hruler_event), dtw);
+ g_signal_connect (G_OBJECT (dtw->_hruler_box->gobj()), "button_release_event", G_CALLBACK (SPDesktopWidget::hruler_event), dtw);
+ g_signal_connect (G_OBJECT (dtw->_hruler_box->gobj()), "motion_notify_event", G_CALLBACK (SPDesktopWidget::hruler_event), dtw);
dtw->_canvas_tbl->attach(*dtw->_hruler_box, 1, 0, 1, 1);
@@ -414,9 +415,9 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
dtw->_vruler_box->set_tooltip_text(gettext(pt->name_plural.c_str()));
dtw->_vruler_box->add(*dtw->_vruler);
- g_signal_connect (G_OBJECT (dtw->_vruler_box->gobj()), "button_press_event", G_CALLBACK (sp_dt_vruler_event), dtw);
- g_signal_connect (G_OBJECT (dtw->_vruler_box->gobj()), "button_release_event", G_CALLBACK (sp_dt_vruler_event), dtw);
- g_signal_connect (G_OBJECT (dtw->_vruler_box->gobj()), "motion_notify_event", G_CALLBACK (sp_dt_vruler_event), dtw);
+ g_signal_connect (G_OBJECT (dtw->_vruler_box->gobj()), "button_press_event", G_CALLBACK (SPDesktopWidget::vruler_event), dtw);
+ g_signal_connect (G_OBJECT (dtw->_vruler_box->gobj()), "button_release_event", G_CALLBACK (SPDesktopWidget::vruler_event), dtw);
+ g_signal_connect (G_OBJECT (dtw->_vruler_box->gobj()), "motion_notify_event", G_CALLBACK (SPDesktopWidget::vruler_event), dtw);
dtw->_canvas_tbl->attach(*dtw->_vruler_box, 0, 1, 1, 1);
@@ -492,16 +493,16 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
watcher->add(dtw);
}
/* Canvas */
- dtw->canvas = SP_CANVAS(SPCanvas::createAA());
+ dtw->_canvas = SP_CANVAS(SPCanvas::createAA());
#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
- dtw->canvas->_enable_cms_display_adj = prefs->getBool("/options/displayprofile/enable");
+ dtw->_canvas->_enable_cms_display_adj = prefs->getBool("/options/displayprofile/enable");
#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
- gtk_widget_set_can_focus (GTK_WIDGET (dtw->canvas), TRUE);
+ gtk_widget_set_can_focus (GTK_WIDGET (dtw->_canvas), TRUE);
- 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));
+ 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));
auto css_provider = gtk_css_provider_new();
- auto style_context = gtk_widget_get_style_context(GTK_WIDGET(dtw->canvas));
+ auto style_context = gtk_widget_get_style_context(GTK_WIDGET(dtw->_canvas));
gtk_css_provider_load_from_data(css_provider,
"SPCanvas {\n"
@@ -512,11 +513,11 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
gtk_style_context_add_provider(style_context,
GTK_STYLE_PROVIDER(css_provider),
GTK_STYLE_PROVIDER_PRIORITY_USER);
- g_signal_connect (G_OBJECT (dtw->canvas), "event", G_CALLBACK (sp_desktop_widget_event), dtw);
+ g_signal_connect (G_OBJECT (dtw->_canvas), "event", G_CALLBACK (SPDesktopWidget::event), dtw);
- gtk_widget_set_hexpand(GTK_WIDGET(dtw->canvas), TRUE);
- gtk_widget_set_vexpand(GTK_WIDGET(dtw->canvas), TRUE);
- dtw->_canvas_tbl->attach(*Glib::wrap(GTK_WIDGET(dtw->canvas)), 1, 1, 1, 1);
+ gtk_widget_set_hexpand(GTK_WIDGET(dtw->_canvas), TRUE);
+ gtk_widget_set_vexpand(GTK_WIDGET(dtw->_canvas), TRUE);
+ dtw->_canvas_tbl->attach(*Glib::wrap(GTK_WIDGET(dtw->_canvas)), 1, 1, 1, 1);
/* Dock */
bool create_dock =
@@ -588,7 +589,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
auto zoom_adj = Gtk::Adjustment::create(100.0, log(SP_DESKTOP_ZOOM_MIN)/log(2), log(SP_DESKTOP_ZOOM_MAX)/log(2), 0.1);
dtw->_zoom_status = Gtk::manage(new Gtk::SpinButton(zoom_adj));
- dtw->_zoom_status->set_data("dtw", dtw->canvas);
+ dtw->_zoom_status->set_data("dtw", dtw->_canvas);
dtw->_zoom_status->set_tooltip_text(_("Zoom"));
dtw->_zoom_status->set_size_request(STATUS_ZOOM_WIDTH, -1);
dtw->_zoom_status->set_width_chars(6);
@@ -614,7 +615,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
// Rotate status spinbutton ---------------
auto rotation_adj = Gtk::Adjustment::create(0, -360.0, 360.0, 1.0);
dtw->_rotation_status = Gtk::manage(new Gtk::SpinButton(rotation_adj));
- dtw->_rotation_status->set_data("dtw", dtw->canvas);
+ dtw->_rotation_status->set_data("dtw", dtw->_canvas);
dtw->_rotation_status->set_tooltip_text(_("Rotation. (Also Ctrl+Shift+Scroll)"));
dtw->_rotation_status->set_size_request(STATUS_ROTATION_WIDTH, -1);
dtw->_rotation_status->set_width_chars(7);
@@ -685,17 +686,17 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
Glib::ustring id = Inkscape::CMSSystem::getDisplayId( 0 );
bool enabled = false;
- dtw->canvas->_cms_key = id;
- enabled = !dtw->canvas->_cms_key.empty();
+ dtw->_canvas->_cms_key = id;
+ enabled = !dtw->_canvas->_cms_key.empty();
dtw->cms_adjust_set_sensitive(enabled);
}
#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
- g_signal_connect( G_OBJECT(dtw->_tracker), "changed", G_CALLBACK(sp_dtw_color_profile_event), dtw );
+ g_signal_connect( G_OBJECT(dtw->_tracker), "changed", G_CALLBACK(SPDesktopWidget::color_profile_event), dtw );
// ------------------ Finish Up -------------------- //
dtw->_vbox->show_all();
- gtk_widget_grab_focus (GTK_WIDGET(dtw->canvas));
+ gtk_widget_grab_focus (GTK_WIDGET(dtw->_canvas));
// If this is the first desktop created, report the time it takes to show up
if ( overallTimer ) {
@@ -748,7 +749,7 @@ SPDesktopWidget::dispose(GObject *object)
dtw->_rotation_status_populate_popup_connection.disconnect();
// Canvas
- g_signal_handlers_disconnect_by_func (G_OBJECT (dtw->canvas), (gpointer) G_CALLBACK (sp_desktop_widget_event), dtw);
+ g_signal_handlers_disconnect_by_func (G_OBJECT (dtw->_canvas), (gpointer) G_CALLBACK (SPDesktopWidget::event), dtw);
dtw->_canvas_tbl_size_allocate_connection.disconnect();
dtw->layer_selector->setDesktop(nullptr);
@@ -927,12 +928,12 @@ void SPDesktopWidget::updateNamedview()
/**
* Callback to handle desktop widget event.
*/
-static gint
-sp_desktop_widget_event (GtkWidget *widget, GdkEvent *event, SPDesktopWidget *dtw)
+gint
+SPDesktopWidget::event(GtkWidget *widget, GdkEvent *event, SPDesktopWidget *dtw)
{
if (event->type == GDK_BUTTON_PRESS) {
// defocus any spinbuttons
- gtk_widget_grab_focus (GTK_WIDGET(dtw->canvas));
+ gtk_widget_grab_focus (GTK_WIDGET(dtw->_canvas));
}
if ((event->type == GDK_BUTTON_PRESS) && (event->button.button == 3)) {
@@ -952,7 +953,7 @@ sp_desktop_widget_event (GtkWidget *widget, GdkEvent *event, SPDesktopWidget *dt
// current item on the canvas, because item events and all mouse events are caught
// and passed on by the canvas acetate (I think). --bb
if ((event->type == GDK_KEY_PRESS || event->type == GDK_KEY_RELEASE)
- && !dtw->canvas->_current_item) {
+ && !dtw->_canvas->_current_item) {
return sp_desktop_root_handler (nullptr, event, dtw->desktop);
}
}
@@ -962,7 +963,8 @@ sp_desktop_widget_event (GtkWidget *widget, GdkEvent *event, SPDesktopWidget *dt
#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
-void sp_dtw_color_profile_event(EgeColorProfTracker */*tracker*/, SPDesktopWidget *dtw)
+void
+SPDesktopWidget::color_profile_event(EgeColorProfTracker */*tracker*/, SPDesktopWidget *dtw)
{
// Handle profile changes
GdkScreen* screen = gtk_widget_get_screen(GTK_WIDGET(dtw));
@@ -989,9 +991,9 @@ void sp_dtw_color_profile_event(EgeColorProfTracker */*tracker*/, SPDesktopWidge
Glib::ustring id = Inkscape::CMSSystem::getDisplayId( monitorNum );
bool enabled = false;
- dtw->canvas->_cms_key = id;
+ dtw->_canvas->_cms_key = id;
dtw->requestCanvasUpdate();
- enabled = !dtw->canvas->_cms_key.empty();
+ enabled = !dtw->_canvas->_cms_key.empty();
dtw->cms_adjust_set_sensitive(enabled);
}
#else // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
@@ -1027,8 +1029,8 @@ SPDesktopWidget::cms_adjust_toggled( GtkWidget */*button*/, gpointer data )
SPDesktopWidget *dtw = SP_DESKTOP_WIDGET(data);
bool down = dtw->_cms_adjust->get_active();
- if ( down != dtw->canvas->_enable_cms_display_adj ) {
- dtw->canvas->_enable_cms_display_adj = down;
+ if ( down != dtw->_canvas->_enable_cms_display_adj ) {
+ dtw->_canvas->_enable_cms_display_adj = down;
dtw->desktop->redrawDesktop();
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->setBool("/options/displayprofile/enable", down);
@@ -1375,11 +1377,11 @@ bool SPDesktopWidget::warnDialog (Glib::ustring const &text)
}
void
-sp_desktop_widget_iconify(SPDesktopWidget *dtw)
+SPDesktopWidget::iconify()
{
- GtkWindow *topw = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(dtw->canvas)));
+ GtkWindow *topw = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(_canvas)));
if (GTK_IS_WINDOW(topw)) {
- if (dtw->desktop->is_iconified()) {
+ if (desktop->is_iconified()) {
gtk_window_deiconify(topw);
} else {
gtk_window_iconify(topw);
@@ -1388,22 +1390,22 @@ sp_desktop_widget_iconify(SPDesktopWidget *dtw)
}
void
-sp_desktop_widget_maximize(SPDesktopWidget *dtw)
+SPDesktopWidget::maximize()
{
- GtkWindow *topw = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(dtw->canvas)));
+ GtkWindow *topw = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(_canvas)));
if (GTK_IS_WINDOW(topw)) {
- if (dtw->desktop->is_maximized()) {
+ if (desktop->is_maximized()) {
gtk_window_unmaximize(topw);
} else {
// Save geometry to prefs before maximizing so that
// something useful is stored there, because GTK doesn't maintain
// a separate non-maximized size.
- if (!dtw->desktop->is_iconified() && !dtw->desktop->is_fullscreen())
+ if (!desktop->is_iconified() && !desktop->is_fullscreen())
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
gint w = -1;
gint h, x, y;
- dtw->getWindowGeometry(x, y, w, h);
+ getWindowGeometry(x, y, w, h);
g_assert(w != -1);
prefs->setInt("/desktop/geometry/width", w);
prefs->setInt("/desktop/geometry/height", h);
@@ -1416,22 +1418,22 @@ sp_desktop_widget_maximize(SPDesktopWidget *dtw)
}
void
-sp_desktop_widget_fullscreen(SPDesktopWidget *dtw)
+SPDesktopWidget::fullscreen()
{
- GtkWindow *topw = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(dtw->canvas)));
+ GtkWindow *topw = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(_canvas)));
if (GTK_IS_WINDOW(topw)) {
- if (dtw->desktop->is_fullscreen()) {
+ if (desktop->is_fullscreen()) {
gtk_window_unfullscreen(topw);
// widget layout is triggered by the resulting window_state_event
} else {
// Save geometry to prefs before maximizing so that
// something useful is stored there, because GTK doesn't maintain
// a separate non-maximized size.
- if (!dtw->desktop->is_iconified() && !dtw->desktop->is_maximized())
+ if (!desktop->is_iconified() && !desktop->is_maximized())
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
gint w, h, x, y;
- dtw->getWindowGeometry(x, y, w, h);
+ getWindowGeometry(x, y, w, h);
prefs->setInt("/desktop/geometry/width", w);
prefs->setInt("/desktop/geometry/height", h);
prefs->setInt("/desktop/geometry/x", x);
@@ -1652,7 +1654,7 @@ SPDesktopWidget* SPDesktopWidget::createInstance(SPNamedView *namedview)
dtw->desktop = new SPDesktop();
dtw->stub = new SPDesktopWidget::WidgetStub (dtw);
- dtw->desktop->init (namedview, dtw->canvas, dtw->stub);
+ dtw->desktop->init (namedview, dtw->_canvas, dtw->stub);
INKSCAPE.add_desktop (dtw->desktop);
// Add the shape geometry to libavoid for autorouting connectors.
@@ -2158,7 +2160,7 @@ SPDesktopWidget::update_scrollbars(double scale)
Geom::Rect carea( Geom::Point(deskarea->left() * scale - 64, (deskarea->top() * scale + 64) * y_dir),
Geom::Point(deskarea->right() * scale + 64, (deskarea->bottom() * scale - 64) * y_dir) );
- Geom::Rect viewbox = canvas->getViewbox();
+ Geom::Rect viewbox = _canvas->getViewbox();
/* Viewbox is always included into scrollable region */
carea = Geom::unify(carea, viewbox);
@@ -2197,6 +2199,255 @@ SPDesktopWidget::get_vruler_thickness() const
auto allocation = _vruler->get_allocation();
return allocation.get_width();
}
+
+gint
+SPDesktopWidget::ruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidget *dtw, bool horiz)
+{
+ static bool clicked = false;
+ static bool dragged = false;
+ static SPCanvasItem *guide = nullptr;
+ static Geom::Point normal;
+ int wx, wy;
+ static gint xp = 0, yp = 0; // where drag started
+
+ SPDesktop *desktop = dtw->desktop;
+ GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(dtw->_canvas));
+
+ gint width, height;
+
+ auto device = gdk_event_get_device(event);
+ gdk_window_get_device_position(window, device, &wx, &wy, nullptr);
+ gdk_window_get_geometry(window, nullptr /*x*/, nullptr /*y*/, &width, &height);
+
+ Geom::Point const event_win(wx, wy);
+
+ switch (event->type) {
+ case GDK_BUTTON_PRESS:
+ if (event->button.button == 1) {
+ clicked = true;
+ dragged = false;
+ // save click origin
+ xp = (gint) event->button.x;
+ yp = (gint) event->button.y;
+
+ Geom::Point const event_w(sp_canvas_window_to_world(dtw->_canvas, event_win));
+ Geom::Point const event_dt(desktop->w2d(event_w));
+
+ // calculate the normal of the guidelines when dragged from the edges of rulers.
+ auto const y_dir = desktop->yaxisdir();
+ Geom::Point normal_bl_to_tr(1., y_dir); //bottomleft to topright
+ Geom::Point normal_tr_to_bl(-1., y_dir); //topright to bottomleft
+ normal_bl_to_tr.normalize();
+ normal_tr_to_bl.normalize();
+ Inkscape::CanvasGrid * grid = sp_namedview_get_first_enabled_grid(desktop->namedview);
+ if (grid){
+ if (grid->getGridType() == Inkscape::GRID_AXONOMETRIC ) {
+ Inkscape::CanvasAxonomGrid *axonomgrid = dynamic_cast<Inkscape::CanvasAxonomGrid *>(grid);
+ if (event->button.state & GDK_CONTROL_MASK) {
+ // guidelines normal to gridlines
+ normal_bl_to_tr = Geom::Point::polar(-axonomgrid->angle_rad[0], 1.0);
+ normal_tr_to_bl = Geom::Point::polar(axonomgrid->angle_rad[2], 1.0);
+ } else {
+ normal_bl_to_tr = rot90(Geom::Point::polar(axonomgrid->angle_rad[2], 1.0));
+ normal_tr_to_bl = rot90(Geom::Point::polar(-axonomgrid->angle_rad[0], 1.0));
+ }
+ }
+ }
+ if (horiz) {
+ if (wx < 50) {
+ normal = normal_bl_to_tr;
+ } else if (wx > width - 50) {
+ normal = normal_tr_to_bl;
+ } else {
+ normal = Geom::Point(0.,1.);
+ }
+ } else {
+ if (wy < 50) {
+ normal = normal_bl_to_tr;
+ } else if (wy > height - 50) {
+ normal = normal_tr_to_bl;
+ } else {
+ normal = Geom::Point(1.,0.);
+ }
+ }
+
+ guide = sp_guideline_new(desktop->guides, nullptr, event_dt, normal);
+ sp_guideline_set_color(SP_GUIDELINE(guide), desktop->namedview->guidehicolor);
+
+ auto window = gtk_widget_get_window(widget);
+
+#if GTK_CHECK_VERSION(3,20,0)
+ auto seat = gdk_device_get_seat(device);
+ gdk_seat_grab(seat,
+ window,
+ GDK_SEAT_CAPABILITY_ALL_POINTING,
+ FALSE,
+ nullptr,
+ event,
+ nullptr,
+ nullptr);
+#else
+ gdk_device_grab(device,
+ window,
+ GDK_OWNERSHIP_NONE,
+ FALSE,
+ (GdkEventMask)(GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK ),
+ NULL,
+ event->button.time);
+#endif
+ }
+ break;
+ case GDK_MOTION_NOTIFY:
+ if (clicked) {
+ Geom::Point const event_w(sp_canvas_window_to_world(dtw->_canvas, event_win));
+ Geom::Point event_dt(desktop->w2d(event_w));
+
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ gint tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100);
+ if ( ( abs( (gint) event->motion.x - xp ) < tolerance )
+ && ( abs( (gint) event->motion.y - yp ) < tolerance ) ) {
+ break;
+ }
+
+ dragged = true;
+
+ // explicitly show guidelines; if I draw a guide, I want them on
+ if ((horiz ? wy : wx) >= 0) {
+ desktop->namedview->setGuides(true);
+ }
+
+ if (!(event->motion.state & GDK_SHIFT_MASK)) {
+ ruler_snap_new_guide(desktop, guide, event_dt, normal);
+ }
+ sp_guideline_set_normal(SP_GUIDELINE(guide), normal);
+ sp_guideline_set_position(SP_GUIDELINE(guide), event_dt);
+
+ desktop->set_coordinate_status(event_dt);
+ }
+ break;
+ case GDK_BUTTON_RELEASE:
+ if (clicked && event->button.button == 1) {
+ sp_event_context_discard_delayed_snap_event(desktop->event_context);
+
+#if GTK_CHECK_VERSION(3,20,0)
+ auto seat = gdk_device_get_seat(device);
+ gdk_seat_ungrab(seat);
+#else
+ gdk_device_ungrab(device, event->button.time);
+#endif
+
+ Geom::Point const event_w(sp_canvas_window_to_world(dtw->_canvas, event_win));
+ Geom::Point event_dt(desktop->w2d(event_w));
+
+ if (!(event->button.state & GDK_SHIFT_MASK)) {
+ ruler_snap_new_guide(desktop, guide, event_dt, normal);
+ }
+
+ sp_canvas_item_destroy(guide);
+ guide = nullptr;
+ if ((horiz ? wy : wx) >= 0) {
+ Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc();
+ Inkscape::XML::Node *repr = xml_doc->createElement("sodipodi:guide");
+
+ // If root viewBox set, interpret guides in terms of viewBox (90/96)
+ double newx = event_dt.x();
+ double newy = event_dt.y();
+
+ // <sodipodi:guide> stores inverted y-axis coordinates
+ if (desktop->is_yaxisdown()) {
+ newy = desktop->doc()->getHeight().value("px") - newy;
+ normal[Geom::Y] *= -1.0;
+ }
+
+ SPRoot *root = desktop->doc()->getRoot();
+ if( root->viewBox_set ) {
+ newx = newx * root->viewBox.width() / root->width.computed;
+ newy = newy * root->viewBox.height() / root->height.computed;
+ }
+ sp_repr_set_point(repr, "position", Geom::Point( newx, newy ));
+ sp_repr_set_point(repr, "orientation", normal);
+ desktop->namedview->appendChild(repr);
+ Inkscape::GC::release(repr);
+ DocumentUndo::done(desktop->getDocument(), SP_VERB_NONE,
+ _("Create guide"));
+ }
+ desktop->set_coordinate_status(event_dt);
+
+ if (!dragged) {
+ // Ruler click (without drag) toggle the guide visibility on and off
+ Inkscape::XML::Node *repr = desktop->namedview->getRepr();
+ sp_namedview_toggle_guides(desktop->getDocument(), repr);
+ }
+
+ clicked = false;
+ dragged = false;
+ }
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+int
+SPDesktopWidget::hruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidget *dtw)
+{
+ if (event->type == GDK_MOTION_NOTIFY) {
+ sp_event_context_snap_delay_handler(dtw->desktop->event_context, (gpointer) widget, (gpointer) dtw, (GdkEventMotion *)event, Inkscape::UI::Tools::DelayedSnapEvent::GUIDE_HRULER);
+ }
+ return ruler_event(widget, event, dtw, true);
+}
+
+int
+SPDesktopWidget::vruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidget *dtw)
+{
+ if (event->type == GDK_MOTION_NOTIFY) {
+ sp_event_context_snap_delay_handler(dtw->desktop->event_context, (gpointer) widget, (gpointer) dtw, (GdkEventMotion *)event, Inkscape::UI::Tools::DelayedSnapEvent::GUIDE_VRULER);
+ }
+ return ruler_event(widget, event, dtw, false);
+}
+
+GtkAllocation
+SPDesktopWidget::get_canvas_allocation() const
+{
+ GtkAllocation allocation;
+ gtk_widget_get_allocation(GTK_WIDGET(_canvas), &allocation);
+ return allocation;
+}
+
+void
+SPDesktopWidget::ruler_snap_new_guide(SPDesktop *desktop, SPCanvasItem * /*guide*/, Geom::Point &event_dt, Geom::Point &normal)
+{
+ SnapManager &m = desktop->namedview->snap_manager;
+ m.setup(desktop);
+ // We're dragging a brand new guide, just pulled of the rulers seconds ago. When snapping to a
+ // path this guide will change it slope to become either tangential or perpendicular to that path. It's
+ // therefore not useful to try tangential or perpendicular snapping, so this will be disabled temporarily
+ bool pref_perp = m.snapprefs.getSnapPerp();
+ bool pref_tang = m.snapprefs.getSnapTang();
+ m.snapprefs.setSnapPerp(false);
+ m.snapprefs.setSnapTang(false);
+ // We only have a temporary guide which is not stored in our document yet.
+ // Because the guide snapper only looks in the document for guides to snap to,
+ // we don't have to worry about a guide snapping to itself here
+ Geom::Point normal_orig = normal;
+ m.guideFreeSnap(event_dt, normal, false, false);
+ // After snapping, both event_dt and normal have been modified accordingly; we'll take the normal (of the
+ // curve we snapped to) to set the normal the guide. And rotate it by 90 deg. if needed
+ if (pref_perp) { // Perpendicular snapping to paths is requested by the user, so let's do that
+ if (normal != normal_orig) {
+ normal = Geom::rot90(normal);
+ }
+ }
+ if (!(pref_tang || pref_perp)) { // if we don't want to snap either perpendicularly or tangentially, then
+ normal = normal_orig; // we must restore the normal to it's original state
+ }
+ // Restore the preferences
+ m.snapprefs.setSnapPerp(pref_perp);
+ m.snapprefs.setSnapTang(pref_tang);
+ m.unSetup();
+}
+
/*
Local Variables:
mode:c++
diff --git a/src/widgets/desktop-widget.h b/src/widgets/desktop-widget.h
index f0d4ac3bf..6ad430fa3 100644
--- a/src/widgets/desktop-widget.h
+++ b/src/widgets/desktop-widget.h
@@ -27,6 +27,7 @@
// forward declaration
typedef struct _EgeColorProfTracker EgeColorProfTracker;
struct SPCanvas;
+struct SPCanvasItem;
class SPDesktop;
struct SPDesktopWidget;
class SPObject;
@@ -53,9 +54,6 @@ class ToggleButton;
SPViewWidget *sp_desktop_widget_new(SPNamedView *namedview);
void sp_desktop_widget_show_decorations(SPDesktopWidget *dtw, gboolean show);
-void sp_desktop_widget_iconify(SPDesktopWidget *dtw);
-void sp_desktop_widget_maximize(SPDesktopWidget *dtw);
-void sp_desktop_widget_fullscreen(SPDesktopWidget *dtw);
void sp_desktop_widget_update_hruler (SPDesktopWidget *dtw);
void sp_desktop_widget_update_vruler (SPDesktopWidget *dtw);
@@ -144,9 +142,9 @@ private:
Geom::Point _ruler_origin;
double _dt2r;
-public:
+ SPCanvas *_canvas;
- SPCanvas *canvas;
+public:
Inkscape::Widgets::LayerSelector *layer_selector;
@@ -178,11 +176,11 @@ public:
Geom::Point getPointer() override
{ return _dtw->window_get_pointer(); }
void setIconified() override
- { sp_desktop_widget_iconify (_dtw); }
+ { _dtw->iconify(); }
void setMaximized() override
- { sp_desktop_widget_maximize (_dtw); }
+ { _dtw->maximize(); }
void setFullscreen() override
- { sp_desktop_widget_fullscreen (_dtw); }
+ { _dtw->fullscreen(); }
bool shutdown() override
{ return _dtw->shutdown(); }
void destroy() override
@@ -279,6 +277,12 @@ public:
void update_rulers();
double get_hruler_thickness() const;
double get_vruler_thickness() const;
+ GtkAllocation get_canvas_allocation() const;
+ static int hruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidget *dtw);
+ static int vruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidget *dtw);
+ void iconify();
+ void maximize();
+ void fullscreen();
private:
GtkWidget *tool_toolbox;
@@ -308,7 +312,11 @@ private:
#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
static void cms_adjust_toggled( GtkWidget *button, gpointer data );
+ static void color_profile_event(EgeColorProfTracker *tracker, SPDesktopWidget *dtw);
#endif
+ static gint ruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidget *dtw, bool horiz);
+ static void ruler_snap_new_guide(SPDesktop *desktop, SPCanvasItem *guide, Geom::Point &event_dt, Geom::Point &normal);
+ static gint event(GtkWidget *widget, GdkEvent *event, SPDesktopWidget *dtw);
};
/// The SPDesktopWidget vtable