Graphviz  2.41.20171026.1811
callbacks.c
Go to the documentation of this file.
1 /* $Id$ $Revision$ */
2 /* vim:set shiftwidth=4 ts=8: */
3 
4 /*************************************************************************
5  * Copyright (c) 2011 AT&T Intellectual Property
6  * All rights reserved. This program and the accompanying materials
7  * are made available under the terms of the Eclipse Public License v1.0
8  * which accompanies this distribution, and is available at
9  * http://www.eclipse.org/legal/epl-v10.html
10  *
11  * Contributors: See CVS logs. Details at http://www.graphviz.org/
12  *************************************************************************/
13 
14 #include "config.h"
15 
16 #include <gtk/gtk.h>
17 
18 #include "gvplugin_device.h"
19 
20 #include "callbacks.h"
21 #include "interface.h"
22 #include "support.h"
23 
24 void
25 on_new1_activate (GtkMenuItem *menuitem,
26  gpointer user_data)
27 {
28  GtkWindow *window1;
29  GVJ_t *job;
30 
31  window1 = GTK_WINDOW(menuitem);
32  job = g_object_get_data(G_OBJECT(window1), "job");
33 
34  (job->callbacks->read)(job, NULL, "dot");
35 
36  // should there be specific menus for (un)directed graphs etc?
37  // - I think the directed flag only affects layout and rendering
38  // so I plan to make it look like a graph attribute.
39  // Similarly "strict".
40 }
41 
42 static void
43 ui_open_graph(GtkWindow *window1, gchar *filename)
44 {
45  GVJ_t *job;
46  GtkWidget *dialog;
47 
48  job = g_object_get_data(G_OBJECT(window1), "job");
49  dialog = gtk_file_chooser_dialog_new(
50  "Open graph", window1, GTK_FILE_CHOOSER_ACTION_OPEN,
51  "Cancel", GTK_RESPONSE_CANCEL,
52  "Open", GTK_RESPONSE_ACCEPT,
53  NULL);
54  if (filename)
55  gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), filename);
56  if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
57  filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
58  gtk_widget_destroy(dialog);
59  if (filename) {
60  (job->callbacks->read)(job, filename, "dot");
61 // if (!file) // we'll probably want to create a error dialog function
62 // fprintf(stderr, "Could not open file: %s\n", filename);
63 // else
64  g_object_set_data_full(G_OBJECT(window1),
65  "activefilename", filename, (GDestroyNotify)g_free);
66  }
67 }
68 
69 void
70 on_open1_activate (GtkMenuItem *menuitem,
71  gpointer user_data)
72 {
73  GtkWindow *window1;
74  gchar *filename;
75 
76  window1 = GTK_WINDOW(menuitem);
77  filename = g_object_get_data(G_OBJECT(window1), "activefilename");
78  ui_open_graph(window1, filename);
79 }
80 
81 static void
82 ui_save_graph(GtkWindow *window1, gchar *filename)
83 {
84  GVJ_t *job;
85  GtkWidget *dialog;
86 
87  job = (GVJ_t *)g_object_get_data(G_OBJECT(window1), "job");
88 
89  dialog = gtk_file_chooser_dialog_new(
90  "Save graph as", window1, GTK_FILE_CHOOSER_ACTION_SAVE,
91  "Cancel", GTK_RESPONSE_CANCEL,
92  "Save", GTK_RESPONSE_ACCEPT,
93  NULL);
94  filename = g_object_get_data(G_OBJECT(window1), "activefilename");
95  if (filename)
96  gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), filename);
97  if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
98  filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
99  gtk_widget_destroy(dialog);
100  if (filename) {
101  (job->callbacks->render)(job, "dot", filename);
102  g_object_set_data_full(G_OBJECT(window1),
103  "activefilename", filename, (GDestroyNotify)g_free);
104  }
105 }
106 
107 void
108 on_save1_activate (GtkMenuItem *menuitem,
109  gpointer user_data)
110 {
111  GtkWindow *window1;
112  gchar *filename;
113 
114  window1 = GTK_WINDOW(menuitem);
115  filename = (gchar *)g_object_get_data(G_OBJECT(window1), "activefilename");
116  ui_save_graph(window1, filename);
117 }
118 
119 
120 void
121 on_save_as1_activate (GtkMenuItem *menuitem,
122  gpointer user_data)
123 {
124  GtkWindow *window1;
125 
126  window1 = GTK_WINDOW(menuitem);
127  ui_save_graph(window1, NULL);
128 }
129 
130 
131 void
132 on_quit1_activate (GtkMenuItem *menuitem,
133  gpointer user_data)
134 {
135  gtk_widget_destroy(GTK_WIDGET(gtk_widget_get_toplevel(GTK_WIDGET(menuitem))));
136  gtk_main_quit();
137 }
138 
139 
140 void
141 on_cut1_activate (GtkMenuItem *menuitem,
142  gpointer user_data)
143 {
144  // I am thinking that we will annotate a node as to whether it is selected,
145  // then retrieve a list of selected nodes for these operations
146 }
147 
148 
149 void
150 on_copy1_activate (GtkMenuItem *menuitem,
151  gpointer user_data)
152 {
153 
154 }
155 
156 
157 void
158 on_paste1_activate (GtkMenuItem *menuitem,
159  gpointer user_data)
160 {
161 
162 }
163 
164 
165 void
166 on_delete1_activate (GtkMenuItem *menuitem,
167  gpointer user_data)
168 {
169 
170 }
171 
172 
173 void
174 on_about1_activate (GtkMenuItem *menuitem,
175  gpointer user_data)
176 {
177  static gchar *authors[] = {
178  "John Ellson",
179  "Emden Gansner",
180  "Stephen North",
181  "special thanks to Michael Lawrence",
182  NULL };
183  GtkWindow *window = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(menuitem)));
184  gtk_show_about_dialog(window,
185  "name", "DotEdit",
186  "program-name", "DotEdit",
187  "version", "0.1",
188  "copyright", "(C) 2011 AT&T Intellectual Procerty.",
189  "license", "Eclipse Public License v1.0.",
190  "website", "http://www.graphviz.org",
191  "comments", "Visualize and edit graphs of nodes and edges",
192  "authors", authors,
193  NULL);
194 }
195 
196 static void
197 load_store_with_attrs(GtkListStore *model, GVJ_t *job)
198 {
199 #if 0
200  gint attrs_len = job->selected_obj_attributes.argc, i;
201  gchar **attrs = job->selected_obj_attributes.argv;
202  GtkTreeIter iter;
203  gvattr_t type;
204 #endif
205 
206  gtk_list_store_clear(model);
207 
208 #if 0
209  for (i = 0; i < attrs_len; i+=3) {
210  gtk_list_store_append(model, &iter);
211  gtk_list_store_set(model, &iter, 0, attrs[i], 1, g_strdup(attrs[i+1]), -1);
212  type = (gvattr_t)attrs[i+2];
213  }
214 #endif
215 }
216 
217 
218 gboolean
219 on_drawingarea1_expose_event (GtkWidget *widget,
220  GdkEventExpose *event,
221  gpointer user_data)
222 {
223  GVJ_t *job;
224  cairo_t *cr;
225 
226  job = (GVJ_t *)g_object_get_data(G_OBJECT(widget),"job");
227  cr = gdk_cairo_create(widget->window);
228 
229  (job->callbacks->motion)(job, job->pointer);
230 
231  job->context = (void *)cr;
232  job->external_context = TRUE;
233  job->width = widget->allocation.width;
234  job->height = widget->allocation.height;
235  if (job->has_been_rendered) {
236  (job->callbacks->refresh)(job);
237  }
238  else {
239  (job->callbacks->refresh)(job);
240 
241 // FIXME - copy image to keyhole
242 // the keyhole image is a fixed size and doesn;t need to be recomputed
243 // each time. save a pixmap, then each time, show pixmap and overlay
244 // with scaled view rectangle.
245 
246  }
247  cairo_destroy(cr);
248 
249  load_store_with_attrs(GTK_LIST_STORE(g_object_get_data(G_OBJECT(widget), "attr_store")), job);
250 
251  return FALSE;
252 }
253 
254 
255 gboolean
257  GdkEventMotion *event,
258  gpointer user_data)
259 {
260  GVJ_t *job;
261 
262  job = (GVJ_t *)g_object_get_data(G_OBJECT(widget),"job");
263  job->pointer.x = event->x;
264  job->pointer.y = event->y;
265  gtk_widget_queue_draw(widget);
266 
267 #if 0
268  if (job->active_tooltip && job->active_tooltip[0])
269  fprintf(stderr,"tooltip = \"%s\"\n", job->active_tooltip);
270 #endif
271 
272  return FALSE;
273 }
274 
275 
276 gboolean
278  GdkEventMotion *event,
279  gpointer user_data)
280 {
281 
282  return FALSE;
283 }
284 
285 
286 
287 gboolean
288 on_drawingarea2_expose_event (GtkWidget *widget,
289  GdkEventExpose *event,
290  gpointer user_data)
291 {
292  GVJ_t *job;
293  cairo_t *cr;
294  double tmp;
295 
296  job = (GVJ_t *)g_object_get_data(G_OBJECT(widget),"job");
297  cr = gdk_cairo_create(widget->window);
298 
299  (job->callbacks->motion)(job, job->pointer);
300 
301  job->context = (void *)cr;
302  job->external_context = TRUE;
303  job->width = widget->allocation.width;
304  job->height = widget->allocation.height;
305 
306  tmp = job->zoom;
307  job->zoom = MIN(job->width * POINTS_PER_INCH / (job->bb.UR.x * job->dpi.x),
308  job->height * POINTS_PER_INCH / (job->bb.UR.y * job->dpi.y));
309  (job->callbacks->refresh)(job);
310  job->zoom = tmp;
311 
312  cairo_destroy(cr);
313 
314  return FALSE;
315 }
316 
317 gboolean
318 on_window1_delete_event (GtkWidget *widget,
319  GdkEvent *event,
320  gpointer user_data)
321 {
322  gtk_main_quit();
323  return FALSE;
324 }
325 
326 
327 gboolean
329  GdkEventConfigure *event,
330  gpointer user_data)
331 {
332  GVJ_t *job;
333  double zoom_to_fit;
334 
335 /*FIXME - should allow for margins */
336 /* - similar zoom_to_fit code exists in: */
337 /* plugin/gtk/callbacks.c */
338 /* plugin/xlib/gvdevice_xlib.c */
339 /* lib/gvc/gvevent.c */
340 
341  job = (GVJ_t *)g_object_get_data(G_OBJECT(widget),"job");
342  if (! job->has_been_rendered) {
343  zoom_to_fit = MIN((double) event->width / (double) job->width,
344  (double) event->height / (double) job->height);
345  if (zoom_to_fit < 1.0) /* don't make bigger */
346  job->zoom *= zoom_to_fit;
347  }
348  else if (job->fit_mode) {
349  zoom_to_fit = MIN((double) event->width / (double) job->width,
350  (double) event->height / (double) job->height);
351  job->zoom *= zoom_to_fit;
352  }
353  if (event->width > job->width || event->height > job->height)
354  job->has_grown = TRUE;
355  job->width = event->width;
356  job->height = event->height;
357  job->needs_refresh = TRUE;
358 
359  return FALSE;
360 }
361 
362 
363 gboolean
365  GdkEventButton *event,
366  gpointer user_data)
367 {
368  GVJ_t *job;
369  pointf pointer;
370 
371  job = (GVJ_t *)g_object_get_data(G_OBJECT(widget),"job");
372  pointer.x = event->x;
373  pointer.y = event->y;
374  (job->callbacks->button_press)(job, event->button, pointer);
375 
376  load_store_with_attrs(GTK_LIST_STORE(g_object_get_data(G_OBJECT(widget), "attr_store")), job);
377  return FALSE;
378 }
379 
380 
381 gboolean
383  GdkEventButton *event,
384  gpointer user_data)
385 {
386  GVJ_t *job;
387  pointf pointer;
388 
389  job = (GVJ_t *)g_object_get_data(G_OBJECT(widget),"job");
390  pointer.x = event->x;
391  pointer.y = event->y;
392  (job->callbacks->button_release)(job, event->button, pointer);
393 
394  return FALSE;
395 }
396 
397 
398 gboolean
399 on_drawingarea1_scroll_event (GtkWidget *widget,
400  GdkEvent *event,
401  gpointer user_data)
402 {
403  GVJ_t *job;
404  pointf pointer;
405 
406  job = (GVJ_t *)g_object_get_data(G_OBJECT(widget),"job");
407  pointer.x = ((GdkEventScroll *)event)->x;
408  pointer.y = ((GdkEventScroll *)event)->y;
409  switch (((GdkEventScroll *)event)->direction) {
410  case GDK_SCROLL_UP:
411  (job->callbacks->button_press)(job, 4, pointer);
412  break;
413  case GDK_SCROLL_DOWN:
414  (job->callbacks->button_press)(job, 5, pointer);
415  break;
416  case GDK_SCROLL_LEFT:
417  case GDK_SCROLL_RIGHT:
418  break;
419  }
420  gtk_widget_queue_draw(widget);
421 
422  return FALSE;
423 }
424 
425 gboolean
426 on_button1_button_press_event (GtkWidget *widget,
427  GdkEventButton *event,
428  gpointer user_data)
429 {
430 
431 
432 fprintf(stderr, "will delete selected object\n");
433 
434  return FALSE;
435 }
436 
void on_paste1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:158
void(* button_press)(GVJ_t *job, int button, pointf pointer)
Definition: gvcjob.h:158
pointf pointer
Definition: gvcjob.h:352
#define MIN(a, b)
Definition: arith.h:35
gboolean on_button1_button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
Definition: callbacks.c:426
void * context
Definition: gvcjob.h:304
void(* refresh)(GVJ_t *job)
Definition: gvcjob.h:157
gboolean on_drawingarea1_button_release_event(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
Definition: callbacks.c:382
Definition: geom.h:28
boolean has_grown
Definition: gvcjob.h:345
unsigned int width
Definition: gvcjob.h:336
void on_save1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:108
void on_save_as1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:121
Definition: gvcjob.h:271
void on_quit1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:132
#define POINTS_PER_INCH
Definition: geom.h:62
gboolean on_drawingarea1_scroll_event(GtkWidget *widget, GdkEvent *event, gpointer user_data)
Definition: callbacks.c:399
void on_about1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:174
void(* button_release)(GVJ_t *job, int button, pointf pointer)
Definition: gvcjob.h:159
void on_cut1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:141
pointf dpi
Definition: gvcjob.h:334
void on_delete1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:166
char * active_tooltip
Definition: gvcjob.h:359
double y
Definition: geom.h:28
gvattr_t
Definition: gvcjob.h:42
gboolean on_drawingarea1_motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
Definition: callbacks.c:256
void on_new1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:25
void on_copy1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:150
gboolean on_drawingarea1_configure_event(GtkWidget *widget, GdkEventConfigure *event, gpointer user_data)
Definition: callbacks.c:328
boxf bb
Definition: gvcjob.h:320
void on_open1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:70
unsigned char button
Definition: gvcjob.h:351
void(* render)(GVJ_t *job, const char *format, const char *filename)
Definition: gvcjob.h:165
#define NULL
Definition: logic.h:39
gv_argvlist_t selected_obj_attributes
Definition: gvcjob.h:362
double x
Definition: geom.h:28
boolean external_context
Definition: gvcjob.h:305
void(* read)(GVJ_t *job, const char *filename, const char *layout)
Definition: gvcjob.h:163
boolean has_been_rendered
Definition: gvcjob.h:345
boolean needs_refresh
Definition: gvcjob.h:345
gboolean on_drawingarea2_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
Definition: callbacks.c:288
gboolean on_drawingarea1_button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
Definition: callbacks.c:364
boolean fit_mode
Definition: gvcjob.h:345
void(* motion)(GVJ_t *job, pointf pointer)
Definition: gvcjob.h:160
gboolean on_drawingarea1_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
Definition: callbacks.c:219
gboolean on_window1_delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data)
Definition: callbacks.c:318
double zoom
Definition: gvcjob.h:327
pointf UR
Definition: geom.h:35
unsigned int height
Definition: gvcjob.h:337
#define FALSE
Definition: cgraph.h:35
gvdevice_callbacks_t * callbacks
Definition: gvcjob.h:297
char ** argv
Definition: gvcjob.h:151
gboolean on_drawingarea2_motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
Definition: callbacks.c:277
#define TRUE
Definition: cgraph.h:38