Two patches: Improved print dialog, standard tool shortcuts.
[dia.git] / app / interface.c
blobec415bfe8b95fb8da2f2daee70e016bb42c03642
1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
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.
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.
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.
19 #include <config.h>
21 #include <gtk/gtk.h>
23 #include <stdio.h>
24 #include <string.h>
26 #include "diagram.h"
27 #include "object.h"
28 #include "layer_dialog.h"
29 #include "interface.h"
30 #include "display.h"
31 #include "pixmaps.h"
32 #include "preferences.h"
33 #include "commands.h"
34 #include "dia_dirs.h"
35 #include "diagram_tree_window.h"
36 #include "intl.h"
37 #include "navigation.h"
38 #include "persistence.h"
39 #include "diaarrowchooser.h"
40 #include "dialinechooser.h"
41 #include "widgets.h"
42 #include "message.h"
44 #include <gdk-pixbuf/gdk-pixbuf.h>
45 #include "dia-app-icons.h"
46 #include "diacanvas.h"
48 #include "pixmaps/missing.xpm"
50 static const GtkTargetEntry create_object_targets[] = {
51 { "application/x-dia-object", 0, 0 },
54 ToolButton tool_data[] =
56 { (char **) dia_modify_tool_icon,
57 N_("Modify object(s)"),
58 NULL,
59 "ToolsModify",
60 { MODIFY_TOOL, NULL, NULL}
62 { (char **) dia_zoom_tool_icon,
63 N_("Magnify"),
64 "<alt>M",
65 "ToolsMagnify",
66 { MAGNIFY_TOOL, NULL, NULL}
68 { (char **) dia_scroll_tool_icon,
69 N_("Scroll around the diagram"),
70 "<alt>S",
71 "ToolsScroll",
72 { SCROLL_TOOL, NULL, NULL}
74 { NULL,
75 N_("Text"),
76 "<alt>T",
77 "ToolsText",
78 { CREATE_OBJECT_TOOL, "Standard - Text", NULL }
80 { NULL,
81 N_("Box"),
82 "<alt>R",
83 "ToolsBox",
84 { CREATE_OBJECT_TOOL, "Standard - Box", NULL }
86 { NULL,
87 N_("Ellipse"),
88 "<alt>E",
89 "ToolsEllipse",
90 { CREATE_OBJECT_TOOL, "Standard - Ellipse", NULL }
92 { NULL,
93 N_("Polygon"),
94 "<alt>P",
95 "ToolsPolygon",
96 { CREATE_OBJECT_TOOL, "Standard - Polygon", NULL }
98 { NULL,
99 N_("Beziergon"),
100 "<alt>B",
101 "ToolsBeziergon",
102 { CREATE_OBJECT_TOOL, "Standard - Beziergon", NULL }
104 { NULL,
105 N_("Line"),
106 "<alt>L",
107 "ToolsLine",
108 { CREATE_OBJECT_TOOL, "Standard - Line", NULL }
110 { NULL,
111 N_("Arc"),
112 "<alt>A",
113 "ToolsArc",
114 { CREATE_OBJECT_TOOL, "Standard - Arc", NULL }
116 { NULL,
117 N_("Zigzagline"),
118 "<alt>Z",
119 "ToolsZigzagline",
120 { CREATE_OBJECT_TOOL, "Standard - ZigZagLine", NULL }
122 { NULL,
123 N_("Polyline"),
124 NULL,
125 "ToolsPolyline",
126 { CREATE_OBJECT_TOOL, "Standard - PolyLine", NULL }
128 { NULL,
129 N_("Bezierline"),
130 "<alt>C",
131 "ToolsBezierline",
132 { CREATE_OBJECT_TOOL, "Standard - BezierLine", NULL }
134 { NULL,
135 N_("Image"),
136 "<alt>I",
137 "ToolsImage",
138 { CREATE_OBJECT_TOOL, "Standard - Image", NULL }
142 #define NUM_TOOLS (sizeof (tool_data) / sizeof (ToolButton))
143 const int num_tools = NUM_TOOLS;
145 #define COLUMNS 4
146 #define ROWS 3
148 static GtkWidget *toolbox_shell = NULL;
149 static GtkWidget *tool_widgets[NUM_TOOLS];
150 /*static*/ GtkTooltips *tool_tips;
151 static GSList *tool_group = NULL;
153 GtkWidget *modify_tool_button;
155 static void
156 grid_toggle_snap(GtkWidget *widget, gpointer data)
158 DDisplay *ddisp = (DDisplay *)data;
159 ddisplay_set_snap_to_grid(ddisp,
160 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
163 static void
164 interface_toggle_mainpoint_magnetism(GtkWidget *widget, gpointer data)
166 DDisplay *ddisp = (DDisplay *)data;
167 ddisplay_set_snap_to_objects(ddisp,
168 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
169 ddisplay_add_update_all(ddisp);
170 ddisplay_flush(ddisp);
173 static gint
174 origin_button_press(GtkWidget *widget, GdkEventButton *event, gpointer data)
176 DDisplay *ddisp = (DDisplay *)data;
178 display_set_active(ddisp);
179 ddisplay_popup_menu(ddisp, event);
181 /* stop the signal emission so the button doesn't grab the
182 * pointer from us */
183 gtk_signal_emit_stop_by_name(GTK_OBJECT(widget), "button_press_event");
185 return FALSE;
188 static void
189 zoom_activate_callback(GtkWidget *item, gpointer user_data) {
190 DDisplay *ddisp = (DDisplay *)user_data;
191 const gchar *zoom_text =
192 gtk_entry_get_text(GTK_ENTRY(gtk_object_get_user_data(GTK_OBJECT(ddisp->zoom_status))));
193 float zoom_amount, magnify;
194 gchar *zoomamount = g_object_get_data(G_OBJECT(item), "zoomamount");
195 if (zoomamount != NULL) {
196 zoom_text = zoomamount;
199 if (sscanf(zoom_text, "%f", &zoom_amount) == 1) {
200 Point middle;
201 Rectangle *visible;
203 magnify = (zoom_amount*DDISPLAY_NORMAL_ZOOM/100.0)/ddisp->zoom_factor;
204 if (fabs(magnify - 1.0) > 0.000001) {
205 visible = &ddisp->visible;
206 middle.x = visible->left*0.5 + visible->right*0.5;
207 middle.y = visible->top*0.5 + visible->bottom*0.5;
208 ddisplay_zoom(ddisp, &middle, magnify);
213 static void
214 zoom_add_zoom_amount(GtkWidget *menu, gchar *text, DDisplay *ddisp) {
215 GtkWidget *menuitem = gtk_menu_item_new_with_label(text);
216 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
217 g_signal_connect(GTK_OBJECT(menuitem),
218 "activate", G_CALLBACK(zoom_activate_callback),
219 ddisp);
220 g_object_set_data(G_OBJECT(menuitem), "zoomamount", text);
223 static void
224 zoom_popup_menu(GtkWidget *button, GdkEventButton *event, gpointer user_data) {
225 /* display_set_active(ddisp); */
226 /* ddisplay_popup_menu(ddisp, event); */
228 GtkMenu *menu = GTK_MENU(user_data);
230 gtk_menu_popup(menu, NULL, NULL, NULL, NULL,
231 event->button, event->time);
232 /* stop the signal emission so the button doesn't grab the
233 * pointer from us */
234 gtk_signal_emit_stop_by_name(GTK_OBJECT(button), "button_press_event");
237 static GtkWidget*
238 create_zoom_widget(DDisplay *ddisp) {
239 GtkWidget *combo;
240 GtkWidget *entry;
241 GtkWidget *menu;
242 GtkWidget *button;
243 GtkWidget *arrow;
245 combo = gtk_hbox_new(FALSE, 0);
246 entry = gtk_entry_new();
247 g_signal_connect (GTK_OBJECT (entry), "activate",
248 G_CALLBACK(zoom_activate_callback),
249 ddisp);
250 gtk_box_pack_start_defaults(GTK_BOX(combo), entry);
251 gtk_object_set_user_data(GTK_OBJECT(combo), entry);
252 gtk_entry_set_width_chars(GTK_ENTRY(entry), 8);
253 gtk_widget_show(entry);
255 button = gtk_button_new();
256 GTK_WIDGET_UNSET_FLAGS(button, GTK_CAN_FOCUS);
257 arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
258 gtk_container_add(GTK_CONTAINER(button), arrow);
259 gtk_box_pack_start_defaults(GTK_BOX(combo), button);
260 gtk_object_set_user_data(GTK_OBJECT(combo), entry);
261 gtk_widget_show_all(button);
263 menu = gtk_menu_new();
264 zoom_add_zoom_amount(menu, "400%", ddisp);
265 zoom_add_zoom_amount(menu, "283%", ddisp);
266 zoom_add_zoom_amount(menu, "200%", ddisp);
267 zoom_add_zoom_amount(menu, "141%", ddisp);
268 zoom_add_zoom_amount(menu, "100%", ddisp);
269 zoom_add_zoom_amount(menu, "85%", ddisp);
270 zoom_add_zoom_amount(menu, "70.7%", ddisp);
271 zoom_add_zoom_amount(menu, "50%", ddisp);
272 zoom_add_zoom_amount(menu, "35.4%", ddisp);
273 zoom_add_zoom_amount(menu, "25%", ddisp);
275 gtk_widget_show_all(menu);
277 g_signal_connect (GTK_OBJECT (button), "button_press_event",
278 G_CALLBACK(zoom_popup_menu),
279 menu);
281 return combo;
284 static gboolean
285 display_drop_callback(GtkWidget *widget, GdkDragContext *context,
286 gint x, gint y, guint time)
288 if (gtk_drag_get_source_widget(context) != NULL) {
289 /* we only accept drops from the same instance of the application,
290 * as the drag data is a pointer in our address space */
291 return TRUE;
293 gtk_drag_finish (context, FALSE, FALSE, time);
294 return FALSE;
297 static void
298 display_data_received_callback (GtkWidget *widget, GdkDragContext *context,
299 gint x, gint y, GtkSelectionData *data,
300 guint info, guint time, DDisplay *ddisp)
302 if (data->format == 8 && data->length == sizeof(ToolButtonData *) &&
303 gtk_drag_get_source_widget(context) != NULL) {
304 ToolButtonData *tooldata = *(ToolButtonData **)data->data;
306 /* g_message("Tool drop %s at (%d, %d)", (gchar *)tooldata->extra_data, x, y);*/
307 ddisplay_drop_object(ddisp, x, y,
308 object_get_type((gchar *)tooldata->extra_data),
309 tooldata->user_data);
311 gtk_drag_finish (context, TRUE, FALSE, time);
312 } else
313 gtk_drag_finish (context, FALSE, FALSE, time);
316 void
317 create_display_shell(DDisplay *ddisp,
318 int width, int height,
319 char *title, int use_mbar, int top_level_window)
321 GtkWidget *table, *widget;
322 GtkWidget *navigation_button;
323 GtkWidget *status_hbox;
324 GtkWidget *root_vbox = NULL;
325 GtkWidget *zoom_hbox, *zoom_label;
326 int s_width, s_height;
328 if (!tool_tips) /* needed here if we dont create_toolbox() */
329 tool_tips = gtk_tooltips_new ();
331 s_width = gdk_screen_width ();
332 s_height = gdk_screen_height ();
333 if (width > s_width)
334 width = s_width;
335 if (height > s_height)
336 height = s_height;
338 /* The adjustment datums */
339 ddisp->hsbdata = GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, width, 1, (width-1)/4, width-1));
340 ddisp->vsbdata = GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, height, 1, (height-1)/4, height-1));
342 /* The toplevel shell */
343 if (top_level_window) {
344 ddisp->shell = gtk_window_new (GTK_WINDOW_TOPLEVEL);
345 gtk_window_set_title (GTK_WINDOW (ddisp->shell), title);
346 gtk_window_set_role (GTK_WINDOW (ddisp->shell), "diagram_window");
348 static GdkPixbuf *pixbuf = NULL;
350 if (!pixbuf)
351 pixbuf = gdk_pixbuf_new_from_inline(-1, dia_diagram_icon, FALSE, NULL);
352 if (pixbuf)
353 gtk_window_set_icon (GTK_WINDOW (ddisp->shell), pixbuf);
355 gtk_window_set_default_size(GTK_WINDOW (ddisp->shell), width, height);
356 } else {
357 ddisp->shell = gtk_event_box_new ();
359 gtk_object_set_user_data (GTK_OBJECT (ddisp->shell), (gpointer) ddisp);
361 gtk_widget_set_events (ddisp->shell,
362 GDK_POINTER_MOTION_MASK |
363 GDK_POINTER_MOTION_HINT_MASK |
364 GDK_FOCUS_CHANGE_MASK);
365 /* GDK_ALL_EVENTS_MASK */
367 g_signal_connect (GTK_OBJECT (ddisp->shell), "delete_event",
368 G_CALLBACK (ddisplay_delete),
369 ddisp);
370 g_signal_connect (GTK_OBJECT (ddisp->shell), "destroy",
371 G_CALLBACK (ddisplay_destroy),
372 ddisp);
373 g_signal_connect (GTK_OBJECT (ddisp->shell), "focus_out_event",
374 G_CALLBACK (ddisplay_focus_out_event),
375 ddisp);
376 g_signal_connect (GTK_OBJECT (ddisp->shell), "focus_in_event",
377 G_CALLBACK (ddisplay_focus_in_event),
378 ddisp);
379 g_signal_connect (GTK_OBJECT (ddisp->shell), "realize",
380 G_CALLBACK (ddisplay_realize),
381 ddisp);
382 g_signal_connect (GTK_OBJECT (ddisp->shell), "unrealize",
383 G_CALLBACK (ddisplay_unrealize),
384 ddisp);
385 /*FIXME?:
386 g_signal_connect (GTK_OBJECT (ddisp->shell), "size_allocate",
387 G_CALLBACK (ddisplay_size_allocate),
388 ddisp);
391 /* the table containing all widgets */
392 table = gtk_table_new (4, 3, FALSE);
393 gtk_table_set_col_spacing (GTK_TABLE (table), 0, 1);
394 gtk_table_set_col_spacing (GTK_TABLE (table), 1, 2);
395 gtk_table_set_row_spacing (GTK_TABLE (table), 0, 1);
396 gtk_table_set_row_spacing (GTK_TABLE (table), 1, 2);
397 gtk_container_set_border_width (GTK_CONTAINER (table), 2);
398 if (use_mbar)
400 root_vbox = gtk_vbox_new (FALSE, 1);
401 gtk_container_add (GTK_CONTAINER (ddisp->shell), root_vbox);
402 gtk_box_pack_end (GTK_BOX (root_vbox), table, TRUE, TRUE, 0);
404 else
406 gtk_container_add (GTK_CONTAINER (ddisp->shell), table);
410 /* scrollbars, rulers, canvas, menu popup button */
411 if (!use_mbar) {
412 ddisp->origin = gtk_button_new();
413 GTK_WIDGET_UNSET_FLAGS(ddisp->origin, GTK_CAN_FOCUS);
414 widget = gtk_arrow_new(GTK_ARROW_RIGHT, GTK_SHADOW_OUT);
415 gtk_container_add(GTK_CONTAINER(ddisp->origin), widget);
416 gtk_tooltips_set_tip(tool_tips, widget, _("Diagram menu."), NULL);
417 gtk_widget_show(widget);
418 g_signal_connect(GTK_OBJECT(ddisp->origin), "button_press_event",
419 G_CALLBACK(origin_button_press), ddisp);
421 else {
422 ddisp->origin = gtk_frame_new (NULL);
423 gtk_frame_set_shadow_type (GTK_FRAME (ddisp->origin), GTK_SHADOW_OUT);
427 ddisp->hrule = gtk_hruler_new ();
428 g_signal_connect_swapped (GTK_OBJECT (ddisp->shell), "motion_notify_event",
429 G_CALLBACK(GTK_WIDGET_GET_CLASS (ddisp->hrule)->motion_notify_event),
430 GTK_OBJECT (ddisp->hrule));
432 ddisp->vrule = gtk_vruler_new ();
433 g_signal_connect_swapped (GTK_OBJECT (ddisp->shell), "motion_notify_event",
434 G_CALLBACK(GTK_WIDGET_GET_CLASS (ddisp->vrule)->motion_notify_event),
435 GTK_OBJECT (ddisp->vrule));
437 ddisp->hsb = gtk_hscrollbar_new (ddisp->hsbdata);
438 GTK_WIDGET_UNSET_FLAGS (ddisp->hsb, GTK_CAN_FOCUS);
439 ddisp->vsb = gtk_vscrollbar_new (ddisp->vsbdata);
440 GTK_WIDGET_UNSET_FLAGS (ddisp->vsb, GTK_CAN_FOCUS);
443 /* set up the scrollbar observers */
444 g_signal_connect (GTK_OBJECT (ddisp->hsbdata), "value_changed",
445 G_CALLBACK(ddisplay_hsb_update),
446 ddisp);
447 g_signal_connect (GTK_OBJECT (ddisp->vsbdata), "value_changed",
448 G_CALLBACK(ddisplay_vsb_update),
449 ddisp);
451 /* Popup button between scrollbars for navigation window */
452 navigation_button = navigation_popup_new(ddisp);
453 gtk_tooltips_set_tip(tool_tips, navigation_button,
454 _("Pops up the Navigation window."), NULL);
455 gtk_widget_show(navigation_button);
457 /* Canvas */
458 /* ddisp->canvas = gtk_drawing_area_new ();*/
459 ddisp->canvas = dia_canvas_new();
460 /* Dia's canvas does it' double buffering alone so switch off GTK's */
461 gtk_widget_set_double_buffered (ddisp->canvas, FALSE);
462 #if 0 /* the following call forces the minimum diagram window size. But it seems to be superfluous otherwise. */
463 dia_canvas_set_size(DIA_CANVAS (ddisp->canvas), width, height);
464 #endif
465 gtk_widget_set_events (ddisp->canvas, CANVAS_EVENT_MASK);
466 GTK_WIDGET_SET_FLAGS (ddisp->canvas, GTK_CAN_FOCUS);
467 g_signal_connect (GTK_OBJECT (ddisp->canvas), "event",
468 G_CALLBACK(ddisplay_canvas_events),
469 ddisp);
471 gtk_drag_dest_set(ddisp->canvas, GTK_DEST_DEFAULT_ALL,
472 create_object_targets, 1, GDK_ACTION_COPY);
473 g_signal_connect (GTK_OBJECT (ddisp->canvas), "drag_drop",
474 G_CALLBACK(display_drop_callback), NULL);
475 g_signal_connect (GTK_OBJECT (ddisp->canvas), "drag_data_received",
476 G_CALLBACK(display_data_received_callback), ddisp);
478 gtk_object_set_user_data (GTK_OBJECT (ddisp->canvas), (gpointer) ddisp);
480 /* pack all the widgets */
481 gtk_table_attach (GTK_TABLE (table), ddisp->origin, 0, 1, 0, 1,
482 GTK_FILL, GTK_FILL, 0, 0);
483 gtk_table_attach (GTK_TABLE (table), ddisp->hrule, 1, 2, 0, 1,
484 GTK_EXPAND | GTK_SHRINK | GTK_FILL, GTK_FILL, 0, 0);
485 gtk_table_attach (GTK_TABLE (table), ddisp->vrule, 0, 1, 1, 2,
486 GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
487 gtk_table_attach (GTK_TABLE (table), ddisp->canvas, 1, 2, 1, 2,
488 GTK_EXPAND | GTK_SHRINK | GTK_FILL,
489 GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
490 gtk_table_attach (GTK_TABLE (table), ddisp->hsb, 0, 2, 2, 3,
491 GTK_EXPAND | GTK_SHRINK | GTK_FILL, GTK_FILL, 0, 0);
492 gtk_table_attach (GTK_TABLE (table), ddisp->vsb, 2, 3, 0, 2,
493 GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
494 gtk_table_attach (GTK_TABLE (table), navigation_button, 2, 3, 2, 3,
495 GTK_FILL, GTK_FILL, 0, 0);
497 /* TODO rob use per window accel */
498 ddisp->accel_group = menus_get_display_accels ();
499 if (top_level_window)
500 gtk_window_add_accel_group(GTK_WINDOW(ddisp->shell), ddisp->accel_group);
501 if (use_mbar)
503 ddisp->menu_bar = menus_create_display_menubar (&ddisp->ui_manager, &ddisp->actions);
504 g_assert (ddisp->menu_bar);
505 gtk_box_pack_start (GTK_BOX (root_vbox), ddisp->menu_bar, FALSE, TRUE, 0);
506 menus_initialize_updatable_items (&ddisp->updatable_menu_items, ddisp->actions);
509 /* the statusbars */
510 status_hbox = gtk_hbox_new (FALSE, 2);
513 g_signal_connect(GTK_OBJECT(ddisp->origin), "button_press_event",
514 G_CALLBACK(origin_button_press), ddisp);
517 /* Zoom status pseudo-optionmenu */
518 ddisp->zoom_status = create_zoom_widget(ddisp);
519 zoom_hbox = gtk_hbox_new(FALSE, 0);
520 zoom_label = gtk_label_new(_("Zoom"));
521 gtk_box_pack_start (GTK_BOX(zoom_hbox), zoom_label,
522 FALSE, FALSE, 0);
523 gtk_box_pack_start (GTK_BOX(zoom_hbox), ddisp->zoom_status,
524 FALSE, FALSE, 0);
526 gtk_box_pack_start (GTK_BOX (status_hbox), zoom_hbox, FALSE, FALSE, 0);
528 /* Grid on/off button */
529 ddisp->grid_status = dia_toggle_button_new_with_icons(dia_on_grid_icon,
530 dia_off_grid_icon);
532 g_signal_connect(G_OBJECT(ddisp->grid_status), "toggled",
533 G_CALLBACK (grid_toggle_snap), ddisp);
534 gtk_tooltips_set_tip(tool_tips, ddisp->grid_status,
535 _("Toggles snap-to-grid for this window."), NULL);
536 gtk_box_pack_start (GTK_BOX (status_hbox), ddisp->grid_status,
537 FALSE, FALSE, 0);
540 ddisp->mainpoint_status = dia_toggle_button_new_with_icons(dia_mainpoints_on_icon,
541 dia_mainpoints_off_icon);
543 g_signal_connect(G_OBJECT(ddisp->mainpoint_status), "toggled",
544 G_CALLBACK (interface_toggle_mainpoint_magnetism), ddisp);
545 gtk_tooltips_set_tip(tool_tips, ddisp->mainpoint_status,
546 _("Toggles object snapping for this window."), NULL);
547 gtk_box_pack_start (GTK_BOX (status_hbox), ddisp->mainpoint_status,
548 FALSE, FALSE, 0);
551 /* Statusbar */
552 ddisp->modified_status = gtk_statusbar_new ();
554 gtk_box_pack_start (GTK_BOX (status_hbox), ddisp->modified_status,
555 TRUE, TRUE, 0);
557 gtk_table_attach (GTK_TABLE (table), status_hbox, 0, 3, 3, 4,
558 GTK_FILL, GTK_FILL, 0, 0);
560 gtk_widget_show (ddisp->hsb);
561 gtk_widget_show (ddisp->vsb);
562 gtk_widget_show (ddisp->origin);
563 gtk_widget_show (ddisp->hrule);
564 gtk_widget_show (ddisp->vrule);
565 gtk_widget_show (ddisp->zoom_status);
566 gtk_widget_show (zoom_hbox);
567 gtk_widget_show (zoom_label);
568 gtk_widget_show (ddisp->grid_status);
569 gtk_widget_show (ddisp->mainpoint_status);
570 gtk_widget_show (ddisp->modified_status);
571 gtk_widget_show (status_hbox);
572 gtk_widget_show (table);
573 if (use_mbar)
575 gtk_widget_show (ddisp->menu_bar);
576 gtk_widget_show (root_vbox);
578 gtk_widget_show (ddisp->shell);
580 /* before showing up, checking canvas's REAL size */
581 if (use_mbar && ddisp->hrule->allocation.width > width)
583 /* The menubar is not shrinkable, so the shell will have at least
584 * the menubar's width. If the diagram's requested width is smaller,
585 * the canvas will be enlarged to fit the place. In this case, we
586 * need to adjust the horizontal scrollbar according to the size
587 * that will be allocated, which the same as the hrule got.
590 width = ddisp->hrule->allocation.width;
592 ddisp->hsbdata->upper = width;
593 ddisp->hsbdata->page_increment = (width - 1) / 4;
594 ddisp->hsbdata->page_size = width - 1;
596 gtk_adjustment_changed (GTK_ADJUSTMENT(ddisp->hsbdata));
598 gtk_widget_show (ddisp->canvas);
600 /* set the focus to the canvas area */
601 gtk_widget_grab_focus (ddisp->canvas);
604 void
605 tool_select_update (GtkWidget *w,
606 gpointer data)
608 ToolButtonData *tooldata = (ToolButtonData *) data;
610 if (tooldata == NULL) {
611 g_warning(_("NULL tooldata in tool_select_update"));
612 return;
615 if (tooldata->type != -1) {
616 gint x, y;
617 GdkModifierType mask;
618 /* get the modifiers */
619 gdk_window_get_pointer (gtk_widget_get_parent_window(w), &x, &y, &mask);
620 tool_select (tooldata->type, tooldata->extra_data, tooldata->user_data,
621 w, mask&1);
625 static gint
626 tool_button_press (GtkWidget *w,
627 GdkEventButton *event,
628 gpointer data)
630 ToolButtonData *tooldata = (ToolButtonData *) data;
632 if ((event->type == GDK_2BUTTON_PRESS) &&
633 (event->button == 1)) {
634 tool_options_dialog_show (tooldata->type, tooldata->extra_data,
635 tooldata->user_data, w, event->state&1);
636 return TRUE;
639 return FALSE;
642 static void
643 tool_drag_data_get (GtkWidget *widget, GdkDragContext *context,
644 GtkSelectionData *selection_data, guint info,
645 guint32 time, ToolButtonData *tooldata)
647 if (info == 0) {
648 gtk_selection_data_set(selection_data, selection_data->target,
649 8, (guchar *)&tooldata, sizeof(ToolButtonData *));
653 static void
654 tool_setup_drag_source(GtkWidget *button, ToolButtonData *tooldata,
655 GdkPixmap *pixmap, GdkBitmap *mask)
657 g_return_if_fail(tooldata->type == CREATE_OBJECT_TOOL);
659 gtk_drag_source_set(button, GDK_BUTTON1_MASK,
660 create_object_targets, 1,
661 GDK_ACTION_DEFAULT|GDK_ACTION_COPY);
662 g_signal_connect(GTK_OBJECT(button), "drag_data_get",
663 G_CALLBACK(tool_drag_data_get), tooldata);
664 if (pixmap)
665 gtk_drag_source_set_icon(button, gtk_widget_get_colormap(button),
666 pixmap, mask);
670 void
671 tool_select_callback(GtkWidget *widget, gpointer data) {
672 ToolButtonData *tooldata = (ToolButtonData *)data;
674 if (tooldata == NULL) {
675 g_warning("NULL tooldata in tool_select_callback");
676 return;
679 if (tooldata->type != -1) {
680 tool_select (tooldata->type, tooldata->extra_data,
681 tooldata->user_data,widget);
687 * Don't look too deep into this function. It is doing bad things
688 * with casts to conform to the historically interface. We now
689 * the difference between char* and char** - most of the time ;)
691 static GtkWidget *
692 create_widget_from_xpm_or_gdkp(gchar **icon_data, GtkWidget *button)
694 GtkWidget *pixmapwidget;
696 if (strncmp((char*)icon_data, "GdkP", 4) == 0) {
697 GdkPixbuf *p;
698 p = gdk_pixbuf_new_from_inline(-1, (char*)icon_data, TRUE, NULL);
699 pixmapwidget = gtk_image_new_from_pixbuf(p);
700 } else {
701 GdkBitmap *mask = NULL;
702 GtkStyle *style;
703 char **pixmap_data;
704 GdkPixmap *pixmap = NULL;
706 pixmap_data = icon_data;
707 style = gtk_widget_get_style(button);
708 pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL,
709 gtk_widget_get_colormap(button), &mask,
710 &style->bg[GTK_STATE_NORMAL], pixmap_data);
711 pixmapwidget = gtk_pixmap_new(pixmap, mask);
713 return pixmapwidget;
716 static void
717 create_tools(GtkWidget *parent)
719 GtkWidget *button;
720 GtkWidget *pixmapwidget;
721 GdkPixmap *pixmap = NULL;
722 GdkBitmap *mask = NULL;
723 GtkStyle *style;
724 char **pixmap_data;
725 int i;
727 for (i = 0; i < NUM_TOOLS; i++) {
728 tool_widgets[i] = button = gtk_radio_button_new (tool_group);
729 gtk_container_set_border_width (GTK_CONTAINER (button), 0);
730 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_HALF);
731 tool_group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
732 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
734 gtk_wrap_box_pack(GTK_WRAP_BOX(parent), button,
735 TRUE, TRUE, FALSE, TRUE);
737 if (tool_data[i].callback_data.type == MODIFY_TOOL) {
738 modify_tool_button = GTK_WIDGET(button);
741 if (tool_data[i].icon_data==NULL) {
742 DiaObjectType *type;
743 type =
744 object_get_type((char *)tool_data[i].callback_data.extra_data);
745 if (type == NULL)
746 pixmap_data = tool_data[0].icon_data;
747 else
748 pixmap_data = type->pixmap;
749 pixmapwidget = create_widget_from_xpm_or_gdkp(pixmap_data, button);
750 } else {
751 pixmapwidget = create_widget_from_xpm_or_gdkp(tool_data[i].icon_data, button);
754 /* GTKBUG:? padding changes */
755 gtk_misc_set_padding(GTK_MISC(pixmapwidget), 2, 2);
757 gtk_container_add (GTK_CONTAINER (button), pixmapwidget);
759 g_signal_connect (GTK_OBJECT (button), "clicked",
760 G_CALLBACK (tool_select_update),
761 &tool_data[i].callback_data);
763 g_signal_connect (GTK_OBJECT (button), "button_press_event",
764 G_CALLBACK (tool_button_press),
765 &tool_data[i].callback_data);
767 if (tool_data[i].callback_data.type == CREATE_OBJECT_TOOL)
768 tool_setup_drag_source(button, &tool_data[i].callback_data,
769 pixmap, mask);
771 if (pixmap) gdk_pixmap_unref(pixmap);
772 if (mask) gdk_bitmap_unref(mask);
774 tool_data[i].callback_data.widget = button;
776 if (tool_data[i].tool_accelerator) {
777 guint key;
778 GdkModifierType mods;
780 gtk_accelerator_parse (tool_data[i].tool_accelerator, &key, &mods);
782 gtk_tooltips_set_tip (tool_tips, button,
783 g_strconcat(gettext(tool_data[i].tool_desc),
784 " (", gtk_accelerator_get_label(key, mods), ")"),
785 NULL);
786 } else {
787 gtk_tooltips_set_tip (tool_tips, button,
788 gettext(tool_data[i].tool_desc), NULL);
791 gtk_widget_show (pixmapwidget);
792 gtk_widget_show (button);
796 static GtkWidget *sheet_option_menu;
797 static GtkWidget *sheet_wbox;
799 gchar *interface_current_sheet_name;
801 static Sheet *
802 get_sheet_by_name(const gchar *name)
804 GSList *tmp;
805 for (tmp = get_sheets_list(); tmp != NULL; tmp = tmp->next) {
806 Sheet *sheet = tmp->data;
807 /* There is something fishy with comparing both forms: the english and the localized one.
808 * But we should be on the safe side here, especially when bug #328570 gets tackled.
810 if (0 == g_strcasecmp(name, sheet->name) || 0 == g_strcasecmp(name, gettext(sheet->name)))
811 return sheet;
813 return NULL;
816 static void
817 fill_sheet_wbox(Sheet *sheet)
819 int rows;
820 GtkStyle *style;
821 GSList *tmp;
822 GtkWidget *first_button = NULL;
824 gtk_container_foreach(GTK_CONTAINER(sheet_wbox),
825 (GtkCallback)gtk_widget_destroy, NULL);
826 tool_group = gtk_radio_button_group(GTK_RADIO_BUTTON(tool_widgets[0]));
828 /* Remember sheet 'name' for 'Sheets and Objects' dialog */
829 interface_current_sheet_name = sheet->name;
831 /* set the aspect ratio on the wbox */
832 rows = ceil(g_slist_length(sheet->objects) / (double)COLUMNS);
833 if (rows<1) rows = 1;
834 gtk_wrap_box_set_aspect_ratio(GTK_WRAP_BOX(sheet_wbox),
835 COLUMNS * 1.0 / rows);
836 style = gtk_widget_get_style(sheet_wbox);
837 for (tmp = sheet->objects; tmp != NULL; tmp = tmp->next) {
838 SheetObject *sheet_obj = tmp->data;
839 GdkPixmap *pixmap = NULL;
840 GdkBitmap *mask = NULL;
841 GtkWidget *pixmapwidget;
842 GtkWidget *button;
843 ToolButtonData *data;
845 if (sheet_obj->pixmap != NULL) {
846 pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL,
847 gtk_widget_get_colormap(sheet_wbox), &mask,
848 &style->bg[GTK_STATE_NORMAL], sheet_obj->pixmap);
849 } else if (sheet_obj->pixmap_file != NULL) {
850 GdkPixbuf *pixbuf;
851 GError* gerror = NULL;
853 pixbuf = gdk_pixbuf_new_from_file(sheet_obj->pixmap_file, &gerror);
854 if (pixbuf != NULL) {
855 gdk_pixbuf_render_pixmap_and_mask_for_colormap(pixbuf, gtk_widget_get_colormap(sheet_wbox), &pixmap, &mask, 1.0);
856 gdk_pixbuf_unref(pixbuf);
857 } else {
858 pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL,
859 gtk_widget_get_colormap(sheet_wbox), &mask,
860 &style->bg[GTK_STATE_NORMAL], missing);
862 message_warning("failed to load icon for file\n %s\n cause=%s",
863 sheet_obj->pixmap_file,gerror?gerror->message:"[NULL]");
865 } else {
866 DiaObjectType *type;
867 type = object_get_type(sheet_obj->object_type);
868 pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL,
869 gtk_widget_get_colormap(sheet_wbox), &mask,
870 &style->bg[GTK_STATE_NORMAL], type->pixmap);
872 if (pixmap) {
873 pixmapwidget = gtk_pixmap_new(pixmap, mask);
874 gdk_pixmap_unref(pixmap);
875 if (mask) gdk_bitmap_unref(mask);
876 } else {
877 pixmapwidget = gtk_type_new(gtk_pixmap_get_type());
880 button = gtk_radio_button_new (tool_group);
881 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
882 gtk_container_set_border_width (GTK_CONTAINER (button), 0);
883 tool_group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
885 gtk_container_add (GTK_CONTAINER (button), pixmapwidget);
886 gtk_widget_show(pixmapwidget);
888 gtk_wrap_box_pack_wrapped(GTK_WRAP_BOX(sheet_wbox), button,
889 FALSE, TRUE, FALSE, TRUE, sheet_obj->line_break);
890 gtk_widget_show(button);
892 data = g_new(ToolButtonData, 1);
893 data->type = CREATE_OBJECT_TOOL;
894 data->extra_data = sheet_obj->object_type;
895 data->user_data = sheet_obj->user_data;
896 gtk_object_set_data_full(GTK_OBJECT(button), "Dia::ToolButtonData",
897 data, (GdkDestroyNotify)g_free);
898 if (first_button == NULL) first_button = button;
900 g_signal_connect (GTK_OBJECT (button), "clicked",
901 G_CALLBACK (tool_select_update), data);
902 g_signal_connect (GTK_OBJECT (button), "button_press_event",
903 G_CALLBACK (tool_button_press), data);
905 tool_setup_drag_source(button, data, pixmap, mask);
907 gtk_tooltips_set_tip (tool_tips, button,
908 gettext(sheet_obj->description), NULL);
910 /* If the selection is in the old sheet, steal it */
911 if (active_tool != NULL &&
912 active_tool->type == CREATE_OBJECT_TOOL &&
913 first_button != NULL)
914 gtk_signal_emit_by_name(GTK_OBJECT(first_button), "toggled",
915 GTK_BUTTON(first_button), NULL);
918 static void
919 sheet_menu_callback(DiaDynamicMenu *menu, const gchar *string, void *user_data)
921 Sheet *sheet = get_sheet_by_name(string);
922 if (sheet == NULL) {
923 message_warning(_("No sheet named %s"), string);
924 } else {
925 persistence_set_string("last-sheet-selected", string);
926 fill_sheet_wbox(sheet);
930 static int
931 cmp_names (const void *a, const void *b)
933 return g_utf8_collate(gettext( (gchar *)a ), gettext( (gchar *)b ));
936 static GList *
937 get_sheet_names()
939 GSList *tmp;
940 GList *names = NULL;
941 for (tmp = get_sheets_list(); tmp != NULL; tmp = tmp->next) {
942 Sheet *sheet = tmp->data;
943 names = g_list_append(names, sheet->name);
945 /* Already sorted in lib/ but here we sort by the localized (display-)name */
946 return g_list_sort (names, cmp_names);
949 static void
950 create_sheet_dropdown_menu(GtkWidget *parent)
952 GList *sheet_names = get_sheet_names();
954 if (sheet_option_menu != NULL) {
955 gtk_container_remove(GTK_CONTAINER(parent), sheet_option_menu);
956 sheet_option_menu = NULL;
959 sheet_option_menu =
960 dia_dynamic_menu_new_stringlistbased(_("Other sheets"), sheet_names,
961 sheet_menu_callback,
962 NULL, "sheets");
963 dia_dynamic_menu_add_default_entry(DIA_DYNAMIC_MENU(sheet_option_menu),
964 "Assorted");
965 dia_dynamic_menu_add_default_entry(DIA_DYNAMIC_MENU(sheet_option_menu),
966 "UML");
967 /* gtk_widget_set_size_request(sheet_option_menu, 20, -1);*/
968 gtk_wrap_box_pack_wrapped(GTK_WRAP_BOX(parent), sheet_option_menu,
969 TRUE, TRUE, FALSE, FALSE, TRUE);
970 /* 15 is a magic number that goes beyond the standard objects and
971 * the divider. */
972 gtk_wrap_box_reorder_child(GTK_WRAP_BOX(parent),
973 sheet_option_menu, 15);
974 gtk_widget_show(sheet_option_menu);
977 void
978 fill_sheet_menu(void)
980 gchar *selection = dia_dynamic_menu_get_entry(DIA_DYNAMIC_MENU(sheet_option_menu));
981 create_sheet_dropdown_menu(gtk_widget_get_parent(sheet_option_menu));
982 dia_dynamic_menu_select_entry(DIA_DYNAMIC_MENU(sheet_option_menu), selection);
983 g_free(selection);
986 void
987 create_sheets(GtkWidget *parent)
989 GtkWidget *separator;
990 GtkWidget *label;
991 GtkWidget *swin;
992 gchar *sheetname;
993 Sheet *sheet;
995 separator = gtk_hseparator_new ();
996 /* add a bit of padding around the separator */
997 label = gtk_vbox_new(FALSE, 0);
998 gtk_box_pack_start(GTK_BOX(label), separator, TRUE, TRUE, 3);
999 gtk_widget_show(label);
1001 gtk_wrap_box_pack_wrapped (GTK_WRAP_BOX(parent), label, TRUE,TRUE, FALSE,FALSE, TRUE);
1002 gtk_widget_show(separator);
1004 create_sheet_dropdown_menu(parent);
1006 swin = gtk_scrolled_window_new(NULL, NULL);
1007 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swin),
1008 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1009 gtk_wrap_box_pack_wrapped(GTK_WRAP_BOX(parent), swin, TRUE, TRUE, TRUE, TRUE, TRUE);
1010 gtk_widget_show(swin);
1012 sheet_wbox = gtk_hwrap_box_new(FALSE);
1013 gtk_wrap_box_set_justify(GTK_WRAP_BOX(sheet_wbox), GTK_JUSTIFY_TOP);
1014 gtk_wrap_box_set_line_justify(GTK_WRAP_BOX(sheet_wbox), GTK_JUSTIFY_LEFT);
1015 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(swin), sheet_wbox);
1016 gtk_widget_show(sheet_wbox);
1018 persistence_register_string("last-sheet-selected", _("Misc"));
1019 sheetname = persistence_get_string("last-sheet-selected");
1020 sheet = get_sheet_by_name(sheetname);
1021 if (sheet == NULL) {
1022 /* Couldn't find it */
1023 } else {
1024 fill_sheet_wbox(sheet);
1025 dia_dynamic_menu_select_entry(DIA_DYNAMIC_MENU(sheet_option_menu),
1026 sheetname);
1028 g_free(sheetname);
1031 static void
1032 create_color_area (GtkWidget *parent)
1034 GtkWidget *frame;
1035 GtkWidget *alignment;
1036 GtkWidget *col_area;
1037 GtkWidget *line_area;
1038 GdkPixmap *default_pixmap;
1039 GdkBitmap *default_mask;
1040 GdkPixmap *swap_pixmap;
1041 GdkBitmap *swap_mask;
1042 GtkStyle *style;
1043 GtkWidget *hbox;
1045 gtk_widget_ensure_style(parent);
1046 style = gtk_widget_get_style(parent);
1048 default_pixmap =
1049 gdk_pixmap_colormap_create_from_xpm_d(NULL,
1050 gtk_widget_get_colormap(parent), &default_mask,
1051 &style->bg[GTK_STATE_NORMAL], default_xpm);
1052 swap_pixmap =
1053 gdk_pixmap_colormap_create_from_xpm_d(NULL,
1054 gtk_widget_get_colormap(parent), &swap_mask,
1055 &style->bg[GTK_STATE_NORMAL], swap_xpm);
1057 frame = gtk_frame_new (NULL);
1058 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
1059 gtk_wrap_box_pack_wrapped(GTK_WRAP_BOX(parent), frame, TRUE, TRUE, FALSE, FALSE, TRUE);
1060 gtk_widget_realize (frame);
1062 hbox = gtk_hbox_new (FALSE, 1);
1063 gtk_container_set_border_width (GTK_CONTAINER (hbox), 0);
1064 gtk_container_add (GTK_CONTAINER (frame), hbox);
1066 /* Color area: */
1067 alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
1068 gtk_container_set_border_width (GTK_CONTAINER (alignment), 3);
1070 col_area = color_area_create (54, 42,
1071 default_pixmap, default_mask,
1072 swap_pixmap, swap_mask);
1073 gtk_container_add (GTK_CONTAINER (alignment), col_area);
1076 gtk_box_pack_start (GTK_BOX (hbox), alignment, TRUE, TRUE, 0);
1078 gtk_tooltips_set_tip (tool_tips, col_area,
1079 _("Foreground & background colors for new objects. "
1080 "The small black and white squares reset colors. "
1081 "The small arrows swap colors. Double click to "
1082 "change colors."),
1083 NULL);
1085 gtk_widget_show (alignment);
1087 /* Linewidth area: */
1088 alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
1089 gtk_container_set_border_width (GTK_CONTAINER (alignment), 3);
1091 line_area = linewidth_area_create ();
1092 gtk_container_add (GTK_CONTAINER (alignment), line_area);
1093 gtk_box_pack_start (GTK_BOX (hbox), alignment, TRUE, TRUE, 0);
1094 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);
1095 gtk_widget_show (alignment);
1097 gtk_widget_show (col_area);
1098 gtk_widget_show (line_area);
1099 gtk_widget_show (hbox);
1100 gtk_widget_show (frame);
1103 static void
1104 change_start_arrow_style(Arrow arrow, gpointer user_data)
1106 attributes_set_default_start_arrow(arrow);
1108 static void
1109 change_end_arrow_style(Arrow arrow, gpointer user_data)
1111 attributes_set_default_end_arrow(arrow);
1113 static void
1114 change_line_style(LineStyle lstyle, real dash_length, gpointer user_data)
1116 attributes_set_default_line_style(lstyle, dash_length);
1119 static void
1120 create_lineprops_area(GtkWidget *parent)
1122 GtkWidget *chooser;
1123 Arrow arrow;
1124 real dash_length;
1125 LineStyle style;
1127 chooser = dia_arrow_chooser_new(TRUE, change_start_arrow_style, NULL, tool_tips);
1128 gtk_wrap_box_pack_wrapped(GTK_WRAP_BOX(parent), chooser, FALSE, TRUE, FALSE, TRUE, TRUE);
1129 arrow.width = persistence_register_real("start-arrow-width", DEFAULT_ARROW_WIDTH);
1130 arrow.length = persistence_register_real("start-arrow-length", DEFAULT_ARROW_LENGTH);
1131 arrow.type = arrow_type_from_name(persistence_register_string("start-arrow-type", "None"));
1132 dia_arrow_chooser_set_arrow(DIA_ARROW_CHOOSER(chooser), &arrow);
1133 attributes_set_default_start_arrow(arrow);
1134 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);
1135 gtk_widget_show(chooser);
1137 chooser = dia_line_chooser_new(change_line_style, NULL);
1138 gtk_wrap_box_pack(GTK_WRAP_BOX(parent), chooser, TRUE, TRUE, FALSE, TRUE);
1139 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);
1140 style = persistence_register_integer("line-style", LINESTYLE_SOLID);
1141 dash_length = persistence_register_real("dash-length", DEFAULT_LINESTYLE_DASHLEN);
1142 dia_line_chooser_set_line_style(DIA_LINE_CHOOSER(chooser), style, dash_length);
1143 gtk_widget_show(chooser);
1145 chooser = dia_arrow_chooser_new(FALSE, change_end_arrow_style, NULL, tool_tips);
1146 arrow.width = persistence_register_real("end-arrow-width", DEFAULT_ARROW_WIDTH);
1147 arrow.length = persistence_register_real("end-arrow-length", DEFAULT_ARROW_LENGTH);
1148 arrow.type = arrow_type_from_name(persistence_register_string("end-arrow-type", "Filled Concave"));
1149 dia_arrow_chooser_set_arrow(DIA_ARROW_CHOOSER(chooser), &arrow);
1150 attributes_set_default_end_arrow(arrow);
1152 gtk_wrap_box_pack(GTK_WRAP_BOX(parent), chooser, FALSE, TRUE, FALSE, TRUE);
1153 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);
1154 gtk_widget_show(chooser);
1157 static void
1158 toolbox_destroy (GtkWidget *widget, gpointer data)
1160 app_exit();
1163 static gboolean
1164 toolbox_delete (GtkWidget *widget, GdkEvent *event, gpointer data)
1166 if (!app_is_embedded()) {
1167 gulong handlerid;
1168 /** Stop toolbox_destroy from being called */
1169 handlerid = g_signal_handler_find(widget, G_SIGNAL_MATCH_FUNC,
1170 0, 0, NULL, toolbox_destroy, NULL);
1171 if (handlerid != 0)
1172 g_signal_handler_disconnect (GTK_OBJECT (widget), handlerid);
1174 /** If the app didn't exit, don't close the window */
1175 return (!app_exit());
1177 return FALSE;
1181 /* HB: file dnd stuff lent by The Gimp, not fully understood but working ...
1183 enum
1185 DIA_DND_TYPE_URI_LIST,
1186 DIA_DND_TYPE_TEXT_PLAIN,
1189 static GtkTargetEntry toolbox_target_table[] =
1191 { "text/uri-list", 0, DIA_DND_TYPE_URI_LIST },
1192 { "text/plain", 0, DIA_DND_TYPE_TEXT_PLAIN }
1195 static guint toolbox_n_targets = (sizeof (toolbox_target_table) /
1196 sizeof (toolbox_target_table[0]));
1198 static void
1199 dia_dnd_file_drag_data_received (GtkWidget *widget,
1200 GdkDragContext *context,
1201 gint x,
1202 gint y,
1203 GtkSelectionData *data,
1204 guint info,
1205 guint time)
1207 switch (context->action)
1209 case GDK_ACTION_DEFAULT:
1210 case GDK_ACTION_COPY:
1211 case GDK_ACTION_MOVE:
1212 case GDK_ACTION_LINK:
1213 case GDK_ACTION_ASK:
1214 default:
1216 Diagram *diagram = NULL;
1217 DDisplay *ddisp;
1218 gchar *sPath = NULL, *pFrom, *pTo;
1220 pFrom = strstr((gchar *) data->data, "file:");
1221 while (pFrom) {
1222 GError *error = NULL;
1224 pTo = pFrom;
1225 while (*pTo != 0 && *pTo != 0xd && *pTo != 0xa) pTo ++;
1226 sPath = g_strndup(pFrom, pTo - pFrom);
1228 /* format changed with Gtk+2.0, use conversion */
1229 pFrom = g_filename_from_uri (sPath, NULL, &error);
1230 diagram = diagram_load (pFrom, NULL);
1231 g_free (pFrom);
1232 g_free(sPath);
1234 if (diagram != NULL) {
1235 diagram_update_extents(diagram);
1236 layer_dialog_set_diagram(diagram);
1238 if (diagram->displays == NULL) {
1239 ddisp = new_display(diagram);
1243 pFrom = strstr(pTo, "file:");
1244 } /* while */
1245 gtk_drag_finish (context, TRUE, FALSE, time);
1247 break;
1249 return;
1252 void
1253 create_toolbox ()
1255 GtkWidget *window;
1256 GtkWidget *main_vbox;
1257 GtkWidget *wrapbox;
1258 GtkWidget *menubar;
1259 GtkAccelGroup *accel_group;
1260 GdkPixbuf *pixbuf;
1262 #ifdef GNOME
1263 window = gnome_app_new ("Dia", _("Diagram Editor"));
1264 #else
1265 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1266 gtk_widget_ref (window);
1267 gtk_window_set_title (GTK_WINDOW (window), "Dia v" VERSION);
1268 #endif
1269 gtk_window_set_role (GTK_WINDOW (window), "toolbox_window");
1270 gtk_window_set_default_size(GTK_WINDOW(window), 146, 349);
1272 pixbuf = gdk_pixbuf_new_from_inline (-1, dia_app_icon, FALSE, NULL);
1273 if (pixbuf) {
1274 gtk_window_set_icon (GTK_WINDOW (window), pixbuf);
1275 g_object_unref (pixbuf);
1278 g_signal_connect (GTK_OBJECT (window), "delete_event",
1279 G_CALLBACK (toolbox_delete),
1280 window);
1282 g_signal_connect (GTK_OBJECT (window), "destroy",
1283 G_CALLBACK (toolbox_destroy),
1284 window);
1286 main_vbox = gtk_vbox_new (FALSE, 1);
1287 gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 1);
1288 #ifdef GNOME
1289 gnome_app_set_contents(GNOME_APP(window), main_vbox);
1290 #else
1291 gtk_container_add (GTK_CONTAINER (window), main_vbox);
1292 #endif
1293 gtk_widget_show (main_vbox);
1295 /* tooltips */
1296 tool_tips = gtk_tooltips_new ();
1298 /* gtk_tooltips_set_colors (tool_tips,
1299 &colors[11],
1300 &main_vbox->style->fg[GTK_STATE_NORMAL]);*/
1302 wrapbox = gtk_hwrap_box_new(FALSE);
1303 gtk_wrap_box_set_aspect_ratio(GTK_WRAP_BOX(wrapbox), 144.0 / 318.0);
1304 gtk_wrap_box_set_justify(GTK_WRAP_BOX(wrapbox), GTK_JUSTIFY_TOP);
1305 gtk_wrap_box_set_line_justify(GTK_WRAP_BOX(wrapbox), GTK_JUSTIFY_LEFT);
1308 /* pack the rest of the stuff */
1309 gtk_box_pack_end (GTK_BOX (main_vbox), wrapbox, TRUE, TRUE, 0);
1310 gtk_container_set_border_width (GTK_CONTAINER (wrapbox), 0);
1311 gtk_widget_show (wrapbox);
1313 create_tools (wrapbox);
1314 create_sheets (wrapbox);
1315 create_color_area (wrapbox);
1316 create_lineprops_area (wrapbox);
1318 /* Setup toolbox area as file drop destination */
1319 gtk_drag_dest_set (wrapbox,
1320 GTK_DEST_DEFAULT_ALL,
1321 toolbox_target_table, toolbox_n_targets,
1322 GDK_ACTION_COPY);
1323 g_signal_connect (GTK_OBJECT (wrapbox), "drag_data_received",
1324 G_CALLBACK (dia_dnd_file_drag_data_received),
1325 wrapbox);
1327 /* menus -- initialised afterwards, because initing the display menus
1328 * uses the tool buttons*/
1329 menus_get_toolbox_menubar(&menubar, &accel_group);
1330 gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
1331 #ifdef GNOME
1332 gnome_app_set_menus(GNOME_APP(window), GTK_MENU_BAR(menubar));
1333 #else
1334 gtk_box_pack_start (GTK_BOX (main_vbox), menubar, FALSE, TRUE, 0);
1335 gtk_widget_show (menubar);
1336 #endif
1337 persistence_register_window(GTK_WINDOW(window));
1339 toolbox_shell = window;
1342 void
1343 toolbox_show(void)
1345 gtk_widget_show(toolbox_shell);
1348 void
1349 toolbox_hide(void)
1351 gtk_widget_hide(toolbox_shell);
1354 void
1355 create_tree_window(void)
1357 GtkAction *action = menus_get_action ("FileTree");
1358 create_diagram_tree_window(&prefs.dia_tree, GTK_TOGGLE_ACTION(action));
1361 GtkWidget *
1362 interface_get_toolbox_shell(void)
1364 return toolbox_shell;