1 #define __SP_DESKTOP_EVENTS_C__
3 /*
4 * Event handlers for SPDesktop
5 *
6 * Author:
7 * Lauris Kaplinski <lauris@kaplinski.com>
8 *
9 * Copyright (C) 1999-2002 Lauris Kaplinski
10 *
11 * Released under GNU GPL, read the file 'COPYING' for more information
12 */
14 #ifdef HAVE_CONFIG_H
15 # include <config.h>
16 #endif
17 #include "display/guideline.h"
18 #include "helper/unit-menu.h"
19 #include "helper/units.h"
20 #include "desktop.h"
21 #include "document.h"
22 #include "sp-guide.h"
23 #include "sp-namedview.h"
24 #include "desktop-handles.h"
25 #include "event-context.h"
26 #include "widgets/desktop-widget.h"
27 #include "sp-metrics.h"
28 #include <glibmm/i18n.h>
29 #include "dialogs/dialog-events.h"
30 #include "message-context.h"
31 #include "xml/repr.h"
32 #include "dialogs/guidelinedialog.h"
33 #include "snap.h"
35 /* Root item handler */
37 int sp_desktop_root_handler(SPCanvasItem */*item*/, GdkEvent *event, SPDesktop *desktop)
38 {
39 return sp_event_context_root_handler(desktop->event_context, event);
40 }
43 static gint sp_dt_ruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidget *dtw, bool horiz)
44 {
45 static bool dragging = false;
46 static SPCanvasItem *guide = NULL;
47 static Geom::Point normal;
48 int wx, wy;
50 SPDesktop *desktop = dtw->desktop;
51 Inkscape::XML::Node *repr = SP_OBJECT_REPR(desktop->namedview);
53 gdk_window_get_pointer(GTK_WIDGET(dtw->canvas)->window, &wx, &wy, NULL);
54 NR::Point const event_win(wx, wy);
56 gint width, height;
57 gdk_window_get_geometry(GTK_WIDGET(dtw->canvas)->window, NULL /*x*/, NULL /*y*/, &width, &height, NULL/*depth*/);
59 switch (event->type) {
60 case GDK_BUTTON_PRESS:
61 if (event->button.button == 1) {
62 dragging = true;
63 NR::Point const event_w(sp_canvas_window_to_world(dtw->canvas, event_win));
64 NR::Point const event_dt(desktop->w2d(event_w));
66 // explicitly show guidelines; if I draw a guide, I want them on
67 sp_repr_set_boolean(repr, "showguides", TRUE);
68 sp_repr_set_boolean(repr, "inkscape:guide-bbox", TRUE);
70 if (horiz) {
71 if (wx < 50) {
72 normal = Geom::Point(-1.,1.);
73 normal.normalize();
74 } else if (wx > width - 50) {
75 normal = Geom::Point(1.,1.);
76 normal.normalize();
77 } else {
78 normal = Geom::Point(0.,1.);
79 }
80 } else {
81 if (wy < 50) {
82 normal = Geom::Point(-1.,1.);
83 normal.normalize();
84 } else if (wy > height - 50) {
85 normal = Geom::Point(1.,1.);
86 normal.normalize();
87 } else {
88 normal = Geom::Point(1.,0.);
89 }
90 }
92 guide = sp_guideline_new(desktop->guides, event_dt.to_2geom(), normal);
93 sp_guideline_set_color(SP_GUIDELINE(guide), desktop->namedview->guidehicolor);
94 gdk_pointer_grab(widget->window, FALSE,
95 (GdkEventMask)(GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK ),
96 NULL, NULL,
97 event->button.time);
98 }
99 break;
100 case GDK_MOTION_NOTIFY:
101 if (dragging) {
102 NR::Point const event_w(sp_canvas_window_to_world(dtw->canvas, event_win));
103 NR::Point event_dt(desktop->w2d(event_w));
105 SnapManager const &m = desktop->namedview->snap_manager;
106 event_dt = m.guideSnap(event_dt, normal).getPoint();
108 sp_guideline_set_position(SP_GUIDELINE(guide), event_dt.to_2geom());
109 desktop->set_coordinate_status(event_dt);
110 desktop->setPosition (event_dt);
111 }
112 break;
113 case GDK_BUTTON_RELEASE:
114 if (dragging && event->button.button == 1) {
115 gdk_pointer_ungrab(event->button.time);
116 NR::Point const event_w(sp_canvas_window_to_world(dtw->canvas, event_win));
117 NR::Point event_dt(desktop->w2d(event_w));
119 SnapManager const &m = desktop->namedview->snap_manager;
120 event_dt = m.guideSnap(event_dt, normal).getPoint();
122 dragging = false;
123 gtk_object_destroy(GTK_OBJECT(guide));
124 guide = NULL;
125 if ((horiz ? wy : wx) >= 0) {
126 Inkscape::XML::Document *xml_doc = sp_document_repr_doc(desktop->doc());
127 Inkscape::XML::Node *repr = xml_doc->createElement("sodipodi:guide");
128 sp_repr_set_point(repr, "orientation", normal);
129 sp_repr_set_point(repr, "position", event_dt.to_2geom());
130 SP_OBJECT_REPR(desktop->namedview)->appendChild(repr);
131 Inkscape::GC::release(repr);
132 sp_document_done(sp_desktop_document(desktop), SP_VERB_NONE,
133 _("Create guide"));
134 }
135 desktop->set_coordinate_status(event_dt);
136 }
137 default:
138 break;
139 }
141 return FALSE;
142 }
144 int sp_dt_hruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidget *dtw)
145 {
146 return sp_dt_ruler_event(widget, event, dtw, true);
147 }
149 int sp_dt_vruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidget *dtw)
150 {
151 return sp_dt_ruler_event(widget, event, dtw, false);
152 }
154 /* Guides */
156 gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
157 {
158 static bool dragging = false;
159 static bool moved = false;
160 gint ret = FALSE;
162 SPGuide *guide = SP_GUIDE(data);
163 SPDesktop *desktop = static_cast<SPDesktop*>(gtk_object_get_data(GTK_OBJECT(item->canvas), "SPDesktop"));
165 switch (event->type) {
166 case GDK_2BUTTON_PRESS:
167 if (event->button.button == 1) {
168 dragging = false;
169 sp_canvas_item_ungrab(item, event->button.time);
170 Inkscape::UI::Dialogs::GuidelinePropertiesDialog::showDialog(guide, desktop);
171 ret = TRUE;
172 }
173 break;
174 case GDK_BUTTON_PRESS:
175 if (event->button.button == 1) {
176 dragging = true;
177 sp_canvas_item_grab(item,
178 ( GDK_BUTTON_RELEASE_MASK |
179 GDK_BUTTON_PRESS_MASK |
180 GDK_POINTER_MOTION_MASK ),
181 NULL,
182 event->button.time);
183 ret = TRUE;
184 }
185 break;
186 case GDK_MOTION_NOTIFY:
187 if (dragging) {
188 NR::Point const motion_w(event->motion.x,
189 event->motion.y);
190 NR::Point motion_dt(desktop->w2d(motion_w));
192 // This is for snapping while dragging existing guidelines. New guidelines,
193 // which are dragged off the ruler, are being snapped in sp_dt_ruler_event
194 SnapManager const &m = desktop->namedview->snap_manager;
195 motion_dt = m.guideSnap(motion_dt, guide->normal_to_line).getPoint();
197 sp_guide_moveto(*guide, motion_dt.to_2geom(), false);
198 moved = true;
199 desktop->set_coordinate_status(motion_dt);
200 desktop->setPosition (motion_dt);
201 ret = TRUE;
202 }
203 break;
204 case GDK_BUTTON_RELEASE:
205 if (dragging && event->button.button == 1) {
206 if (moved) {
207 NR::Point const event_w(event->button.x,
208 event->button.y);
209 NR::Point event_dt(desktop->w2d(event_w));
211 SnapManager const &m = desktop->namedview->snap_manager;
212 event_dt = m.guideSnap(event_dt, guide->normal_to_line).getPoint();
214 if (sp_canvas_world_pt_inside_window(item->canvas, event_w)) {
215 sp_guide_moveto(*guide, event_dt.to_2geom(), true);
216 sp_document_done(sp_desktop_document(desktop), SP_VERB_NONE,
217 _("Move guide"));
218 } else {
219 /* Undo movement of any attached shapes. */
220 sp_guide_moveto(*guide, guide->point_on_line, false);
221 sp_guide_remove(guide);
222 sp_document_done(sp_desktop_document(desktop), SP_VERB_NONE,
223 _("Delete guide"));
224 }
225 moved = false;
226 desktop->set_coordinate_status(event_dt);
227 desktop->setPosition (event_dt);
228 }
229 dragging = false;
230 sp_canvas_item_ungrab(item, event->button.time);
231 ret=TRUE;
232 }
233 case GDK_ENTER_NOTIFY:
234 {
235 sp_guideline_set_color(SP_GUIDELINE(item), guide->hicolor);
237 char *guide_description = sp_guide_description(guide);
238 desktop->guidesMessageContext()->setF(Inkscape::NORMAL_MESSAGE, "%s", guide_description);
239 g_free(guide_description);
240 break;
241 }
242 case GDK_LEAVE_NOTIFY:
243 sp_guideline_set_color(SP_GUIDELINE(item), guide->color);
244 desktop->guidesMessageContext()->clear();
245 break;
246 default:
247 break;
248 }
250 return ret;
251 }
254 /*
255 Local Variables:
256 mode:c++
257 c-file-style:"stroustrup"
258 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
259 indent-tabs-mode:nil
260 fill-column:99
261 End:
262 */
263 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :