1 /*
2 Copyright (C) 2002 Kai Sterker <kai.sterker@gmail.com>
3 Part of the Adonthell Project <http://adonthell.nongnu.org>
4
5 Dlgedit is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 Dlgedit is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with Dlgedit. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 /**
20 * @file gui_graph_events.cc
21 *
22 * @author Kai Sterker
23 * @brief Event-callbacks for the dialogue graph view
24 */
25
26 #include <gdk/gdkkeysyms.h>
27 #include "gui_dlgedit.h"
28
29 // Window resized
configure_event(GtkWidget * widget,GdkEventConfigure * event,gpointer data)30 gint configure_event (GtkWidget *widget, GdkEventConfigure *event, gpointer data)
31 {
32 GuiGraph *graph = (GuiGraph *) data;
33
34 // resize the drawing area
35 graph->resizeSurface (widget);
36
37 // do a redraw
38 graph->draw ();
39
40 // redraw the preview
41 GuiDlgedit::window->list()->draw ();
42
43 return TRUE;
44 }
45
46 // Redraw the screen from the backing pixmap
expose_event(GtkWidget * widget,GdkEventExpose * event,gpointer data)47 gint expose_event (GtkWidget * widget, GdkEventExpose * event, gpointer data)
48 {
49 GuiGraph *graph = (GuiGraph *) data;
50
51 cairo_t *cr = gdk_cairo_create (GDK_WINDOW(gtk_widget_get_window(widget)));
52 cairo_set_source_surface (cr, graph->pixmap (), 0, 0);
53 gdk_cairo_rectangle (cr, &event->area);
54 cairo_fill (cr);
55 cairo_destroy(cr);
56
57 return FALSE;
58 }
59
60 // Mouse-button pressed on Drawing Area
button_press_event(GtkWidget * widget,GdkEventButton * event,gpointer data)61 gint button_press_event (GtkWidget *widget, GdkEventButton *event, gpointer data)
62 {
63 GuiGraph *graph = (GuiGraph *) data;
64 DlgPoint point ((int) event->x, (int) event->y);
65
66 #ifdef __APPLE__
67 // simulate right click on OSX
68 if (event->state & GDK_CONTROL_MASK)
69 {
70 event->button = 3;
71 }
72 #endif
73
74 switch (event->button)
75 {
76 // Middle button pressed
77 case 2:
78 {
79 // ignore edit command if in preview mode
80 if (GuiDlgedit::window->mode () == L10N_PREVIEW)
81 break;
82
83 // If nothing selected, see if we're over a node
84 if (graph->mode () == IDLE)
85 if (!graph->selectNode (point))
86 // create a submodule, if we aren't
87 graph->newModule (point);
88
89 // Edit node
90 if (graph->mode () == NODE_SELECTED)
91 graph->editNode ();
92
93 break;
94 }
95
96 // Right button pressed
97 case 3:
98 {
99 // if something selected -> deselect
100 if (graph->mode () == NODE_SELECTED)
101 graph->deselectNode ();
102
103 break;
104 }
105
106 default: break;
107 }
108
109 return TRUE;
110 }
111
112 // Mouse moved over drawing area
motion_notify_event(GtkWidget * widget,GdkEventMotion * event,gpointer data)113 gint motion_notify_event (GtkWidget *widget, GdkEventMotion *event, gpointer data)
114 {
115 GuiGraph *graph = (GuiGraph *) data;
116 DlgPoint point ((int) event->x, (int) event->y);
117
118 // scroll the graph if necessary (this has to happen before
119 // anything else, as the next method(s) change 'point'.
120 graph->prepareScrolling (point);
121
122 // Dragging dialogue nodes
123 if (event->state & GDK_BUTTON1_MASK)
124 {
125 // don't allow dragging if in preview mode
126 if (GuiDlgedit::window->mode () == L10N_PREVIEW)
127 return FALSE;
128
129 // no node being dragged so far -> start dragging
130 if (graph->mode () != NODE_DRAGGED)
131 graph->prepareDragging (point);
132 // otherwise continue moving
133 else
134 graph->drag (point);
135 }
136 // highlight nodes under the cursor and display their 'tooltip'
137 else graph->mouseMoved (point);
138
139 return FALSE;
140 }
141
142 // Mouse-button released on Drawing Area
button_release_event(GtkWidget * widget,GdkEventButton * event,gpointer data)143 gint button_release_event (GtkWidget *widget, GdkEventButton *event, gpointer data)
144 {
145 GuiGraph *graph = (GuiGraph *) data;
146 DlgPoint point ((int) event->x, (int) event->y);
147
148 #ifdef __APPLE__
149 // simulate right click on OSX
150 if (event->state & GDK_CONTROL_MASK)
151 {
152 event->button = 3;
153 }
154 #endif
155
156 // Left button released
157 if (event->button == 1)
158 {
159 switch (graph->mode ())
160 {
161 // nothing selected
162 case IDLE:
163 {
164 // select the node under the cursor, if any
165 if (!graph->selectNode (point))
166 // otherwise create a new circle at that position
167 if (GuiDlgedit::window->mode () != L10N_PREVIEW)
168 graph->newCircle (point);
169
170 break;
171 }
172
173 // node selected
174 case NODE_SELECTED:
175 {
176 // ignore edit command if in preview mode
177 if (GuiDlgedit::window->mode () == L10N_PREVIEW)
178 break;
179
180 // try to create a new link between two nodes
181 graph->newArrow (point);
182 break;
183 }
184
185 // node dragged
186 case NODE_DRAGGED:
187 {
188 // stop dragging
189 graph->stopDragging (point);
190 break;
191 }
192
193 default: break;
194 }
195 }
196 return TRUE;
197 }
198
199 // Key pressed
key_press_notify_event(GtkWidget * widget,GdkEventKey * event,gpointer user_data)200 guint key_press_notify_event (GtkWidget * widget, GdkEventKey * event, gpointer user_data)
201 {
202 GuiGraph *graph = (GuiGraph *) user_data;
203
204 switch (event->keyval)
205 {
206 // scroll up
207 case GDK_KEY_Up:
208 {
209 if (graph->scrollingAllowed())
210 {
211 graph->setScrollOffset(0, 40);
212 graph->scroll();
213 }
214 break;
215 }
216
217 // scroll down
218 case GDK_KEY_Down:
219 {
220 if (graph->scrollingAllowed())
221 {
222 graph->setScrollOffset(0, -40);
223 graph->scroll();
224 }
225 break;
226 }
227
228 // scroll left
229 case GDK_KEY_Left:
230 {
231 if (graph->scrollingAllowed())
232 {
233 graph->setScrollOffset(40, 0);
234 graph->scroll();
235 }
236 break;
237 }
238
239 // scroll right
240 case GDK_KEY_Right:
241 {
242 if (graph->scrollingAllowed())
243 {
244 graph->setScrollOffset(-40, 0);
245 graph->scroll();
246 }
247 break;
248 }
249
250 // center current node
251 case 'c':
252 {
253 graph->centerNode ();
254 break;
255 }
256
257 // select parent node
258 case 'w':
259 {
260 if (graph->selectParent ()) graph->centerNode ();
261 break;
262 }
263
264 // select child node
265 case 's':
266 {
267 if (graph->selectChild ()) graph->centerNode ();
268 break;
269 }
270
271 // select sibling to the left
272 case 'a':
273 {
274 if (graph->selectSibling (PREV)) graph->centerNode ();
275 break;
276 }
277
278 // select sibling to the right
279 case 'd':
280 {
281 if (graph->selectSibling (NEXT)) graph->centerNode ();
282 break;
283 }
284
285 // edit selected node
286 case GDK_KEY_Return:
287 {
288 int x, y;
289
290 // ignore edit command if in preview mode
291 if (GuiDlgedit::window->mode () == L10N_PREVIEW)
292 break;
293
294 // get cursor position
295 gtk_widget_get_pointer (graph->drawingArea (), &x, &y);
296 DlgPoint point (x, y);
297
298 // If nothing selected, see if we're over a node
299 if (graph->mode () == IDLE)
300 if (!graph->selectNode (point))
301 // create a submodule, if we aren't
302 graph->newModule (point);
303
304 // Edit node
305 if (graph->mode () == NODE_SELECTED)
306 graph->editNode ();
307
308 break;
309 }
310
311 // deselect Node
312 case GDK_KEY_Escape:
313 {
314 graph->deselectNode ();
315 break;
316 }
317
318 // delete node
319 case GDK_KEY_BackSpace: // fall through
320 case GDK_KEY_Delete:
321 {
322 // ignore delete command if in preview mode
323 if (GuiDlgedit::window->mode () == L10N_PREVIEW)
324 break;
325
326 graph->deleteNode ();
327 break;
328 }
329
330 // key not consumed
331 default:
332 {
333 return FALSE;
334 }
335 }
336
337 return TRUE;
338 }
339