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