1 /* Dia -- an diagram creation/manipulation program
2  * Copyright (C) 1998 Alexander Larsson
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  */
18 
19 #include <config.h>
20 
21 #ifdef GNOME
22 #undef GTK_DISABLE_DEPRECATED /* gnome */
23 #include <gnome.h>
24 #else
25 #undef GTK_DISABLE_DEPRECATED /* GtkTooltips */
26 #include <gtk/gtk.h>
27 #endif
28 #include "gtkwrapbox.h"
29 #include "gtkhwrapbox.h"
30 
31 #include <stdio.h>
32 #include <string.h>
33 
34 #include "diagram.h"
35 #include "object.h"
36 #include "layer_dialog.h"
37 #include "interface.h"
38 #include "display.h"
39 #include "preferences.h"
40 #include "commands.h"
41 #include "dia_dirs.h"
42 #include "diagram_tree_window.h"
43 #include "intl.h"
44 #include "navigation.h"
45 #include "persistence.h"
46 #include "diaarrowchooser.h"
47 #include "dialinechooser.h"
48 #include "widgets.h"
49 #include "message.h"
50 
51 #include <gdk-pixbuf/gdk-pixbuf.h>
52 #include "dia-app-icons.h"
53 #include "diacanvas.h"
54 
55 #include "pixmaps/swap.xpm"
56 #include "pixmaps/default.xpm"
57 #include "pixmaps/missing.xpm"
58 
59 /* HB: file dnd stuff lent by The Gimp, not fully understood but working ...
60  */
61 enum
62 {
63   DIA_DND_TYPE_URI_LIST,
64   DIA_DND_TYPE_TEXT_PLAIN,
65 };
66 
67 static GtkTargetEntry toolbox_target_table[] =
68 {
69   { "text/uri-list", 0, DIA_DND_TYPE_URI_LIST },
70   { "text/plain", 0, DIA_DND_TYPE_TEXT_PLAIN }
71 };
72 
73 static guint toolbox_n_targets = (sizeof (toolbox_target_table) /
74                                  sizeof (toolbox_target_table[0]));
75 
76 static void
77 use_integrated_ui_for_display_shell(DDisplay *ddisp, char *title);
78 
79 static void
dia_dnd_file_drag_data_received(GtkWidget * widget,GdkDragContext * context,gint x,gint y,GtkSelectionData * data,guint info,guint time,DDisplay * ddisp)80 dia_dnd_file_drag_data_received (GtkWidget        *widget,
81                                  GdkDragContext   *context,
82                                  gint              x,
83                                  gint              y,
84                                  GtkSelectionData *data,
85                                  guint             info,
86                                  guint             time,
87 				 DDisplay         *ddisp)
88 {
89   switch (context->action)
90     {
91     case GDK_ACTION_DEFAULT:
92     case GDK_ACTION_COPY:
93     case GDK_ACTION_MOVE:
94     case GDK_ACTION_LINK:
95     case GDK_ACTION_ASK:
96     default:
97       {
98         Diagram *diagram = NULL;
99         gchar *sPath = NULL, *pFrom, *pTo;
100 
101         pFrom = strstr((gchar *) data->data, "file:");
102         while (pFrom) {
103           GError *error = NULL;
104 
105           pTo = pFrom;
106           while (*pTo != 0 && *pTo != 0xd && *pTo != 0xa) pTo ++;
107           sPath = g_strndup(pFrom, pTo - pFrom);
108 
109           /* format changed with Gtk+2.0, use conversion */
110           pFrom = g_filename_from_uri (sPath, NULL, &error);
111 	  if (!ddisp)
112             diagram = diagram_load (pFrom, NULL);
113 	  else {
114 	    diagram = ddisp->diagram;
115 	    if (!diagram_load_into (diagram, pFrom, NULL)) {
116 	      /* the import filter is supposed to show the error message */
117               gtk_drag_finish (context, TRUE, FALSE, time);
118 	      break;
119 	    }
120 	  }
121 
122           g_free (pFrom);
123           g_free(sPath);
124 
125           if (diagram != NULL) {
126             diagram_update_extents(diagram);
127             layer_dialog_set_diagram(diagram);
128 
129 	    if (diagram->displays == NULL) {
130 	      new_display(diagram);
131 	    }
132           }
133 
134           pFrom = strstr(pTo, "file:");
135         } /* while */
136         gtk_drag_finish (context, TRUE, FALSE, time);
137       }
138       break;
139     }
140   return;
141 }
142 
143 static const GtkTargetEntry display_target_table[] = {
144   { "application/x-dia-object", 0, 0 },
145   { "text/uri-list", 0, DIA_DND_TYPE_URI_LIST },
146   { "text/plain", 0, DIA_DND_TYPE_TEXT_PLAIN }
147 };
148 static int display_n_targets = sizeof(display_target_table)/sizeof(display_target_table[0]);
149 
150 ToolButton tool_data[] =
151 {
152   { (char **) dia_modify_tool_icon,
153     N_("Modify object(s)\nUse <Space> to toggle between this and other tools"),
154     NULL,
155     "ToolsModify",
156     { MODIFY_TOOL, NULL, NULL}
157   },
158   { (char **) dia_textedit_tool_icon,
159     N_("Text edit(s)\nUse <Esc> to leave this tool"),
160     "F2",
161     "ToolsTextedit",
162     { TEXTEDIT_TOOL, NULL, NULL}
163   },
164   { (char **) dia_zoom_tool_icon,
165     N_("Magnify"),
166     "M",
167     "ToolsMagnify",
168     { MAGNIFY_TOOL, NULL, NULL}
169   },
170   { (char **) dia_scroll_tool_icon,
171     N_("Scroll around the diagram"),
172     "S",
173     "ToolsScroll",
174     { SCROLL_TOOL, NULL, NULL}
175   },
176   { NULL,
177     N_("Text"),
178     "T",
179     "ToolsText",
180     { CREATE_OBJECT_TOOL, "Standard - Text", NULL }
181   },
182   { NULL,
183     N_("Box"),
184     "R",
185     "ToolsBox",
186     { CREATE_OBJECT_TOOL, "Standard - Box", NULL }
187   },
188   { NULL,
189     N_("Ellipse"),
190     "E",
191     "ToolsEllipse",
192     { CREATE_OBJECT_TOOL, "Standard - Ellipse", NULL }
193   },
194   { NULL,
195     N_("Polygon"),
196     "P",
197     "ToolsPolygon",
198     { CREATE_OBJECT_TOOL, "Standard - Polygon", NULL }
199   },
200   { NULL,
201     N_("Beziergon"),
202     "B",
203     "ToolsBeziergon",
204     { CREATE_OBJECT_TOOL, "Standard - Beziergon", NULL }
205   },
206   { NULL,
207     N_("Line"),
208     "L",
209     "ToolsLine",
210     { CREATE_OBJECT_TOOL, "Standard - Line", NULL }
211   },
212   { NULL,
213     N_("Arc"),
214     "A",
215     "ToolsArc",
216     { CREATE_OBJECT_TOOL, "Standard - Arc", NULL }
217   },
218   { NULL,
219     N_("Zigzagline"),
220     "Z",
221     "ToolsZigzagline",
222     { CREATE_OBJECT_TOOL, "Standard - ZigZagLine", NULL }
223   },
224   { NULL,
225     N_("Polyline"),
226     NULL,
227     "ToolsPolyline",
228     { CREATE_OBJECT_TOOL, "Standard - PolyLine", NULL }
229   },
230   { NULL,
231     N_("Bezierline"),
232     "C",
233     "ToolsBezierline",
234     { CREATE_OBJECT_TOOL, "Standard - BezierLine", NULL }
235   },
236   { NULL,
237     N_("Image"),
238     "I",
239     "ToolsImage",
240     { CREATE_OBJECT_TOOL, "Standard - Image", NULL }
241 #ifdef HAVE_CAIRO
242   },
243   { NULL,
244     N_("Outline"),
245     NULL,
246     "ToolsOutline",
247     { CREATE_OBJECT_TOOL, "Standard - Outline", NULL }
248 #endif
249   }
250 };
251 
252 #define NUM_TOOLS (sizeof (tool_data) / sizeof (ToolButton))
253 const int num_tools = NUM_TOOLS;
254 
255 #define COLUMNS   4
256 #define ROWS      3
257 
258 static GtkWidget *toolbox_shell = NULL;
259 static GtkWidget *tool_widgets[NUM_TOOLS];
260 
261 static struct
262 {
263     GtkWindow    * main_window;
264     GtkToolbar   * toolbar;
265     GtkNotebook  * diagram_notebook;
266     GtkStatusbar * statusbar;
267     GtkWidget    * layer_view;
268 } ui;
269 
270 /*static*/ GtkTooltips *tool_tips;
271 static GSList *tool_group = NULL;
272 
273 GtkWidget *modify_tool_button;
274 
275 /**
276  * Used to determine if the current user interface is the integrated interface or
277  * the distributed interface.  This cannot presently be determined by the preferences
278  * setting because changing that setting at run time does not change the interface.
279  * @return Non-zero if the integrated interface is present, else zero.
280  */
is_integrated_ui(void)281 int is_integrated_ui (void)
282 {
283   return ui.main_window == NULL? 0 : 1;
284 }
285 
286 static void
grid_toggle_snap(GtkWidget * widget,gpointer data)287 grid_toggle_snap(GtkWidget *widget, gpointer data)
288 {
289   DDisplay *ddisp = (DDisplay *)data;
290   ddisplay_set_snap_to_grid(ddisp,
291 			    gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
292 }
293 
294 static void
interface_toggle_mainpoint_magnetism(GtkWidget * widget,gpointer data)295 interface_toggle_mainpoint_magnetism(GtkWidget *widget, gpointer data)
296 {
297   DDisplay *ddisp = (DDisplay *)data;
298   ddisplay_set_snap_to_objects(ddisp,
299 				   gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
300   ddisplay_add_update_all(ddisp);
301   ddisplay_flush(ddisp);
302 }
303 
304 static gint
origin_button_press(GtkWidget * widget,GdkEventButton * event,gpointer data)305 origin_button_press(GtkWidget *widget, GdkEventButton *event, gpointer data)
306 {
307   DDisplay *ddisp = (DDisplay *)data;
308 
309   display_set_active(ddisp);
310   ddisplay_popup_menu(ddisp, event);
311 
312   /* stop the signal emission so the button doesn't grab the
313    * pointer from us */
314   gtk_signal_emit_stop_by_name(GTK_OBJECT(widget), "button_press_event");
315 
316   return FALSE;
317 }
318 
319 void
view_zoom_set(float factor)320 view_zoom_set (float factor)
321 {
322   DDisplay *ddisp;
323   real scale;
324   Point middle;
325   Rectangle *visible;
326 
327   ddisp = ddisplay_active();
328   if (!ddisp) return;
329 
330   visible = &ddisp->visible;
331   middle.x = visible->left*0.5 + visible->right*0.5;
332   middle.y = visible->top*0.5 + visible->bottom*0.5;
333 
334   scale = ((real) factor)/1000.0 * DDISPLAY_NORMAL_ZOOM;
335 
336   ddisplay_zoom(ddisp, &middle, scale / ddisp->zoom_factor);
337 }
338 
339 static void
zoom_activate_callback(GtkWidget * item,gpointer user_data)340 zoom_activate_callback(GtkWidget *item, gpointer user_data)
341 {
342   DDisplay *ddisp = (DDisplay *)user_data;
343   const gchar *zoom_text =
344       gtk_entry_get_text(GTK_ENTRY(gtk_object_get_user_data(GTK_OBJECT(ddisp->zoom_status))));
345   float zoom_amount, magnify;
346   gchar *zoomamount = g_object_get_data(G_OBJECT(item), "zoomamount");
347   if (zoomamount != NULL) {
348     zoom_text = zoomamount;
349   }
350 
351   if (sscanf(zoom_text, "%f", &zoom_amount) == 1) {
352     Point middle;
353     Rectangle *visible;
354 
355     /* Set limits to avoid crashes, see bug #483384 */
356     if (zoom_amount < .1) {
357       zoom_amount = .1;
358     } else if (zoom_amount > 1e4) {
359       zoom_amount = 1e4;
360     }
361     zoomamount = g_strdup_printf("%f%%\n", zoom_amount);
362     gtk_entry_set_text(GTK_ENTRY(gtk_object_get_user_data(GTK_OBJECT(ddisp->zoom_status))), zoomamount);
363     g_free(zoomamount);
364     magnify = (zoom_amount*DDISPLAY_NORMAL_ZOOM/100.0)/ddisp->zoom_factor;
365     if (fabs(magnify - 1.0) > 0.000001) {
366       visible = &ddisp->visible;
367       middle.x = visible->left*0.5 + visible->right*0.5;
368       middle.y = visible->top*0.5 + visible->bottom*0.5;
369       ddisplay_zoom(ddisp, &middle, magnify);
370     }
371   }
372 }
373 
374 static void
zoom_add_zoom_amount(GtkWidget * menu,gchar * text,DDisplay * ddisp)375 zoom_add_zoom_amount(GtkWidget *menu, gchar *text, DDisplay *ddisp)
376 {
377   GtkWidget *menuitem = gtk_menu_item_new_with_label(text);
378   gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
379   g_signal_connect(GTK_OBJECT(menuitem),
380 		     "activate", G_CALLBACK(zoom_activate_callback),
381 		     ddisp);
382   g_object_set_data(G_OBJECT(menuitem), "zoomamount", text);
383 }
384 
385 static void
zoom_popup_menu(GtkWidget * button,GdkEventButton * event,gpointer user_data)386 zoom_popup_menu(GtkWidget *button, GdkEventButton *event, gpointer user_data) {
387   /* display_set_active(ddisp); */
388   /* ddisplay_popup_menu(ddisp, event); */
389 
390   GtkMenu *menu = GTK_MENU(user_data);
391 
392   gtk_menu_popup(menu, NULL, NULL, NULL, NULL,
393 		 event->button, event->time);
394   /* stop the signal emission so the button doesn't grab the
395    * pointer from us */
396   gtk_signal_emit_stop_by_name(GTK_OBJECT(button), "button_press_event");
397 }
398 
399 static GtkWidget*
create_zoom_widget(DDisplay * ddisp)400 create_zoom_widget(DDisplay *ddisp) {
401   GtkWidget *combo;
402   GtkWidget *entry;
403   GtkWidget *menu;
404   GtkWidget *button;
405   GtkWidget *arrow;
406 
407   combo = gtk_hbox_new(FALSE, 0);
408   entry = gtk_entry_new();
409   g_signal_connect (GTK_OBJECT (entry), "activate",
410 		    G_CALLBACK(zoom_activate_callback),
411 		      ddisp);
412   gtk_box_pack_start_defaults(GTK_BOX(combo), entry);
413   g_object_set_data (G_OBJECT(combo), "user_data", entry);
414   gtk_entry_set_width_chars(GTK_ENTRY(entry), 8);
415   gtk_widget_show(entry);
416 
417   button = gtk_button_new();
418   GTK_WIDGET_UNSET_FLAGS(button, GTK_CAN_FOCUS);
419   arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
420   gtk_container_add(GTK_CONTAINER(button), arrow);
421   gtk_box_pack_start_defaults(GTK_BOX(combo), button);
422   g_object_set_data (G_OBJECT(combo), "user_data", entry);
423   gtk_widget_show_all(button);
424 
425   menu = gtk_menu_new();
426   zoom_add_zoom_amount(menu, "800%", ddisp);
427   zoom_add_zoom_amount(menu, "400%", ddisp);
428   zoom_add_zoom_amount(menu, "200%", ddisp);
429   zoom_add_zoom_amount(menu, "100%", ddisp);
430   zoom_add_zoom_amount(menu, "50%", ddisp);
431   zoom_add_zoom_amount(menu, "25%", ddisp);
432   zoom_add_zoom_amount(menu, "12%", ddisp);
433 
434   gtk_widget_show_all(menu);
435 
436   g_signal_connect (GTK_OBJECT (button), "button_press_event",
437 		    G_CALLBACK(zoom_popup_menu),
438 		      menu);
439 
440   return combo;
441 }
442 
443 static gboolean
display_drop_callback(GtkWidget * widget,GdkDragContext * context,gint x,gint y,guint time)444 display_drop_callback(GtkWidget *widget, GdkDragContext *context,
445 		      gint x, gint y, guint time)
446 {
447   if (gtk_drag_get_source_widget(context) != NULL) {
448     /* we only accept drops from the same instance of the application,
449      * as the drag data is a pointer in our address space */
450     return TRUE;
451   }
452   gtk_drag_finish (context, FALSE, FALSE, time);
453   return FALSE;
454 }
455 
456 static void
display_data_received_callback(GtkWidget * widget,GdkDragContext * context,gint x,gint y,GtkSelectionData * data,guint info,guint time,DDisplay * ddisp)457 display_data_received_callback (GtkWidget *widget,
458 				GdkDragContext *context,
459 				gint x,
460 				gint y,
461 				GtkSelectionData *data,
462 				guint info,
463 				guint time,
464 				DDisplay *ddisp)
465 {
466   if (data->format == 8 && data->length == sizeof(ToolButtonData *) &&
467       gtk_drag_get_source_widget(context) != NULL) {
468     ToolButtonData *tooldata = *(ToolButtonData **)data->data;
469 
470     /* g_message("Tool drop %s at (%d, %d)", (gchar *)tooldata->extra_data, x, y);*/
471     ddisplay_drop_object(ddisp, x, y,
472 			 object_get_type((gchar *)tooldata->extra_data),
473 			 tooldata->user_data);
474 
475     gtk_drag_finish (context, TRUE, FALSE, time);
476   } else
477     dia_dnd_file_drag_data_received (widget, context, x, y, data, info, time, ddisp);
478 }
479 
480 /**
481  * @param button The notebook close button.
482  * @param user_data Container widget (e.g. VBox).
483  */
484 void
close_notebook_page_callback(GtkButton * button,gpointer user_data)485 close_notebook_page_callback (GtkButton *button,
486                               gpointer   user_data)
487 {
488   GtkBox      *page     = user_data;
489   DDisplay    *ddisp    = g_object_get_data (G_OBJECT (page), "DDisplay");
490 
491   /* When the page widget is destroyed it removes itself from the notebook */
492   ddisplay_close (ddisp);
493 }
494 
495 /**
496  * @param ddisp The diagram display object that a window is created for
497  * @param title
498  */
499 static void
use_integrated_ui_for_display_shell(DDisplay * ddisp,char * title)500 use_integrated_ui_for_display_shell(DDisplay *ddisp, char *title)
501 {
502   GtkWidget *table;
503   GtkWidget *navigation_button;
504   /* GtkWidget *status_hbox; */
505   /* GtkWidget *zoom_hbox, *zoom_label; */
506   GtkWidget *label;                /* Text label for the notebook page */
507   GtkWidget *tab_label_container;  /* Container to hold text label & close button */
508   int width, height;               /* Width/Heigth of the diagram */
509   GtkWidget *image;
510   GtkWidget *close_button;         /* Close button for the notebook page */
511   /* GtkWidget *widget; */
512   GtkRcStyle *rcstyle;
513   gint       notebook_page_index;
514 
515   ddisp->is_standalone_window = FALSE;
516 
517   ddisp->shell = GTK_WIDGET (ui.main_window);
518 
519   /* Statusbar */
520   ddisp->modified_status = GTK_WIDGET (ui.statusbar);
521 
522   tab_label_container = gtk_hbox_new(FALSE,3);
523 
524   label = gtk_label_new( title );
525   gtk_box_pack_start( GTK_BOX(tab_label_container), label, FALSE, FALSE, 0 );
526   gtk_widget_show (label);
527 
528   /* Create a new tab page */
529   ddisp->container = gtk_vbox_new(FALSE, 0);
530 
531   /* Create a new tab page */
532   ddisp->container = gtk_vbox_new(FALSE, 0);
533 
534   /* <from GEdit> */
535   /* don't allow focus on the close button */
536   close_button = gtk_button_new();
537   gtk_button_set_relief (GTK_BUTTON (close_button), GTK_RELIEF_NONE);
538   gtk_button_set_focus_on_click (GTK_BUTTON (close_button), FALSE);
539 
540   /* make it as small as possible */
541   rcstyle = gtk_rc_style_new ();
542   rcstyle->xthickness = rcstyle->ythickness = 0;
543   gtk_widget_modify_style (close_button, rcstyle);
544   gtk_rc_style_unref (rcstyle),
545 
546   image = gtk_image_new_from_stock (GTK_STOCK_CLOSE,
547                                     GTK_ICON_SIZE_MENU);
548 
549   gtk_container_add (GTK_CONTAINER(close_button), image);
550   gtk_signal_connect (GTK_OBJECT (close_button), "clicked",
551                       GTK_SIGNAL_FUNC (close_notebook_page_callback), ddisp->container);
552   /* </from GEdit> */
553 
554   gtk_box_pack_start( GTK_BOX(tab_label_container), close_button, FALSE, FALSE, 0 );
555   gtk_widget_show (close_button);
556   gtk_widget_show (image);
557 
558   /* Set events for new tab page */
559   gtk_widget_set_events (ddisp->container,
560                          GDK_POINTER_MOTION_MASK |
561                          GDK_POINTER_MOTION_HINT_MASK |
562                          GDK_FOCUS_CHANGE_MASK);
563 
564   g_signal_connect (GTK_OBJECT (ddisp->container), "focus_out_event",
565 		    G_CALLBACK (ddisplay_focus_out_event),
566 		      ddisp);
567   g_signal_connect (GTK_OBJECT (ddisp->container), "focus_in_event",
568 		    G_CALLBACK (ddisplay_focus_in_event),
569 		      ddisp);
570   g_signal_connect (GTK_OBJECT (ddisp->container), "realize",
571 		    G_CALLBACK (ddisplay_realize),
572                       ddisp);
573   g_signal_connect (GTK_OBJECT (ddisp->container), "unrealize",
574 		    G_CALLBACK (ddisplay_unrealize),
575 		      ddisp);
576 
577   notebook_page_index = gtk_notebook_append_page (GTK_NOTEBOOK(ui.diagram_notebook),
578                                                   ddisp->container,
579                                                   tab_label_container);
580 
581   g_object_set_data (G_OBJECT (ddisp->container), "DDisplay",  ddisp);
582   g_object_set_data (G_OBJECT (ddisp->container), "tab-label", label);
583   g_object_set_data (G_OBJECT (ddisp->container), "window",    ui.main_window);
584 
585   /*  the table containing all widgets  */
586   table = gtk_table_new (3, 3, FALSE);
587   gtk_table_set_col_spacing (GTK_TABLE (table), 0, 1);
588   gtk_table_set_col_spacing (GTK_TABLE (table), 1, 2);
589   gtk_table_set_row_spacing (GTK_TABLE (table), 0, 1);
590   gtk_table_set_row_spacing (GTK_TABLE (table), 1, 2);
591   gtk_container_set_border_width (GTK_CONTAINER (table), 2);
592 
593   gtk_box_pack_start( GTK_BOX(ddisp->container), table, TRUE, TRUE, 0 );
594 
595   /*  scrollbars, rulers, canvas, menu popup button  */
596   ddisp->origin = gtk_frame_new (NULL);
597   gtk_frame_set_shadow_type (GTK_FRAME (ddisp->origin), GTK_SHADOW_OUT);
598 
599   ddisp->hrule = gtk_hruler_new ();
600   g_signal_connect_swapped (GTK_OBJECT (ddisp->container), "motion_notify_event",
601                             G_CALLBACK(GTK_WIDGET_GET_CLASS (ddisp->hrule)->motion_notify_event),
602                             GTK_OBJECT (ddisp->hrule));
603 
604   ddisp->vrule = gtk_vruler_new ();
605   g_signal_connect_swapped (GTK_OBJECT (ddisp->container), "motion_notify_event",
606 			    G_CALLBACK(GTK_WIDGET_GET_CLASS (ddisp->vrule)->motion_notify_event),
607                             GTK_OBJECT (ddisp->vrule));
608 
609   /* Get the width/height of the Notebook child area */
610   /* TODO: Fix width/height hardcoded values */
611   width = 100;
612   height = 100;
613 
614   /*  The adjustment datums  */
615   ddisp->hsbdata = GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, width, 1, (width-1)/4, width-1));
616   ddisp->vsbdata = GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, height, 1, (height-1)/4, height-1));
617 
618   ddisp->hsb = gtk_hscrollbar_new (ddisp->hsbdata);
619   GTK_WIDGET_UNSET_FLAGS (ddisp->hsb, GTK_CAN_FOCUS);
620   ddisp->vsb = gtk_vscrollbar_new (ddisp->vsbdata);
621   GTK_WIDGET_UNSET_FLAGS (ddisp->vsb, GTK_CAN_FOCUS);
622 
623   /*  set up the scrollbar observers  */
624   g_signal_connect (GTK_OBJECT (ddisp->hsbdata), "value_changed",
625 		    G_CALLBACK(ddisplay_hsb_update),
626 		      ddisp);
627   g_signal_connect (GTK_OBJECT (ddisp->vsbdata), "value_changed",
628 		    G_CALLBACK(ddisplay_vsb_update),
629 		      ddisp);
630 
631   /*  Popup button between scrollbars for navigation window  */
632   navigation_button = navigation_popup_new(ddisp);
633   gtk_tooltips_set_tip(tool_tips, navigation_button,
634                        _("Pops up the Navigation window."), NULL);
635   gtk_widget_show(navigation_button);
636 
637   /*  Canvas  */
638   ddisp->canvas = dia_canvas_new();
639 
640   /* Dia's canvas does it's double buffering alone so switch off GTK's */
641   gtk_widget_set_double_buffered (ddisp->canvas, FALSE);
642 
643   gtk_widget_set_events (ddisp->canvas, CANVAS_EVENT_MASK);
644   GTK_WIDGET_SET_FLAGS (ddisp->canvas, GTK_CAN_FOCUS);
645   g_signal_connect (GTK_OBJECT (ddisp->canvas), "event",
646                     G_CALLBACK(ddisplay_canvas_events),
647                     ddisp);
648 
649   gtk_drag_dest_set(ddisp->canvas, GTK_DEST_DEFAULT_ALL,
650 		    display_target_table, display_n_targets, GDK_ACTION_COPY);
651   g_signal_connect (GTK_OBJECT (ddisp->canvas), "drag_drop",
652 		    G_CALLBACK(display_drop_callback), NULL);
653   g_signal_connect (GTK_OBJECT (ddisp->canvas), "drag_data_received",
654 		    G_CALLBACK(display_data_received_callback), ddisp);
655 
656   /*  place all the widgets  */
657   gtk_table_attach (GTK_TABLE (table), ddisp->origin, 0, 1, 0, 1,
658                     GTK_FILL, GTK_FILL, 0, 0);
659   gtk_table_attach (GTK_TABLE (table), ddisp->hrule, 1, 2, 0, 1,
660                     GTK_EXPAND | GTK_SHRINK | GTK_FILL, GTK_FILL, 0, 0);
661   gtk_table_attach (GTK_TABLE (table), ddisp->vrule, 0, 1, 1, 2,
662                     GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
663   gtk_table_attach (GTK_TABLE (table), ddisp->canvas, 1, 2, 1, 2,
664                     GTK_EXPAND | GTK_SHRINK | GTK_FILL,
665                     GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
666   gtk_table_attach (GTK_TABLE (table), ddisp->hsb, 0, 2, 2, 3,
667                     GTK_EXPAND | GTK_SHRINK | GTK_FILL, GTK_FILL, 0, 0);
668   gtk_table_attach (GTK_TABLE (table), ddisp->vsb, 2, 3, 0, 2,
669                     GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
670   gtk_table_attach (GTK_TABLE (table), navigation_button, 2, 3, 2, 3,
671                     GTK_FILL, GTK_FILL, 0, 0);
672 
673   ddisp->common_toolbar = ui.toolbar;
674 
675   /* Stand-alone window menubar */
676   ddisp->menu_bar = NULL;
677 
678   /* Stand-alone window Zoom status/menu */
679   ddisp->zoom_status = NULL;
680 
681   /* Stand-alone window Grid on/off button */
682   ddisp->grid_status = NULL;
683 
684   /* Stand-alone window Object Snapping button */
685   ddisp->mainpoint_status = NULL;
686 
687   gtk_widget_show (ddisp->container);
688   gtk_widget_show (table);
689   gtk_widget_show (ddisp->hsb);
690   gtk_widget_show (ddisp->vsb);
691   display_rulers_show (ddisp);
692   gtk_widget_show (ddisp->canvas);
693 
694   /* Show new page */
695   gtk_notebook_set_current_page (ui.diagram_notebook, notebook_page_index);
696 
697   integrated_ui_toolbar_grid_snap_synchronize_to_display (ddisp);
698 
699   integrated_ui_toolbar_object_snap_synchronize_to_display (ddisp);
700 
701   /* TODO: Figure out how to detect if anti-aliased renderer was set */
702   /** For the distributed display this is called when the ddisp->canvas is shown.
703    * The show causes a GDK_CONFIGURE event but this is not happening here.  If this
704    * is not set a seg-fault occurs when dia_renderer_get_width_pixels() is called
705    */
706   ddisplay_set_renderer(ddisp, ddisp->aa_renderer);
707 
708   /*  set the focus to the canvas area  */
709   gtk_widget_grab_focus (ddisp->canvas);
710 }
711 
712 /**
713  * @param ddisp The diagram display object that a window is created for
714  * @param width Diagram widgth
715  * @param height Diagram Height
716  * @param title Window title
717  * @param use_mbar Flag to indicate whether to add a menubar to the window
718  * @param top_level_window
719  */
720 void
create_display_shell(DDisplay * ddisp,int width,int height,char * title,int use_mbar,int top_level_window)721 create_display_shell(DDisplay *ddisp,
722 		     int width, int height,
723 		     char *title, int use_mbar, int top_level_window)
724 {
725   GtkWidget *table, *widget;
726   GtkWidget *navigation_button;
727   GtkWidget *status_hbox;
728   GtkWidget *root_vbox = NULL;
729   GtkWidget *zoom_hbox, *zoom_label;
730   int s_width, s_height;
731 
732   if (app_is_interactive() && is_integrated_ui())
733   {
734     use_integrated_ui_for_display_shell(ddisp, title);
735     return;
736   }
737 
738   ddisp->is_standalone_window = TRUE;
739   ddisp->container            = NULL;
740 
741 
742   if (!tool_tips) /* needed here if we dont create_toolbox() */
743     tool_tips = gtk_tooltips_new ();
744 
745   s_width = gdk_screen_width ();
746   s_height = gdk_screen_height ();
747   if (width > s_width)
748     width = s_width;
749   if (height > s_height)
750     height = s_height;
751 
752   /*  The adjustment datums  */
753   ddisp->hsbdata = GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, width, 1, (width-1)/4, width-1));
754   ddisp->vsbdata = GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, height, 1, (height-1)/4, height-1));
755 
756   /*  The toplevel shell */
757   if (top_level_window) {
758     ddisp->shell = gtk_window_new (GTK_WINDOW_TOPLEVEL);
759     gtk_window_set_title (GTK_WINDOW (ddisp->shell), title);
760     gtk_window_set_role (GTK_WINDOW (ddisp->shell), "diagram_window");
761     gtk_window_set_icon_name (GTK_WINDOW (ddisp->shell), "dia");
762     gtk_window_set_default_size(GTK_WINDOW (ddisp->shell), width, height);
763     /* set_icon_name needs registered theme icons, not always available: provide fallback */
764     if (!gtk_window_get_icon (GTK_WINDOW (ddisp->shell))) {
765       static GdkPixbuf *pixbuf = NULL;
766 
767       if (!pixbuf)
768         pixbuf = gdk_pixbuf_new_from_inline(-1, dia_diagram_icon, FALSE, NULL);
769       if (pixbuf)
770         gtk_window_set_icon (GTK_WINDOW (ddisp->shell), pixbuf);
771     }
772   } else {
773     ddisp->shell = gtk_event_box_new ();
774   }
775   g_object_set_data (G_OBJECT (ddisp->shell), "user_data", (gpointer) ddisp);
776 
777   gtk_widget_set_events (ddisp->shell,
778 			 GDK_POINTER_MOTION_MASK |
779 			 GDK_POINTER_MOTION_HINT_MASK |
780 			 GDK_FOCUS_CHANGE_MASK);
781                       /* GDK_ALL_EVENTS_MASK */
782 
783   g_signal_connect (GTK_OBJECT (ddisp->shell), "delete_event",
784 		    G_CALLBACK (ddisplay_delete),
785                       ddisp);
786   g_signal_connect (GTK_OBJECT (ddisp->shell), "destroy",
787 		    G_CALLBACK (ddisplay_destroy),
788                       ddisp);
789   g_signal_connect (GTK_OBJECT (ddisp->shell), "focus_out_event",
790 		    G_CALLBACK (ddisplay_focus_out_event),
791 		      ddisp);
792   g_signal_connect (GTK_OBJECT (ddisp->shell), "focus_in_event",
793 		    G_CALLBACK (ddisplay_focus_in_event),
794 		      ddisp);
795   g_signal_connect (GTK_OBJECT (ddisp->shell), "realize",
796 		    G_CALLBACK (ddisplay_realize),
797                       ddisp);
798   g_signal_connect (GTK_OBJECT (ddisp->shell), "unrealize",
799 		    G_CALLBACK (ddisplay_unrealize),
800 		      ddisp);
801 /*FIXME?:
802   g_signal_connect (GTK_OBJECT (ddisp->shell), "size_allocate",
803 		    G_CALLBACK (ddisplay_size_allocate),
804 		      ddisp);
805 */
806 
807   /*  the table containing all widgets  */
808   table = gtk_table_new (4, 3, FALSE);
809   gtk_table_set_col_spacing (GTK_TABLE (table), 0, 1);
810   gtk_table_set_col_spacing (GTK_TABLE (table), 1, 2);
811   gtk_table_set_row_spacing (GTK_TABLE (table), 0, 1);
812   gtk_table_set_row_spacing (GTK_TABLE (table), 1, 2);
813   gtk_container_set_border_width (GTK_CONTAINER (table), 2);
814   if (use_mbar)
815   {
816       root_vbox = gtk_vbox_new (FALSE, 1);
817       gtk_container_add (GTK_CONTAINER (ddisp->shell), root_vbox);
818       gtk_box_pack_end (GTK_BOX (root_vbox), table, TRUE, TRUE, 0);
819   }
820   else
821   {
822       gtk_container_add (GTK_CONTAINER (ddisp->shell), table);
823   }
824 
825 
826   /*  scrollbars, rulers, canvas, menu popup button  */
827   if (!use_mbar) {
828       ddisp->origin = gtk_button_new();
829       GTK_WIDGET_UNSET_FLAGS(ddisp->origin, GTK_CAN_FOCUS);
830       widget = gtk_arrow_new(GTK_ARROW_RIGHT, GTK_SHADOW_OUT);
831       gtk_container_add(GTK_CONTAINER(ddisp->origin), widget);
832       gtk_tooltips_set_tip(tool_tips, widget, _("Diagram menu."), NULL);
833       gtk_widget_show(widget);
834       g_signal_connect(GTK_OBJECT(ddisp->origin), "button_press_event",
835 		     G_CALLBACK(origin_button_press), ddisp);
836   }
837   else {
838       ddisp->origin = gtk_frame_new (NULL);
839       gtk_frame_set_shadow_type (GTK_FRAME (ddisp->origin), GTK_SHADOW_OUT);
840   }
841 
842 
843   ddisp->hrule = gtk_hruler_new ();
844   g_signal_connect_swapped (GTK_OBJECT (ddisp->shell), "motion_notify_event",
845                              G_CALLBACK(GTK_WIDGET_GET_CLASS (ddisp->hrule)->motion_notify_event),
846                              GTK_OBJECT (ddisp->hrule));
847 
848   ddisp->vrule = gtk_vruler_new ();
849   g_signal_connect_swapped (GTK_OBJECT (ddisp->shell), "motion_notify_event",
850 			    G_CALLBACK(GTK_WIDGET_GET_CLASS (ddisp->vrule)->motion_notify_event),
851                              GTK_OBJECT (ddisp->vrule));
852 
853   ddisp->hsb = gtk_hscrollbar_new (ddisp->hsbdata);
854   GTK_WIDGET_UNSET_FLAGS (ddisp->hsb, GTK_CAN_FOCUS);
855   ddisp->vsb = gtk_vscrollbar_new (ddisp->vsbdata);
856   GTK_WIDGET_UNSET_FLAGS (ddisp->vsb, GTK_CAN_FOCUS);
857 
858 
859   /*  set up the scrollbar observers  */
860   g_signal_connect (GTK_OBJECT (ddisp->hsbdata), "value_changed",
861 		    G_CALLBACK(ddisplay_hsb_update),
862 		      ddisp);
863   g_signal_connect (GTK_OBJECT (ddisp->vsbdata), "value_changed",
864 		    G_CALLBACK(ddisplay_vsb_update),
865 		      ddisp);
866 
867   /*  Popup button between scrollbars for navigation window  */
868   navigation_button = navigation_popup_new(ddisp);
869   gtk_tooltips_set_tip(tool_tips, navigation_button,
870                        _("Pops up the Navigation window."), NULL);
871   gtk_widget_show(navigation_button);
872 
873   /*  Canvas  */
874   /*  ddisp->canvas = gtk_drawing_area_new ();*/
875   ddisp->canvas = dia_canvas_new();
876   /* Dia's canvas does it' double buffering alone so switch off GTK's */
877   gtk_widget_set_double_buffered (ddisp->canvas, FALSE);
878 #if 0 /* the following call forces the minimum diagram window size. But it seems to be superfluous otherwise. */
879   dia_canvas_set_size(DIA_CANVAS (ddisp->canvas), width, height);
880 #endif
881   gtk_widget_set_events (ddisp->canvas, CANVAS_EVENT_MASK);
882   GTK_WIDGET_SET_FLAGS (ddisp->canvas, GTK_CAN_FOCUS);
883   g_signal_connect (GTK_OBJECT (ddisp->canvas), "event",
884 		    G_CALLBACK(ddisplay_canvas_events),
885 		      ddisp);
886 
887   gtk_drag_dest_set(ddisp->canvas, GTK_DEST_DEFAULT_ALL,
888 		    display_target_table, display_n_targets, GDK_ACTION_COPY);
889   g_signal_connect (GTK_OBJECT (ddisp->canvas), "drag_drop",
890 		    G_CALLBACK(display_drop_callback), NULL);
891   g_signal_connect (GTK_OBJECT (ddisp->canvas), "drag_data_received",
892 		    G_CALLBACK(display_data_received_callback), ddisp);
893 
894   g_object_set_data (G_OBJECT (ddisp->canvas), "user_data", (gpointer) ddisp);
895 
896   /*  pack all the widgets  */
897   gtk_table_attach (GTK_TABLE (table), ddisp->origin, 0, 1, 0, 1,
898                     GTK_FILL, GTK_FILL, 0, 0);
899   gtk_table_attach (GTK_TABLE (table), ddisp->hrule, 1, 2, 0, 1,
900                     GTK_EXPAND | GTK_SHRINK | GTK_FILL, GTK_FILL, 0, 0);
901   gtk_table_attach (GTK_TABLE (table), ddisp->vrule, 0, 1, 1, 2,
902                     GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
903   gtk_table_attach (GTK_TABLE (table), ddisp->canvas, 1, 2, 1, 2,
904                     GTK_EXPAND | GTK_SHRINK | GTK_FILL,
905                     GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
906   gtk_table_attach (GTK_TABLE (table), ddisp->hsb, 0, 2, 2, 3,
907                     GTK_EXPAND | GTK_SHRINK | GTK_FILL, GTK_FILL, 0, 0);
908   gtk_table_attach (GTK_TABLE (table), ddisp->vsb, 2, 3, 0, 2,
909                     GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
910   gtk_table_attach (GTK_TABLE (table), navigation_button, 2, 3, 2, 3,
911                     GTK_FILL, GTK_FILL, 0, 0);
912 
913   /* TODO rob use per window accel */
914   ddisp->accel_group = menus_get_display_accels ();
915   if (top_level_window)
916     gtk_window_add_accel_group(GTK_WINDOW(ddisp->shell), ddisp->accel_group);
917   if (use_mbar)
918   {
919     ddisp->menu_bar = menus_create_display_menubar (&ddisp->ui_manager, &ddisp->actions);
920     g_assert (ddisp->menu_bar);
921     gtk_box_pack_start (GTK_BOX (root_vbox), ddisp->menu_bar, FALSE, TRUE, 0);
922   }
923 
924   /* the statusbars */
925   status_hbox = gtk_hbox_new (FALSE, 2);
926 
927   /*
928     g_signal_connect(GTK_OBJECT(ddisp->origin), "button_press_event",
929     G_CALLBACK(origin_button_press), ddisp);
930   */
931 
932   /* Zoom status pseudo-optionmenu */
933   ddisp->zoom_status = create_zoom_widget(ddisp);
934   zoom_hbox = gtk_hbox_new(FALSE, 0);
935   zoom_label = gtk_label_new(_("Zoom"));
936   gtk_box_pack_start (GTK_BOX(zoom_hbox), zoom_label,
937 		      FALSE, FALSE, 0);
938   gtk_box_pack_start (GTK_BOX(zoom_hbox), ddisp->zoom_status,
939 		      FALSE, FALSE, 0);
940 
941   gtk_box_pack_start (GTK_BOX (status_hbox), zoom_hbox, FALSE, FALSE, 0);
942 
943   /* Grid on/off button */
944   ddisp->grid_status = dia_toggle_button_new_with_icons(dia_on_grid_icon,
945 							dia_off_grid_icon);
946 
947   g_signal_connect(G_OBJECT(ddisp->grid_status), "toggled",
948 		   G_CALLBACK (grid_toggle_snap), ddisp);
949   gtk_tooltips_set_tip(tool_tips, ddisp->grid_status,
950 		       _("Toggles snap-to-grid for this window."), NULL);
951   gtk_box_pack_start (GTK_BOX (status_hbox), ddisp->grid_status,
952 		      FALSE, FALSE, 0);
953 
954 
955   ddisp->mainpoint_status = dia_toggle_button_new_with_icons(dia_mainpoints_on_icon,
956 							dia_mainpoints_off_icon);
957 
958   g_signal_connect(G_OBJECT(ddisp->mainpoint_status), "toggled",
959 		   G_CALLBACK (interface_toggle_mainpoint_magnetism), ddisp);
960   gtk_tooltips_set_tip(tool_tips, ddisp->mainpoint_status,
961 		       _("Toggles object snapping for this window."), NULL);
962   gtk_box_pack_start (GTK_BOX (status_hbox), ddisp->mainpoint_status,
963 		      FALSE, FALSE, 0);
964 
965 
966   /* Statusbar */
967   ddisp->modified_status = gtk_statusbar_new ();
968 
969   gtk_box_pack_start (GTK_BOX (status_hbox), ddisp->modified_status,
970 		      TRUE, TRUE, 0);
971 
972   gtk_table_attach (GTK_TABLE (table), status_hbox, 0, 3, 3, 4,
973                     GTK_FILL, GTK_FILL, 0, 0);
974 
975   gtk_widget_show (ddisp->hsb);
976   gtk_widget_show (ddisp->vsb);
977   display_rulers_show (ddisp);
978   gtk_widget_show (ddisp->zoom_status);
979   gtk_widget_show (zoom_hbox);
980   gtk_widget_show (zoom_label);
981   gtk_widget_show (ddisp->grid_status);
982   gtk_widget_show (ddisp->mainpoint_status);
983   gtk_widget_show (ddisp->modified_status);
984   gtk_widget_show (status_hbox);
985   gtk_widget_show (table);
986   if (use_mbar)
987   {
988       gtk_widget_show (ddisp->menu_bar);
989       gtk_widget_show (root_vbox);
990   }
991   gtk_widget_show (ddisp->shell);
992 
993   /* before showing up, checking canvas's REAL size */
994   if (use_mbar && ddisp->hrule->allocation.width > width)
995   {
996     /* The menubar is not shrinkable, so the shell will have at least
997      * the menubar's width. If the diagram's requested width is smaller,
998      * the canvas will be enlarged to fit the place. In this case, we
999      * need to adjust the horizontal scrollbar according to the size
1000      * that will be allocated, which the same as the hrule got.
1001      */
1002 
1003     width = ddisp->hrule->allocation.width;
1004 
1005     ddisp->hsbdata->upper          = width;
1006     ddisp->hsbdata->page_increment = (width - 1) / 4;
1007     ddisp->hsbdata->page_size      = width - 1;
1008 
1009     gtk_adjustment_changed (GTK_ADJUSTMENT(ddisp->hsbdata));
1010   }
1011   gtk_widget_show (ddisp->canvas);
1012 
1013   /*  set the focus to the canvas area  */
1014   gtk_widget_grab_focus (ddisp->canvas);
1015 }
1016 
1017 void
tool_select_update(GtkWidget * w,gpointer data)1018 tool_select_update (GtkWidget *w,
1019 		     gpointer   data)
1020 {
1021   ToolButtonData *tooldata = (ToolButtonData *) data;
1022 
1023   if (tooldata == NULL) {
1024     g_warning("NULL tooldata in tool_select_update");
1025     return;
1026   }
1027 
1028   if (tooldata->type != -1) {
1029     gint x, y;
1030     GdkModifierType mask;
1031     /*  get the modifiers  */
1032     gdk_window_get_pointer (gtk_widget_get_parent_window(w), &x, &y, &mask);
1033     tool_select (tooldata->type, tooldata->extra_data, tooldata->user_data,
1034                  w, mask&1);
1035   }
1036 }
1037 
1038 static gint
tool_button_press(GtkWidget * w,GdkEventButton * event,gpointer data)1039 tool_button_press (GtkWidget      *w,
1040 		    GdkEventButton *event,
1041 		    gpointer        data)
1042 {
1043   ToolButtonData *tooldata = (ToolButtonData *) data;
1044 
1045   if ((event->type == GDK_2BUTTON_PRESS) &&
1046       (event->button == 1)) {
1047     tool_options_dialog_show (tooldata->type, tooldata->extra_data,
1048                               tooldata->user_data, w, event->state&1);
1049     return TRUE;
1050   }
1051 
1052   return FALSE;
1053 }
1054 
1055 static void
tool_drag_data_get(GtkWidget * widget,GdkDragContext * context,GtkSelectionData * selection_data,guint info,guint32 time,ToolButtonData * tooldata)1056 tool_drag_data_get (GtkWidget *widget, GdkDragContext *context,
1057 		    GtkSelectionData *selection_data, guint info,
1058 		    guint32 time, ToolButtonData *tooldata)
1059 {
1060   if (info == 0) {
1061     gtk_selection_data_set(selection_data, selection_data->target,
1062 			   8, (guchar *)&tooldata, sizeof(ToolButtonData *));
1063   }
1064 }
1065 
1066 static void
tool_setup_drag_source(GtkWidget * button,ToolButtonData * tooldata,GdkPixmap * pixmap,GdkBitmap * mask)1067 tool_setup_drag_source(GtkWidget *button, ToolButtonData *tooldata,
1068 		       GdkPixmap *pixmap, GdkBitmap *mask)
1069 {
1070   g_return_if_fail(tooldata->type == CREATE_OBJECT_TOOL);
1071 
1072   gtk_drag_source_set(button, GDK_BUTTON1_MASK,
1073 		      display_target_table, display_n_targets,
1074 		      GDK_ACTION_DEFAULT|GDK_ACTION_COPY);
1075   g_signal_connect(GTK_OBJECT(button), "drag_data_get",
1076 		   G_CALLBACK(tool_drag_data_get), tooldata);
1077   if (pixmap)
1078     gtk_drag_source_set_icon(button, gtk_widget_get_colormap(button),
1079 			     pixmap, mask);
1080 }
1081 
1082 /*
1083 void
1084 tool_select_callback(GtkWidget *widget, gpointer data) {
1085   ToolButtonData *tooldata = (ToolButtonData *)data;
1086 
1087   if (tooldata == NULL) {
1088     g_warning("NULL tooldata in tool_select_callback");
1089     return;
1090   }
1091 
1092   if (tooldata->type != -1) {
1093     tool_select (tooldata->type, tooldata->extra_data,
1094                  tooldata->user_data,widget);
1095   }
1096 }
1097 */
1098 
1099 /*
1100  * Don't look too deep into this function. It is doing bad things
1101  * with casts to conform to the historically interface. We know
1102  * the difference between char* and char** - most of the time ;)
1103  */
1104 static GtkWidget *
create_widget_from_xpm_or_gdkp(gchar ** icon_data,GtkWidget * button)1105 create_widget_from_xpm_or_gdkp(gchar **icon_data, GtkWidget *button)
1106 {
1107   GtkWidget *pixmapwidget;
1108 
1109   if (strncmp((char*)icon_data, "GdkP", 4) == 0) {
1110     GdkPixbuf *p;
1111     p = gdk_pixbuf_new_from_inline(-1, (char*)icon_data, TRUE, NULL);
1112     pixmapwidget = gtk_image_new_from_pixbuf(p);
1113   } else {
1114     GdkBitmap *mask = NULL;
1115     GtkStyle *style;
1116     char **pixmap_data;
1117     GdkPixmap *pixmap = NULL;
1118 
1119     pixmap_data = icon_data;
1120     style = gtk_widget_get_style(button);
1121     pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL,
1122 						   gtk_widget_get_colormap(button), &mask,
1123 						   &style->bg[GTK_STATE_NORMAL], pixmap_data);
1124     pixmapwidget = gtk_pixmap_new(pixmap, mask);
1125   }
1126   return pixmapwidget;
1127 }
1128 
1129 static void
create_tools(GtkWidget * parent)1130 create_tools(GtkWidget *parent)
1131 {
1132   GtkWidget *button;
1133   GtkWidget *pixmapwidget;
1134   GdkPixmap *pixmap = NULL;
1135   GdkBitmap *mask = NULL;
1136   /* GtkStyle *style; */
1137   char **pixmap_data;
1138   int i;
1139 
1140   for (i = 0; i < NUM_TOOLS; i++) {
1141     tool_widgets[i] = button = gtk_radio_button_new (tool_group);
1142     gtk_container_set_border_width (GTK_CONTAINER (button), 0);
1143     gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_HALF);
1144     tool_group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
1145     gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
1146 
1147     gtk_wrap_box_pack(GTK_WRAP_BOX(parent), button,
1148 		      TRUE, TRUE, FALSE, TRUE);
1149 
1150     if (tool_data[i].callback_data.type == MODIFY_TOOL) {
1151       modify_tool_button = GTK_WIDGET(button);
1152     }
1153 
1154     if (tool_data[i].icon_data==NULL) {
1155       DiaObjectType *type;
1156       type =
1157 	object_get_type((char *)tool_data[i].callback_data.extra_data);
1158       if (type == NULL)
1159 	pixmap_data = tool_data[0].icon_data;
1160       else
1161 	pixmap_data = type->pixmap;
1162       pixmapwidget = create_widget_from_xpm_or_gdkp(pixmap_data, button);
1163     } else {
1164       pixmapwidget = create_widget_from_xpm_or_gdkp(tool_data[i].icon_data, button);
1165     }
1166 
1167     /* GTKBUG:? padding changes */
1168     gtk_misc_set_padding(GTK_MISC(pixmapwidget), 2, 2);
1169 
1170     gtk_container_add (GTK_CONTAINER (button), pixmapwidget);
1171 
1172     g_signal_connect (GTK_OBJECT (button), "clicked",
1173 		      G_CALLBACK (tool_select_update),
1174 			&tool_data[i].callback_data);
1175 
1176     g_signal_connect (GTK_OBJECT (button), "button_press_event",
1177 		      G_CALLBACK (tool_button_press),
1178 			&tool_data[i].callback_data);
1179 
1180     if (tool_data[i].callback_data.type == CREATE_OBJECT_TOOL)
1181       tool_setup_drag_source(button, &tool_data[i].callback_data,
1182 			     pixmap, mask);
1183 
1184     if (pixmap) gdk_pixmap_unref(pixmap);
1185     if (mask) gdk_bitmap_unref(mask);
1186 
1187     tool_data[i].callback_data.widget = button;
1188 
1189     if (tool_data[i].tool_accelerator) {
1190 	guint key;
1191 	GdkModifierType mods;
1192 	gchar *alabel, *atip;
1193 
1194 	gtk_accelerator_parse (tool_data[i].tool_accelerator, &key, &mods);
1195 
1196 	alabel = gtk_accelerator_get_label(key, mods);
1197 	atip = g_strconcat(gettext(tool_data[i].tool_desc), " (", alabel, ")", NULL);
1198 	gtk_tooltips_set_tip (tool_tips, button, atip, NULL);
1199 	g_free (atip);
1200 	g_free (alabel);
1201 
1202     } else {
1203 	gtk_tooltips_set_tip (tool_tips, button,
1204 				gettext(tool_data[i].tool_desc), NULL);
1205     }
1206 
1207     gtk_widget_show (pixmapwidget);
1208     gtk_widget_show (button);
1209   }
1210 }
1211 
1212 static GtkWidget *sheet_option_menu;
1213 static GtkWidget *sheet_wbox;
1214 
1215 gchar *interface_current_sheet_name;
1216 
1217 static Sheet *
get_sheet_by_name(const gchar * name)1218 get_sheet_by_name(const gchar *name)
1219 {
1220   GSList *tmp;
1221   for (tmp = get_sheets_list(); tmp != NULL; tmp = tmp->next) {
1222     Sheet *sheet = tmp->data;
1223     /* There is something fishy with comparing both forms: the english and the localized one.
1224      * But we should be on the safe side here, especially when bug #328570 gets tackled.
1225      */
1226     if (0 == g_strcasecmp(name, sheet->name) || 0 == g_strcasecmp(name, gettext(sheet->name)))
1227       return sheet;
1228   }
1229   return NULL;
1230 }
1231 
1232 static void
fill_sheet_wbox(Sheet * sheet)1233 fill_sheet_wbox(Sheet *sheet)
1234 {
1235   int rows;
1236   GtkStyle *style;
1237   GSList *tmp;
1238   GtkWidget *first_button = NULL;
1239 
1240   gtk_container_foreach(GTK_CONTAINER(sheet_wbox),
1241 			(GtkCallback)gtk_widget_destroy, NULL);
1242   tool_group = gtk_radio_button_group(GTK_RADIO_BUTTON(tool_widgets[0]));
1243 
1244   /* Remember sheet 'name' for 'Sheets and Objects' dialog */
1245   interface_current_sheet_name = sheet->name;
1246 
1247   /* set the aspect ratio on the wbox */
1248   rows = ceil(g_slist_length(sheet->objects) / (double)COLUMNS);
1249   if (rows<1) rows = 1;
1250   gtk_wrap_box_set_aspect_ratio(GTK_WRAP_BOX(sheet_wbox),
1251 				COLUMNS * 1.0 / rows);
1252   style = gtk_widget_get_style(sheet_wbox);
1253   for (tmp = sheet->objects; tmp != NULL; tmp = tmp->next) {
1254     SheetObject *sheet_obj = tmp->data;
1255     GdkPixmap *pixmap = NULL;
1256     GdkBitmap *mask = NULL;
1257     GtkWidget *pixmapwidget;
1258     GtkWidget *button;
1259     ToolButtonData *data;
1260 
1261     if (sheet_obj->pixmap != NULL) {
1262       pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL,
1263 			gtk_widget_get_colormap(sheet_wbox), &mask,
1264 			&style->bg[GTK_STATE_NORMAL], sheet_obj->pixmap);
1265     } else if (sheet_obj->pixmap_file != NULL) {
1266       GdkPixbuf *pixbuf;
1267       GError* gerror = NULL;
1268 
1269       pixbuf = gdk_pixbuf_new_from_file(sheet_obj->pixmap_file, &gerror);
1270       if (pixbuf != NULL) {
1271           int width = gdk_pixbuf_get_width (pixbuf);
1272           int height = gdk_pixbuf_get_height (pixbuf);
1273           if (width > 22) {
1274 	    GdkPixbuf *cropped;
1275 	    g_warning ("Shape icon '%s' size wrong, cropped.", sheet_obj->pixmap_file);
1276 	    cropped = gdk_pixbuf_new_subpixbuf (pixbuf,
1277 	                                       (width - 22) / 2, height > 22 ? (height - 22) / 2 : 0,
1278 					       22, height > 22 ? 22 : height);
1279 	    g_object_unref (pixbuf);
1280 	    pixbuf = cropped;
1281 	  }
1282           gdk_pixbuf_render_pixmap_and_mask_for_colormap(pixbuf, gtk_widget_get_colormap(sheet_wbox), &pixmap, &mask, 1.0);
1283           gdk_pixbuf_unref(pixbuf);
1284       } else {
1285           pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL,
1286 			gtk_widget_get_colormap(sheet_wbox), &mask,
1287 			&style->bg[GTK_STATE_NORMAL], missing);
1288 
1289           message_warning("failed to load icon for file\n %s\n cause=%s",
1290                           sheet_obj->pixmap_file,gerror?gerror->message:"[NULL]");
1291       }
1292     } else {
1293       DiaObjectType *type;
1294       type = object_get_type(sheet_obj->object_type);
1295       pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL,
1296 			gtk_widget_get_colormap(sheet_wbox), &mask,
1297 			&style->bg[GTK_STATE_NORMAL], type->pixmap);
1298     }
1299     if (pixmap) {
1300       pixmapwidget = gtk_pixmap_new(pixmap, mask);
1301       gdk_pixmap_unref(pixmap);
1302       if (mask) gdk_bitmap_unref(mask);
1303     } else {
1304       pixmapwidget = gtk_type_new(gtk_pixmap_get_type());
1305     }
1306 
1307     button = gtk_radio_button_new (tool_group);
1308     gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
1309     gtk_container_set_border_width (GTK_CONTAINER (button), 0);
1310     tool_group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
1311 
1312     gtk_container_add (GTK_CONTAINER (button), pixmapwidget);
1313     gtk_widget_show(pixmapwidget);
1314 
1315     gtk_wrap_box_pack_wrapped(GTK_WRAP_BOX(sheet_wbox), button,
1316 		      FALSE, TRUE, FALSE, TRUE, sheet_obj->line_break);
1317     gtk_widget_show(button);
1318 
1319     data = g_new(ToolButtonData, 1);
1320     data->type = CREATE_OBJECT_TOOL;
1321     data->extra_data = sheet_obj->object_type;
1322     data->user_data = sheet_obj->user_data;
1323     gtk_object_set_data_full(GTK_OBJECT(button), "Dia::ToolButtonData",
1324 			     data, (GdkDestroyNotify)g_free);
1325     if (first_button == NULL) first_button = button;
1326 
1327     g_signal_connect (GTK_OBJECT (button), "clicked",
1328 		      G_CALLBACK (tool_select_update), data);
1329     g_signal_connect (GTK_OBJECT (button), "button_press_event",
1330 		      G_CALLBACK (tool_button_press), data);
1331 
1332     tool_setup_drag_source(button, data, pixmap, mask);
1333 
1334     gtk_tooltips_set_tip (tool_tips, button,
1335 			  gettext(sheet_obj->description), NULL);
1336   }
1337   /* If the selection is in the old sheet, steal it */
1338   if (active_tool != NULL &&
1339       active_tool->type == CREATE_OBJECT_TOOL &&
1340       first_button != NULL)
1341     gtk_signal_emit_by_name(GTK_OBJECT(first_button), "toggled",
1342 			    GTK_BUTTON(first_button), NULL);
1343 }
1344 
1345 static void
sheet_option_menu_changed(DiaDynamicMenu * menu,gpointer user_data)1346 sheet_option_menu_changed(DiaDynamicMenu *menu, gpointer user_data)
1347 {
1348   char *string = dia_dynamic_menu_get_entry(menu);
1349   Sheet *sheet = get_sheet_by_name(string);
1350   if (sheet == NULL) {
1351     message_warning(_("No sheet named %s"), string);
1352   } else {
1353     persistence_set_string("last-sheet-selected", string);
1354     fill_sheet_wbox(sheet);
1355   }
1356   g_free(string);
1357 }
1358 
1359 static int
cmp_names(const void * a,const void * b)1360 cmp_names (const void *a, const void *b)
1361 {
1362   return g_utf8_collate(gettext( (gchar *)a ), gettext( (gchar *)b ));
1363 }
1364 
1365 static GList *
get_sheet_names()1366 get_sheet_names()
1367 {
1368   GSList *tmp;
1369   GList *names = NULL;
1370   for (tmp = get_sheets_list(); tmp != NULL; tmp = tmp->next) {
1371     Sheet *sheet = tmp->data;
1372     names = g_list_append(names, sheet->name);
1373   }
1374   /* Already sorted in lib/ but here we sort by the localized (display-)name */
1375   return g_list_sort (names, cmp_names);
1376 }
1377 
1378 static void
create_sheet_dropdown_menu(GtkWidget * parent)1379 create_sheet_dropdown_menu(GtkWidget *parent)
1380 {
1381   GList *sheet_names = get_sheet_names();
1382 
1383   if (sheet_option_menu != NULL) {
1384     gtk_container_remove(GTK_CONTAINER(parent), sheet_option_menu);
1385     sheet_option_menu = NULL;
1386   }
1387 
1388   sheet_option_menu =
1389     dia_dynamic_menu_new_stringlistbased(_("Other sheets"), sheet_names,
1390 					 NULL, "sheets");
1391   g_signal_connect(DIA_DYNAMIC_MENU(sheet_option_menu), "value-changed",
1392 		   G_CALLBACK(sheet_option_menu_changed), sheet_option_menu);
1393   dia_dynamic_menu_add_default_entry(DIA_DYNAMIC_MENU(sheet_option_menu),
1394 				     "Assorted");
1395   dia_dynamic_menu_add_default_entry(DIA_DYNAMIC_MENU(sheet_option_menu),
1396 				     "Flowchart");
1397   dia_dynamic_menu_add_default_entry(DIA_DYNAMIC_MENU(sheet_option_menu),
1398 				     "UML");
1399   /*    gtk_widget_set_size_request(sheet_option_menu, 20, -1);*/
1400   gtk_wrap_box_pack_wrapped(GTK_WRAP_BOX(parent), sheet_option_menu,
1401 			    TRUE, TRUE, FALSE, FALSE, TRUE);
1402   /* 15 was a magic number that goes beyond the standard objects and the divider. */
1403   gtk_wrap_box_reorder_child(GTK_WRAP_BOX(parent),
1404 			     sheet_option_menu, NUM_TOOLS+1);
1405   gtk_widget_show(sheet_option_menu);
1406 }
1407 
1408 void
fill_sheet_menu(void)1409 fill_sheet_menu(void)
1410 {
1411   gchar *selection = dia_dynamic_menu_get_entry(DIA_DYNAMIC_MENU(sheet_option_menu));
1412   create_sheet_dropdown_menu(gtk_widget_get_parent(sheet_option_menu));
1413   dia_dynamic_menu_select_entry(DIA_DYNAMIC_MENU(sheet_option_menu), selection);
1414   g_free(selection);
1415 }
1416 
1417 void
create_sheets(GtkWidget * parent)1418 create_sheets(GtkWidget *parent)
1419 {
1420   GtkWidget *separator;
1421   GtkWidget *label;
1422   GtkWidget *swin;
1423   gchar *sheetname;
1424   Sheet *sheet;
1425 
1426   separator = gtk_hseparator_new ();
1427   /* add a bit of padding around the separator */
1428   label = gtk_vbox_new(FALSE, 0);
1429   gtk_box_pack_start(GTK_BOX(label), separator, TRUE, TRUE, 3);
1430   gtk_widget_show(label);
1431 
1432   gtk_wrap_box_pack_wrapped (GTK_WRAP_BOX(parent), label, TRUE,TRUE, FALSE,FALSE, TRUE);
1433   gtk_widget_show(separator);
1434 
1435   create_sheet_dropdown_menu(parent);
1436 
1437   swin = gtk_scrolled_window_new(NULL, NULL);
1438   gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swin),
1439 				 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1440   gtk_wrap_box_pack_wrapped(GTK_WRAP_BOX(parent), swin, TRUE, TRUE, TRUE, TRUE, TRUE);
1441   gtk_widget_show(swin);
1442 
1443   sheet_wbox = gtk_hwrap_box_new(FALSE);
1444   gtk_wrap_box_set_justify(GTK_WRAP_BOX(sheet_wbox), GTK_JUSTIFY_TOP);
1445   gtk_wrap_box_set_line_justify(GTK_WRAP_BOX(sheet_wbox), GTK_JUSTIFY_LEFT);
1446   gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(swin), sheet_wbox);
1447   gtk_widget_show(sheet_wbox);
1448 
1449   sheetname = persistence_register_string("last-sheet-selected", _("Flowchart"));
1450   sheet = get_sheet_by_name(sheetname);
1451   if (sheet == NULL) {
1452     /* Couldn't find it */
1453   } else {
1454     fill_sheet_wbox(sheet);
1455     dia_dynamic_menu_select_entry(DIA_DYNAMIC_MENU(sheet_option_menu),
1456 				  sheetname);
1457   }
1458   g_free(sheetname);
1459 }
1460 
1461 static void
create_color_area(GtkWidget * parent)1462 create_color_area (GtkWidget *parent)
1463 {
1464   GtkWidget *frame;
1465   GtkWidget *alignment;
1466   GtkWidget *col_area;
1467   GtkWidget *line_area;
1468   GdkPixmap *default_pixmap;
1469   GdkBitmap *default_mask;
1470   GdkPixmap *swap_pixmap;
1471   GdkBitmap *swap_mask;
1472   GtkStyle *style;
1473   GtkWidget *hbox;
1474 
1475   gtk_widget_ensure_style(parent);
1476   style = gtk_widget_get_style(parent);
1477 
1478   default_pixmap =
1479     gdk_pixmap_colormap_create_from_xpm_d(NULL,
1480 		gtk_widget_get_colormap(parent), &default_mask,
1481 		&style->bg[GTK_STATE_NORMAL], default_xpm);
1482   swap_pixmap =
1483     gdk_pixmap_colormap_create_from_xpm_d(NULL,
1484 		gtk_widget_get_colormap(parent), &swap_mask,
1485 		&style->bg[GTK_STATE_NORMAL], swap_xpm);
1486 
1487   frame = gtk_frame_new (NULL);
1488   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
1489   gtk_wrap_box_pack_wrapped(GTK_WRAP_BOX(parent), frame, TRUE, TRUE, FALSE, FALSE, TRUE);
1490   gtk_widget_realize (frame);
1491 
1492   hbox = gtk_hbox_new (FALSE, 1);
1493   gtk_container_set_border_width (GTK_CONTAINER (hbox), 0);
1494   gtk_container_add (GTK_CONTAINER (frame), hbox);
1495 
1496   /* Color area: */
1497   alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
1498   gtk_container_set_border_width (GTK_CONTAINER (alignment), 3);
1499 
1500   col_area = color_area_create (54, 42,
1501                                 default_pixmap, default_mask,
1502                                 swap_pixmap, swap_mask);
1503   gtk_container_add (GTK_CONTAINER (alignment), col_area);
1504 
1505 
1506   gtk_box_pack_start (GTK_BOX (hbox), alignment, TRUE, TRUE, 0);
1507 
1508   gtk_tooltips_set_tip (tool_tips, col_area,
1509 			_("Foreground & background colors for new objects.  "
1510 			  "The small black and white squares reset colors.  "
1511 			  "The small arrows swap colors.  Double click to "
1512 			  "change colors."),
1513                         NULL);
1514 
1515   gtk_widget_show (alignment);
1516 
1517   /* Linewidth area: */
1518   alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
1519   gtk_container_set_border_width (GTK_CONTAINER (alignment), 3);
1520 
1521   line_area = linewidth_area_create ();
1522   gtk_container_add (GTK_CONTAINER (alignment), line_area);
1523   gtk_box_pack_start (GTK_BOX (hbox), alignment, TRUE, TRUE, 0);
1524   gtk_tooltips_set_tip(tool_tips, line_area, _("Line widths.  Click on a line to set the default line width for new objects.  Double-click to set the line width more precisely."), NULL);
1525   gtk_widget_show (alignment);
1526 
1527   gtk_widget_show (col_area);
1528   gtk_widget_show (line_area);
1529   gtk_widget_show (hbox);
1530   gtk_widget_show (frame);
1531 }
1532 
1533 static void
change_start_arrow_style(Arrow arrow,gpointer user_data)1534 change_start_arrow_style(Arrow arrow, gpointer user_data)
1535 {
1536   attributes_set_default_start_arrow(arrow);
1537 }
1538 static void
change_end_arrow_style(Arrow arrow,gpointer user_data)1539 change_end_arrow_style(Arrow arrow, gpointer user_data)
1540 {
1541   attributes_set_default_end_arrow(arrow);
1542 }
1543 static void
change_line_style(LineStyle lstyle,real dash_length,gpointer user_data)1544 change_line_style(LineStyle lstyle, real dash_length, gpointer user_data)
1545 {
1546   attributes_set_default_line_style(lstyle, dash_length);
1547 }
1548 
1549 static void
create_lineprops_area(GtkWidget * parent)1550 create_lineprops_area(GtkWidget *parent)
1551 {
1552   GtkWidget *chooser;
1553   Arrow arrow;
1554   real dash_length;
1555   LineStyle style;
1556   gchar *arrow_name;
1557 
1558   chooser = dia_arrow_chooser_new(TRUE, change_start_arrow_style, NULL, tool_tips);
1559   gtk_wrap_box_pack_wrapped(GTK_WRAP_BOX(parent), chooser, FALSE, TRUE, FALSE, TRUE, TRUE);
1560   arrow.width = persistence_register_real("start-arrow-width", DEFAULT_ARROW_WIDTH);
1561   arrow.length = persistence_register_real("start-arrow-length", DEFAULT_ARROW_LENGTH);
1562   arrow_name = persistence_register_string("start-arrow-type", "None");
1563   arrow.type = arrow_type_from_name(arrow_name);
1564   g_free(arrow_name);
1565   dia_arrow_chooser_set_arrow(DIA_ARROW_CHOOSER(chooser), &arrow);
1566   attributes_set_default_start_arrow(arrow);
1567   gtk_tooltips_set_tip(tool_tips, chooser, _("Arrow style at the beginning of new lines.  Click to pick an arrow, or set arrow parameters with Details..."), NULL);
1568   gtk_widget_show(chooser);
1569 
1570   chooser = dia_line_chooser_new(change_line_style, NULL);
1571   gtk_wrap_box_pack(GTK_WRAP_BOX(parent), chooser, TRUE, TRUE, FALSE, TRUE);
1572   gtk_tooltips_set_tip(tool_tips, chooser, _("Line style for new lines.  Click to pick a line style, or set line style parameters with Details..."), NULL);
1573   style = persistence_register_integer("line-style", LINESTYLE_SOLID);
1574   dash_length = persistence_register_real("dash-length", DEFAULT_LINESTYLE_DASHLEN);
1575   dia_line_chooser_set_line_style(DIA_LINE_CHOOSER(chooser), style, dash_length);
1576   gtk_widget_show(chooser);
1577 
1578   chooser = dia_arrow_chooser_new(FALSE, change_end_arrow_style, NULL, tool_tips);
1579   arrow.width = persistence_register_real("end-arrow-width", DEFAULT_ARROW_WIDTH);
1580   arrow.length = persistence_register_real("end-arrow-length", DEFAULT_ARROW_LENGTH);
1581   arrow_name = persistence_register_string("end-arrow-type", "Filled Concave");
1582   arrow.type = arrow_type_from_name(arrow_name);
1583   g_free(arrow_name);
1584   dia_arrow_chooser_set_arrow(DIA_ARROW_CHOOSER(chooser), &arrow);
1585   attributes_set_default_end_arrow(arrow);
1586 
1587   gtk_wrap_box_pack(GTK_WRAP_BOX(parent), chooser, FALSE, TRUE, FALSE, TRUE);
1588   gtk_tooltips_set_tip(tool_tips, chooser, _("Arrow style at the end of new lines.  Click to pick an arrow, or set arrow parameters with Details..."), NULL);
1589   gtk_widget_show(chooser);
1590 }
1591 
1592 static void
toolbox_destroy(GtkWidget * widget,gpointer data)1593 toolbox_destroy (GtkWidget *widget, gpointer data)
1594 {
1595   app_exit();
1596 }
1597 
1598 static gboolean
toolbox_delete(GtkWidget * widget,GdkEvent * event,gpointer data)1599 toolbox_delete (GtkWidget *widget, GdkEvent *event, gpointer data)
1600 {
1601   if (!app_is_embedded()) {
1602     gulong handlerid;
1603     /** Stop toolbox_destroy from being called */
1604     handlerid = g_signal_handler_find(widget, G_SIGNAL_MATCH_FUNC,
1605 				      0, 0, NULL, toolbox_destroy, NULL);
1606     if (handlerid != 0)
1607       g_signal_handler_disconnect (GTK_OBJECT (widget), handlerid);
1608 
1609     /** If the app didn't exit, don't close the window */
1610     return (!app_exit());
1611   }
1612   return FALSE;
1613 }
1614 
1615 static void
app_set_icon(GtkWindow * window)1616 app_set_icon (GtkWindow *window)
1617 {
1618   gtk_window_set_icon_name (window, "dia");
1619   if (!gtk_window_get_icon (window)) {
1620     GdkPixbuf *pixbuf = gdk_pixbuf_new_from_inline (-1, dia_app_icon, FALSE, NULL);
1621     if (pixbuf) {
1622       gtk_window_set_icon (window, pixbuf);
1623       g_object_unref (pixbuf);
1624     }
1625   }
1626 }
1627 
1628 /**
1629  * Create integrated user interface
1630  */
1631 void
create_integrated_ui(void)1632 create_integrated_ui (void)
1633 {
1634   GtkWidget *window;
1635   GtkWidget *main_vbox;
1636   GtkWidget *hbox;
1637   GtkWidget *wrapbox;
1638   GtkWidget *menubar;
1639   GtkWidget *toolbar;
1640   GtkWidget *notebook;
1641   GtkWidget *statusbar;
1642   GtkAccelGroup *accel_group;
1643   GdkPixbuf *pixbuf;
1644 
1645   GtkWidget *layer_view;
1646 
1647 #ifdef GNOME
1648   window = gnome_app_new ("Dia", _("Diagram Editor"));
1649 #else
1650   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1651   gtk_widget_ref (window);
1652   gtk_window_set_title (GTK_WINDOW (window), "Dia v" VERSION);
1653 #endif
1654 
1655   /* hint to window manager on X so the wm can put the window in the same
1656      as it was when the application shut down                             */
1657   gtk_window_set_role (GTK_WINDOW (window), DIA_MAIN_WINDOW);
1658 
1659   gtk_window_set_default_size (GTK_WINDOW (window), 146, 349);
1660 
1661   app_set_icon (GTK_WINDOW (window));
1662 
1663   g_signal_connect (GTK_OBJECT (window), "delete_event",
1664 		    G_CALLBACK (toolbox_delete),
1665 		      window);
1666 
1667   g_signal_connect (GTK_OBJECT (window), "destroy",
1668 		    G_CALLBACK (toolbox_destroy),
1669 		      window);
1670 
1671   main_vbox = gtk_vbox_new (FALSE, 1);
1672   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 1);
1673 #ifdef GNOME
1674   gnome_app_set_contents (GNOME_APP(window), main_vbox);
1675 #else
1676   gtk_container_add (GTK_CONTAINER (window), main_vbox);
1677 #endif
1678   gtk_widget_show (main_vbox);
1679 
1680   /* Applicatioon Statusbar */
1681   statusbar = gtk_statusbar_new ();
1682   gtk_box_pack_end (GTK_BOX (main_vbox), statusbar, FALSE, TRUE, 0);
1683   /* HBox for everything below the menubar and toolbars */
1684   hbox = gtk_hbox_new(FALSE, 0);
1685   gtk_box_pack_end (GTK_BOX (main_vbox), hbox, TRUE, TRUE, 0);
1686   gtk_widget_show (hbox);
1687 
1688   /* Layer View  */
1689   layer_view = create_layer_view_widget ();
1690   gtk_box_pack_end (GTK_BOX (hbox), layer_view, FALSE, FALSE, 0);
1691 
1692   /* Diagram Notebook */
1693   notebook = gtk_notebook_new ();
1694   gtk_box_pack_end (GTK_BOX (hbox), notebook, TRUE, TRUE, 0);
1695   gtk_notebook_set_scrollable (GTK_NOTEBOOK (notebook), TRUE);
1696   gtk_widget_show (notebook);
1697 
1698   /*  tooltips  */
1699   tool_tips = gtk_tooltips_new ();
1700 
1701   wrapbox = gtk_hwrap_box_new(FALSE);
1702   gtk_wrap_box_set_aspect_ratio(GTK_WRAP_BOX(wrapbox), 144.0 / 318.0);
1703   gtk_wrap_box_set_justify(GTK_WRAP_BOX(wrapbox), GTK_JUSTIFY_TOP);
1704   gtk_wrap_box_set_line_justify(GTK_WRAP_BOX(wrapbox), GTK_JUSTIFY_LEFT);
1705 
1706   /* pack the rest of the stuff */
1707   gtk_box_pack_start (GTK_BOX (hbox), wrapbox, FALSE, TRUE, 0);
1708   gtk_container_set_border_width (GTK_CONTAINER (wrapbox), 0);
1709   gtk_widget_show (wrapbox);
1710 
1711   create_tools (wrapbox);
1712   create_sheets (wrapbox);
1713   create_color_area (wrapbox);
1714   create_lineprops_area (wrapbox);
1715 
1716   /* Setup toolbox area as file drop destination */
1717   gtk_drag_dest_set (wrapbox,
1718 		     GTK_DEST_DEFAULT_ALL,
1719 		     toolbox_target_table, toolbox_n_targets,
1720 		     GDK_ACTION_COPY);
1721   g_signal_connect (GTK_OBJECT (wrapbox), "drag_data_received",
1722 		    G_CALLBACK (dia_dnd_file_drag_data_received),
1723                     NULL); /* userdata == NULL here intentionally */
1724 
1725   /* menus -- initialised afterwards, because initing the display menus
1726    * uses the tool buttons*/
1727   menus_get_integrated_ui_menubar(&menubar, &toolbar, &accel_group);
1728   gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
1729 #ifdef GNOME
1730   gnome_app_set_menus (GNOME_APP (window), GTK_MENU_BAR (menubar));
1731 #else
1732   gtk_box_pack_start (GTK_BOX (main_vbox), menubar, FALSE, TRUE, 0);
1733   gtk_widget_show (menubar);
1734 #endif
1735 
1736   /* Toolbar */
1737   /* TODO: maybe delete set_style(toolbar,ICONS) */
1738   gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_ICONS);
1739   gtk_box_pack_start (GTK_BOX (main_vbox), toolbar, FALSE, TRUE, 0);
1740   gtk_widget_show (toolbar);
1741 
1742   persistence_register_window(GTK_WINDOW(window));
1743 
1744   ui.main_window      = GTK_WINDOW    (window);
1745   ui.toolbar          = GTK_TOOLBAR   (toolbar);
1746   ui.diagram_notebook = GTK_NOTEBOOK  (notebook);
1747   ui.statusbar        = GTK_STATUSBAR (statusbar);
1748   ui.layer_view       =                layer_view;
1749 
1750   /* NOTE: These functions use ui.xxx assignments above and so must come after
1751    *       the user interface components are set.                              */
1752   integrated_ui_main_toolbar_show ();
1753   integrated_ui_main_statusbar_show ();
1754 
1755   /* For access outside here: */
1756   g_object_set_data (G_OBJECT (ui.main_window), DIA_MAIN_NOTEBOOK, notebook);
1757 
1758   /* TODO: Figure out what to do about toolbox_shell for integrated UI */
1759   toolbox_shell = window;
1760 }
1761 
1762 /**
1763  * Create toolbox component for distributed user interface
1764  */
1765 void
create_toolbox()1766 create_toolbox ()
1767 {
1768   GtkWidget *window;
1769   GtkWidget *main_vbox;
1770   GtkWidget *wrapbox;
1771   GtkWidget *menubar;
1772   GtkAccelGroup *accel_group;
1773 
1774 #ifdef GNOME
1775   window = gnome_app_new ("Dia", _("Diagram Editor"));
1776 #else
1777   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1778   gtk_widget_ref (window);
1779   gtk_window_set_title (GTK_WINDOW (window), "Dia v" VERSION);
1780 #endif
1781   gtk_window_set_role (GTK_WINDOW (window), "toolbox_window");
1782   gtk_window_set_default_size(GTK_WINDOW(window), 146, 349);
1783 
1784   app_set_icon (GTK_WINDOW (window));
1785   if (!gtk_window_get_icon (GTK_WINDOW (window))) {
1786     GdkPixbuf *pixbuf = gdk_pixbuf_new_from_inline (-1, dia_app_icon, FALSE, NULL);
1787     if (pixbuf) {
1788       gtk_window_set_icon (GTK_WINDOW (window), pixbuf);
1789       g_object_unref (pixbuf);
1790     }
1791   }
1792 
1793   g_signal_connect (GTK_OBJECT (window), "delete_event",
1794 		    G_CALLBACK (toolbox_delete),
1795 		      window);
1796 
1797   g_signal_connect (GTK_OBJECT (window), "destroy",
1798 		    G_CALLBACK (toolbox_destroy),
1799 		      window);
1800 
1801   main_vbox = gtk_vbox_new (FALSE, 1);
1802   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 1);
1803 #ifdef GNOME
1804   gnome_app_set_contents(GNOME_APP(window), main_vbox);
1805 #else
1806   gtk_container_add (GTK_CONTAINER (window), main_vbox);
1807 #endif
1808   gtk_widget_show (main_vbox);
1809 
1810   /*  tooltips  */
1811   tool_tips = gtk_tooltips_new ();
1812 
1813   /*  gtk_tooltips_set_colors (tool_tips,
1814 			   &colors[11],
1815 			   &main_vbox->style->fg[GTK_STATE_NORMAL]);*/
1816 
1817   wrapbox = gtk_hwrap_box_new(FALSE);
1818   gtk_wrap_box_set_aspect_ratio(GTK_WRAP_BOX(wrapbox), 144.0 / 318.0);
1819   gtk_wrap_box_set_justify(GTK_WRAP_BOX(wrapbox), GTK_JUSTIFY_TOP);
1820   gtk_wrap_box_set_line_justify(GTK_WRAP_BOX(wrapbox), GTK_JUSTIFY_LEFT);
1821 
1822 
1823   /* pack the rest of the stuff */
1824   gtk_box_pack_end (GTK_BOX (main_vbox), wrapbox, TRUE, TRUE, 0);
1825   gtk_container_set_border_width (GTK_CONTAINER (wrapbox), 0);
1826   gtk_widget_show (wrapbox);
1827 
1828   create_tools (wrapbox);
1829   create_sheets (wrapbox);
1830   create_color_area (wrapbox);
1831   create_lineprops_area (wrapbox);
1832 
1833   /* Setup toolbox area as file drop destination */
1834   gtk_drag_dest_set (wrapbox,
1835 		     GTK_DEST_DEFAULT_ALL,
1836 		     toolbox_target_table, toolbox_n_targets,
1837 		     GDK_ACTION_COPY);
1838   g_signal_connect (GTK_OBJECT (wrapbox), "drag_data_received",
1839 		    G_CALLBACK (dia_dnd_file_drag_data_received),
1840                     NULL); /* userdata == NULL here intentionally */
1841 
1842   /* menus -- initialised afterwards, because initing the display menus
1843    * uses the tool buttons*/
1844   menus_get_toolbox_menubar(&menubar, &accel_group);
1845   gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
1846 #ifdef GNOME
1847   gnome_app_set_menus(GNOME_APP(window), GTK_MENU_BAR(menubar));
1848 #else
1849   gtk_box_pack_start (GTK_BOX (main_vbox), menubar, FALSE, TRUE, 0);
1850   gtk_widget_show (menubar);
1851 #endif
1852   persistence_register_window(GTK_WINDOW(window));
1853 
1854   toolbox_shell = window;
1855 }
1856 
1857 void
toolbox_show(void)1858 toolbox_show(void)
1859 {
1860   gtk_widget_show(toolbox_shell);
1861 }
1862 
1863 void
toolbox_hide(void)1864 toolbox_hide(void)
1865 {
1866   gtk_widget_hide(toolbox_shell);
1867 }
1868 
1869 void
create_tree_window(void)1870 create_tree_window(void)
1871 {
1872   GtkAction *action = menus_get_action ("FileTree");
1873   create_diagram_tree_window(&prefs.dia_tree, GTK_TOGGLE_ACTION(action));
1874 }
1875 
1876 GtkWidget *
interface_get_toolbox_shell(void)1877 interface_get_toolbox_shell(void)
1878 {
1879   if (is_integrated_ui ())
1880     return GTK_WIDGET(ui.main_window);
1881 
1882   return toolbox_shell;
1883 }
1884 
1885 /* Indicate if the integrated UI toolbar is showing.
1886  * @return TRUE if showing, FALSE if not showing or doesn't exist
1887  */
integrated_ui_main_toolbar_is_showing(void)1888 gboolean integrated_ui_main_toolbar_is_showing (void)
1889 {
1890   if (ui.toolbar)
1891   {
1892     return GTK_WIDGET_VISIBLE (ui.toolbar)? TRUE : FALSE;
1893   }
1894   return FALSE;
1895 }
1896 
1897 /* show() integrated UI main toolbar and set pulldown menu action. */
integrated_ui_main_toolbar_show(void)1898 void integrated_ui_main_toolbar_show (void)
1899 {
1900   if (ui.toolbar)
1901   {
1902     GtkAction *action = NULL;
1903     gtk_widget_show (GTK_WIDGET (ui.toolbar));
1904     action = menus_get_action (VIEW_MAIN_TOOLBAR_ACTION);
1905     if (action)
1906       gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1907   }
1908 }
1909 
1910 /* hide() integrated UI main toolbar and reset pulldown menu action. */
integrated_ui_main_toolbar_hide(void)1911 void integrated_ui_main_toolbar_hide (void)
1912 {
1913   if (ui.toolbar)
1914   {
1915     GtkAction *action = NULL;
1916     gtk_widget_hide (GTK_WIDGET (ui.toolbar));
1917     action = menus_get_action (VIEW_MAIN_TOOLBAR_ACTION);
1918     if (action)
1919       gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), FALSE);
1920   }
1921 }
1922 
1923 /* Indicate if the integrated UI Layer View is showing.
1924  * @return TRUE if showing, FALSE if not showing or doesn't exist
1925  */
integrated_ui_layer_view_is_showing(void)1926 gboolean integrated_ui_layer_view_is_showing (void)
1927 {
1928   if (ui.layer_view)
1929   {
1930     return GTK_WIDGET_VISIBLE (ui.layer_view)? TRUE : FALSE;
1931   }
1932   return FALSE;
1933 }
1934 
integrated_ui_layer_view_show(void)1935 void integrated_ui_layer_view_show (void)
1936 {
1937   if (ui.layer_view)
1938   {
1939     GtkAction *action = NULL;
1940     gtk_widget_show (ui.layer_view);
1941     action = menus_get_action (VIEW_LAYERS_ACTION);
1942     if (action)
1943     {
1944       gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1945     }
1946   }
1947 }
1948 
integrated_ui_layer_view_hide(void)1949 void integrated_ui_layer_view_hide (void)
1950 {
1951   if (ui.layer_view)
1952   {
1953     GtkAction *action = NULL;
1954     gtk_widget_hide (ui.layer_view);
1955     action = menus_get_action (VIEW_LAYERS_ACTION);
1956     if (action)
1957     {
1958       gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), FALSE);
1959     }
1960   }
1961 }
1962 
1963 /* Indicate if the integrated UI statusbar is showing.
1964  * @return TRUE if showing, FALSE if not showing or doesn't exist
1965  */
integrated_ui_main_statusbar_is_showing(void)1966 gboolean integrated_ui_main_statusbar_is_showing (void)
1967 {
1968   if (ui.statusbar)
1969   {
1970     return GTK_WIDGET_VISIBLE (ui.statusbar)? TRUE : FALSE;
1971   }
1972   return FALSE;
1973 }
1974 
1975 /* show() integrated UI main statusbar and set pulldown menu action. */
integrated_ui_main_statusbar_show(void)1976 void integrated_ui_main_statusbar_show (void)
1977 {
1978   if (ui.statusbar)
1979   {
1980     GtkAction *action = NULL;
1981     gtk_widget_show (GTK_WIDGET (ui.statusbar));
1982     action = menus_get_action (VIEW_MAIN_STATUSBAR_ACTION);
1983     if (action)
1984       gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1985   }
1986 }
1987 
1988 /* hide() integrated UI main statusbar and reset pulldown menu action. */
integrated_ui_main_statusbar_hide(void)1989 void integrated_ui_main_statusbar_hide (void)
1990 {
1991   if (ui.statusbar)
1992   {
1993     GtkAction *action = NULL;
1994     gtk_widget_hide (GTK_WIDGET (ui.statusbar));
1995     action = menus_get_action (VIEW_MAIN_STATUSBAR_ACTION);
1996     if (action)
1997       gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), FALSE);
1998   }
1999 }
2000 
2001 
2002 
2003