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