linewidth is now working for PS_SOLID
[dia.git] / app / interface.c
blob30faf735a8e035493c723d0ec192cac6bf31865c
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 "layer_dialog.h"
28 #include "interface.h"
29 #include "display.h"
30 #include "pixmaps.h"
31 #include "preferences.h"
32 #include "commands.h"
33 #include "dia_dirs.h"
34 #include "diagram_tree_window.h"
35 #include "intl.h"
36 #include "navigation.h"
37 #include "persistence.h"
38 #include "diaarrowchooser.h"
39 #include "dialinechooser.h"
40 #include "widgets.h"
42 #include <gdk-pixbuf/gdk-pixbuf.h>
43 #include "dia-app-icons.h"
44 #include "diacanvas.h"
46 static const GtkTargetEntry create_object_targets[] = {
47 { "application/x-dia-object", 0, 0 },
50 ToolButton tool_data[] =
52 { (char **) arrow_xpm,
53 N_("Modify object(s)"),
54 N_("Modify"),
55 { MODIFY_TOOL, NULL, NULL}
57 { (char **) magnify_xpm,
58 N_("Magnify"),
59 N_("Magnify"),
60 { MAGNIFY_TOOL, NULL, NULL}
62 { (char **) scroll_xpm,
63 N_("Scroll around the diagram"),
64 N_("Scroll"),
65 { SCROLL_TOOL, NULL, NULL}
67 { NULL,
68 N_("Text"),
69 N_("Text"),
70 { CREATE_OBJECT_TOOL, "Standard - Text", NULL }
72 { NULL,
73 N_("Box"),
74 N_("Box"),
75 { CREATE_OBJECT_TOOL, "Standard - Box", NULL }
77 { NULL,
78 N_("Ellipse"),
79 N_("Ellipse"),
80 { CREATE_OBJECT_TOOL, "Standard - Ellipse", NULL }
82 { NULL,
83 N_("Polygon"),
84 N_("Polygon"),
85 { CREATE_OBJECT_TOOL, "Standard - Polygon", NULL }
87 { NULL,
88 N_("Beziergon"),
89 N_("Beziergon"),
90 { CREATE_OBJECT_TOOL, "Standard - Beziergon", NULL }
92 { NULL,
93 N_("Line"),
94 N_("Line"),
95 { CREATE_OBJECT_TOOL, "Standard - Line", NULL }
97 { NULL,
98 N_("Arc"),
99 N_("Arc"),
100 { CREATE_OBJECT_TOOL, "Standard - Arc", NULL }
102 { NULL,
103 N_("Zigzagline"),
104 N_("Zigzagline"),
105 { CREATE_OBJECT_TOOL, "Standard - ZigZagLine", NULL }
107 { NULL,
108 N_("Polyline"),
109 N_("Polyline"),
110 { CREATE_OBJECT_TOOL, "Standard - PolyLine", NULL }
112 { NULL,
113 N_("Bezierline"),
114 N_("Bezierline"),
115 { CREATE_OBJECT_TOOL, "Standard - BezierLine", NULL }
117 { NULL,
118 N_("Image"),
119 N_("Image"),
120 { CREATE_OBJECT_TOOL, "Standard - Image", NULL }
124 #define NUM_TOOLS (sizeof (tool_data) / sizeof (ToolButton))
125 const int num_tools = NUM_TOOLS;
127 #define COLUMNS 4
128 #define ROWS 3
130 static GtkWidget *toolbox_shell = NULL;
131 static GtkWidget *tool_widgets[NUM_TOOLS];
132 /*static*/ GtkTooltips *tool_tips;
133 static GSList *tool_group = NULL;
135 GtkWidget *modify_tool_button;
137 static void
138 grid_toggle_snap(GtkWidget *widget, gpointer data)
140 DDisplay *ddisp = (DDisplay *)data;
141 ddisplay_set_snap_to_grid(ddisp,
142 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
145 /* The popup shell is a pointer to the display shell that posted the latest
146 * popup menu. When this is null, and a command is invoked, then the
147 * assumption is that the command was a result of a keyboard accelerator
149 GtkWidget *popup_shell = NULL;
151 static gint
152 origin_button_press(GtkWidget *widget, GdkEventButton *event, gpointer data)
154 DDisplay *ddisp = (DDisplay *)data;
156 display_set_active(ddisp);
157 ddisplay_popup_menu(ddisp, event);
159 /* stop the signal emission so the button doesn't grab the
160 * pointer from us */
161 gtk_signal_emit_stop_by_name(GTK_OBJECT(widget), "button_press_event");
163 return FALSE;
166 static void
167 zoom_activate_callback(GtkWidget *item, gpointer user_data) {
168 DDisplay *ddisp = (DDisplay *)user_data;
169 const gchar *zoom_text =
170 gtk_entry_get_text(GTK_ENTRY(gtk_object_get_user_data(GTK_OBJECT(ddisp->zoom_status))));
171 float zoom_amount, magnify;
172 gchar *zoomamount = g_object_get_data(G_OBJECT(item), "zoomamount");
173 if (zoomamount != NULL) {
174 zoom_text = zoomamount;
177 if (sscanf(zoom_text, "%f", &zoom_amount) == 1) {
178 Point middle;
179 Rectangle *visible;
181 magnify = (zoom_amount*DDISPLAY_NORMAL_ZOOM/100.0)/ddisp->zoom_factor;
182 if (fabs(magnify - 1.0) > 0.000001) {
183 visible = &ddisp->visible;
184 middle.x = visible->left*0.5 + visible->right*0.5;
185 middle.y = visible->top*0.5 + visible->bottom*0.5;
186 ddisplay_zoom(ddisp, &middle, magnify);
191 static void
192 zoom_add_zoom_amount(GtkWidget *menu, gchar *text, DDisplay *ddisp) {
193 GtkWidget *menuitem = gtk_menu_item_new_with_label(text);
194 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
195 g_signal_connect(GTK_OBJECT(menuitem),
196 "activate", G_CALLBACK(zoom_activate_callback),
197 ddisp);
198 g_object_set_data(G_OBJECT(menuitem), "zoomamount", text);
201 static void
202 zoom_popup_menu(GtkWidget *button, GdkEventButton *event, gpointer user_data) {
203 /* display_set_active(ddisp); */
204 /* ddisplay_popup_menu(ddisp, event); */
206 GtkMenu *menu = GTK_MENU(user_data);
208 gtk_menu_popup(menu, NULL, NULL, NULL, NULL,
209 event->button, event->time);
210 /* stop the signal emission so the button doesn't grab the
211 * pointer from us */
212 gtk_signal_emit_stop_by_name(GTK_OBJECT(button), "button_press_event");
215 static GtkWidget*
216 create_zoom_widget(DDisplay *ddisp) {
217 GtkWidget *combo;
218 GtkWidget *entry;
219 GtkWidget *menu;
220 GtkWidget *button;
221 GtkWidget *arrow;
223 combo = gtk_hbox_new(FALSE, 0);
224 entry = gtk_entry_new();
225 g_signal_connect (GTK_OBJECT (entry), "activate",
226 G_CALLBACK(zoom_activate_callback),
227 ddisp);
228 gtk_box_pack_start_defaults(GTK_BOX(combo), entry);
229 gtk_object_set_user_data(GTK_OBJECT(combo), entry);
230 gtk_entry_set_width_chars(GTK_ENTRY(entry), 8);
231 gtk_widget_show(entry);
233 button = gtk_button_new();
234 GTK_WIDGET_UNSET_FLAGS(button, GTK_CAN_FOCUS);
235 arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
236 gtk_container_add(GTK_CONTAINER(button), arrow);
237 gtk_box_pack_start_defaults(GTK_BOX(combo), button);
238 gtk_object_set_user_data(GTK_OBJECT(combo), entry);
239 gtk_widget_show_all(button);
241 menu = gtk_menu_new();
242 zoom_add_zoom_amount(menu, "400%", ddisp);
243 zoom_add_zoom_amount(menu, "283%", ddisp);
244 zoom_add_zoom_amount(menu, "200%", ddisp);
245 zoom_add_zoom_amount(menu, "141%", ddisp);
246 zoom_add_zoom_amount(menu, "100%", ddisp);
247 zoom_add_zoom_amount(menu, "85%", ddisp);
248 zoom_add_zoom_amount(menu, "70.7%", ddisp);
249 zoom_add_zoom_amount(menu, "50%", ddisp);
250 zoom_add_zoom_amount(menu, "35.4%", ddisp);
251 zoom_add_zoom_amount(menu, "25%", ddisp);
253 gtk_widget_show_all(menu);
255 g_signal_connect (GTK_OBJECT (button), "button_press_event",
256 G_CALLBACK(zoom_popup_menu),
257 menu);
259 return combo;
262 static gboolean
263 display_drop_callback(GtkWidget *widget, GdkDragContext *context,
264 gint x, gint y, guint time)
266 if (gtk_drag_get_source_widget(context) != NULL) {
267 /* we only accept drops from the same instance of the application,
268 * as the drag data is a pointer in our address space */
269 return TRUE;
271 gtk_drag_finish (context, FALSE, FALSE, time);
272 return FALSE;
275 static void
276 display_data_received_callback (GtkWidget *widget, GdkDragContext *context,
277 gint x, gint y, GtkSelectionData *data,
278 guint info, guint time, DDisplay *ddisp)
280 if (data->format == 8 && data->length == sizeof(ToolButtonData *) &&
281 gtk_drag_get_source_widget(context) != NULL) {
282 ToolButtonData *tooldata = *(ToolButtonData **)data->data;
284 /* g_message("Tool drop %s at (%d, %d)", (gchar *)tooldata->extra_data, x, y);*/
285 ddisplay_drop_object(ddisp, x, y,
286 object_get_type((gchar *)tooldata->extra_data),
287 tooldata->user_data);
289 gtk_drag_finish (context, TRUE, FALSE, time);
290 } else
291 gtk_drag_finish (context, FALSE, FALSE, time);
294 void
295 create_display_shell(DDisplay *ddisp,
296 int width, int height,
297 char *title, int use_mbar, int top_level_window)
299 GtkWidget *table, *widget;
300 GtkWidget *navigation_button;
301 GtkWidget *status_hbox;
302 GtkWidget *root_vbox = NULL;
303 GtkWidget *zoom_hbox, *zoom_label;
304 int s_width, s_height;
306 s_width = gdk_screen_width ();
307 s_height = gdk_screen_height ();
308 if (width > s_width)
309 width = s_width;
310 if (height > s_height)
311 width = s_width;
313 /* The adjustment datums */
314 ddisp->hsbdata = GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, width, 1, (width-1)/4, width-1));
315 ddisp->vsbdata = GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, height, 1, (height-1)/4, height-1));
317 /* The toplevel shell */
318 if (top_level_window) {
319 ddisp->shell = gtk_window_new (GTK_WINDOW_TOPLEVEL);
320 gtk_window_set_title (GTK_WINDOW (ddisp->shell), title);
321 gtk_window_set_role (GTK_WINDOW (ddisp->shell), "diagram_window");
323 static GdkPixbuf *pixbuf = NULL;
325 if (!pixbuf)
326 pixbuf = gdk_pixbuf_new_from_inline(-1, dia_diagram_icon, FALSE, NULL);
327 if (pixbuf)
328 gtk_window_set_icon (GTK_WINDOW (ddisp->shell), pixbuf);
330 gtk_window_set_default_size(ddisp->shell, width, height);
331 } else {
332 ddisp->shell = gtk_event_box_new ();
334 gtk_object_set_user_data (GTK_OBJECT (ddisp->shell), (gpointer) ddisp);
336 gtk_widget_set_events (ddisp->shell,
337 GDK_POINTER_MOTION_MASK |
338 GDK_POINTER_MOTION_HINT_MASK |
339 GDK_FOCUS_CHANGE_MASK);
340 /* GDK_ALL_EVENTS_MASK */
342 g_signal_connect (GTK_OBJECT (ddisp->shell), "delete_event",
343 G_CALLBACK (ddisplay_delete),
344 ddisp);
345 g_signal_connect (GTK_OBJECT (ddisp->shell), "destroy",
346 G_CALLBACK (ddisplay_destroy),
347 ddisp);
348 g_signal_connect (GTK_OBJECT (ddisp->shell), "focus_out_event",
349 G_CALLBACK (ddisplay_focus_out_event),
350 ddisp);
351 g_signal_connect (GTK_OBJECT (ddisp->shell), "focus_in_event",
352 G_CALLBACK (ddisplay_focus_in_event),
353 ddisp);
354 g_signal_connect (GTK_OBJECT (ddisp->shell), "realize",
355 G_CALLBACK (ddisplay_realize),
356 ddisp);
357 g_signal_connect (GTK_OBJECT (ddisp->shell), "unrealize",
358 G_CALLBACK (ddisplay_unrealize),
359 ddisp);
360 /*FIXME?:
361 g_signal_connect (GTK_OBJECT (ddisp->shell), "size_allocate",
362 G_CALLBACK (ddisplay_size_allocate),
363 ddisp);
366 /* the table containing all widgets */
367 table = gtk_table_new (4, 3, FALSE);
368 gtk_table_set_col_spacing (GTK_TABLE (table), 0, 1);
369 gtk_table_set_col_spacing (GTK_TABLE (table), 1, 2);
370 gtk_table_set_row_spacing (GTK_TABLE (table), 0, 1);
371 gtk_table_set_row_spacing (GTK_TABLE (table), 1, 2);
372 gtk_container_set_border_width (GTK_CONTAINER (table), 2);
373 if (use_mbar)
375 root_vbox = gtk_vbox_new (FALSE, 1);
376 gtk_container_add (GTK_CONTAINER (ddisp->shell), root_vbox);
377 gtk_box_pack_end (GTK_BOX (root_vbox), table, TRUE, TRUE, 0);
379 else
381 gtk_container_add (GTK_CONTAINER (ddisp->shell), table);
385 /* scrollbars, rulers, canvas, menu popup button */
386 if (!use_mbar) {
387 ddisp->origin = gtk_button_new();
388 GTK_WIDGET_UNSET_FLAGS(ddisp->origin, GTK_CAN_FOCUS);
389 widget = gtk_arrow_new(GTK_ARROW_RIGHT, GTK_SHADOW_OUT);
390 gtk_container_add(GTK_CONTAINER(ddisp->origin), widget);
391 gtk_tooltips_set_tip(tool_tips, widget, _("Diagram menu."), NULL);
392 gtk_widget_show(widget);
393 g_signal_connect(GTK_OBJECT(ddisp->origin), "button_press_event",
394 G_CALLBACK(origin_button_press), ddisp);
396 else {
397 ddisp->origin = gtk_frame_new (NULL);
398 gtk_frame_set_shadow_type (GTK_FRAME (ddisp->origin), GTK_SHADOW_OUT);
402 ddisp->hrule = gtk_hruler_new ();
403 g_signal_connect_swapped (GTK_OBJECT (ddisp->shell), "motion_notify_event",
404 G_CALLBACK(GTK_WIDGET_GET_CLASS (ddisp->hrule)->motion_notify_event),
405 GTK_OBJECT (ddisp->hrule));
407 ddisp->vrule = gtk_vruler_new ();
408 g_signal_connect_swapped (GTK_OBJECT (ddisp->shell), "motion_notify_event",
409 G_CALLBACK(GTK_WIDGET_GET_CLASS (ddisp->vrule)->motion_notify_event),
410 GTK_OBJECT (ddisp->vrule));
412 ddisp->hsb = gtk_hscrollbar_new (ddisp->hsbdata);
413 GTK_WIDGET_UNSET_FLAGS (ddisp->hsb, GTK_CAN_FOCUS);
414 ddisp->vsb = gtk_vscrollbar_new (ddisp->vsbdata);
415 GTK_WIDGET_UNSET_FLAGS (ddisp->vsb, GTK_CAN_FOCUS);
418 /* set up the scrollbar observers */
419 g_signal_connect (GTK_OBJECT (ddisp->hsbdata), "value_changed",
420 G_CALLBACK(ddisplay_hsb_update),
421 ddisp);
422 g_signal_connect (GTK_OBJECT (ddisp->vsbdata), "value_changed",
423 G_CALLBACK(ddisplay_vsb_update),
424 ddisp);
426 /* Popup button between scrollbars for navigation window */
427 navigation_button = navigation_popup_new(ddisp);
428 gtk_tooltips_set_tip(tool_tips, navigation_button,
429 _("Pops up the Navigation window."), NULL);
430 gtk_widget_show(navigation_button);
432 /* Canvas */
433 /* ddisp->canvas = gtk_drawing_area_new ();*/
434 ddisp->canvas = dia_canvas_new();
435 /* Dia's canvas does it' double buffering alone so switch off GTK's */
436 gtk_widget_set_double_buffered (ddisp->canvas, FALSE);
437 dia_canvas_set_size(ddisp->canvas, width, height);
438 gtk_widget_set_events (ddisp->canvas, CANVAS_EVENT_MASK);
439 GTK_WIDGET_SET_FLAGS (ddisp->canvas, GTK_CAN_FOCUS);
440 g_signal_connect (GTK_OBJECT (ddisp->canvas), "event",
441 G_CALLBACK(ddisplay_canvas_events),
442 ddisp);
444 gtk_drag_dest_set(ddisp->canvas, GTK_DEST_DEFAULT_ALL,
445 create_object_targets, 1, GDK_ACTION_COPY);
446 g_signal_connect (GTK_OBJECT (ddisp->canvas), "drag_drop",
447 G_CALLBACK(display_drop_callback), NULL);
448 g_signal_connect (GTK_OBJECT (ddisp->canvas), "drag_data_received",
449 G_CALLBACK(display_data_received_callback), ddisp);
451 gtk_object_set_user_data (GTK_OBJECT (ddisp->canvas), (gpointer) ddisp);
453 /* pack all the widgets */
454 gtk_table_attach (GTK_TABLE (table), ddisp->origin, 0, 1, 0, 1,
455 GTK_FILL, GTK_FILL, 0, 0);
456 gtk_table_attach (GTK_TABLE (table), ddisp->hrule, 1, 2, 0, 1,
457 GTK_EXPAND | GTK_SHRINK | GTK_FILL, GTK_FILL, 0, 0);
458 gtk_table_attach (GTK_TABLE (table), ddisp->vrule, 0, 1, 1, 2,
459 GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
460 gtk_table_attach (GTK_TABLE (table), ddisp->canvas, 1, 2, 1, 2,
461 GTK_EXPAND | GTK_SHRINK | GTK_FILL,
462 GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
463 gtk_table_attach (GTK_TABLE (table), ddisp->hsb, 0, 2, 2, 3,
464 GTK_EXPAND | GTK_SHRINK | GTK_FILL, GTK_FILL, 0, 0);
465 gtk_table_attach (GTK_TABLE (table), ddisp->vsb, 2, 3, 0, 2,
466 GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
467 gtk_table_attach (GTK_TABLE (table), navigation_button, 2, 3, 2, 3,
468 GTK_FILL, GTK_FILL, 0, 0);
470 menus_get_image_menu (NULL, &ddisp->accel_group);
471 if (top_level_window)
472 gtk_window_add_accel_group(GTK_WINDOW(ddisp->shell), ddisp->accel_group);
473 if (use_mbar)
475 GString *path;
476 char *display = "<DisplayMBar>";
478 menus_get_image_menubar(&ddisp->menu_bar, &ddisp->mbar_item_factory);
479 gtk_box_pack_start (GTK_BOX (root_vbox), ddisp->menu_bar, FALSE, TRUE, 0);
481 path = g_string_new (display);
482 g_string_append (path,"/View/Show Rulers");
483 ddisp->rulers = menus_get_item_from_path(path->str, ddisp->mbar_item_factory);
484 g_string_append (g_string_assign(path, display),"/View/Show Grid");
485 ddisp->visible_grid = menus_get_item_from_path(path->str, ddisp->mbar_item_factory);
486 g_string_append (g_string_assign(path, display),"/View/Snap To Grid");
487 ddisp->snap_to_grid = menus_get_item_from_path(path->str, ddisp->mbar_item_factory);
488 g_string_append (g_string_assign(path, display),"/View/Show Connection Points");
489 ddisp->show_cx_pts_mitem = menus_get_item_from_path(path->str, ddisp->mbar_item_factory);
491 #ifdef HAVE_LIBART
492 g_string_append (g_string_assign(path, display),"/View/AntiAliased");
493 ddisp->antialiased = menus_get_item_from_path(path->str, ddisp->mbar_item_factory);
494 #endif
496 menus_initialize_updatable_items (&ddisp->updatable_menu_items, ddisp->mbar_item_factory, display);
497 g_string_free (path,FALSE);
500 /* the statusbars */
501 status_hbox = gtk_hbox_new (FALSE, 2);
504 g_signal_connect(GTK_OBJECT(ddisp->origin), "button_press_event",
505 G_CALLBACK(origin_button_press), ddisp);
508 /* Zoom status pseudo-optionmenu */
509 ddisp->zoom_status = create_zoom_widget(ddisp);
510 zoom_hbox = gtk_hbox_new(FALSE, 0);
511 zoom_label = gtk_label_new(_("Zoom"));
512 gtk_box_pack_start (GTK_BOX(zoom_hbox), zoom_label,
513 FALSE, FALSE, 0);
514 gtk_box_pack_start (GTK_BOX(zoom_hbox), ddisp->zoom_status,
515 FALSE, FALSE, 0);
517 gtk_box_pack_start (GTK_BOX (status_hbox), zoom_hbox, FALSE, FALSE, 0);
519 /* Grid on/off button */
520 ddisp->grid_status = dia_toggle_button_new_with_images("on-grid.png", "off-grid.png");
522 g_signal_connect(G_OBJECT(ddisp->grid_status), "toggled",
523 grid_toggle_snap, ddisp);
524 gtk_tooltips_set_tip(tool_tips, ddisp->grid_status,
525 _("Toggles snap-to-grid for this window."), NULL);
526 gtk_box_pack_start (GTK_BOX (status_hbox), ddisp->grid_status,
527 FALSE, FALSE, 0);
529 /* Statusbar */
530 ddisp->modified_status = gtk_statusbar_new ();
532 gtk_box_pack_start (GTK_BOX (status_hbox), ddisp->modified_status,
533 TRUE, TRUE, 0);
535 gtk_table_attach (GTK_TABLE (table), status_hbox, 0, 3, 3, 4,
536 GTK_FILL, GTK_FILL, 0, 0);
538 gtk_widget_show (ddisp->hsb);
539 gtk_widget_show (ddisp->vsb);
540 gtk_widget_show (ddisp->origin);
541 gtk_widget_show (ddisp->hrule);
542 gtk_widget_show (ddisp->vrule);
543 gtk_widget_show (ddisp->zoom_status);
544 gtk_widget_show (zoom_hbox);
545 gtk_widget_show (zoom_label);
546 gtk_widget_show (ddisp->grid_status);
547 gtk_widget_show (ddisp->modified_status);
548 gtk_widget_show (status_hbox);
549 gtk_widget_show (table);
550 if (use_mbar)
552 gtk_widget_show (ddisp->menu_bar);
553 gtk_widget_show (root_vbox);
555 gtk_widget_show (ddisp->shell);
557 /* before showing up, checking canvas's REAL size */
558 if (use_mbar && ddisp->hrule->allocation.width > width)
560 /* The menubar is not shrinkable, so the shell will have at least
561 * the menubar's width. If the diagram's requested width is smaller,
562 * the canvas will be enlarged to fit the place. In this case, we
563 * need to adjust the horizontal scrollbar according to the size
564 * that will be allocated, which the same as the hrule got.
567 width = ddisp->hrule->allocation.width;
569 ddisp->hsbdata->upper = width;
570 ddisp->hsbdata->page_increment = (width - 1) / 4;
571 ddisp->hsbdata->page_size = width - 1;
573 gtk_adjustment_changed (GTK_ADJUSTMENT(ddisp->hsbdata));
575 gtk_widget_show (ddisp->canvas);
577 /* set the focus to the canvas area */
578 gtk_widget_grab_focus (ddisp->canvas);
581 void
582 tool_select_update (GtkWidget *w,
583 gpointer data)
585 ToolButtonData *tooldata = (ToolButtonData *) data;
587 if (tooldata == NULL) {
588 g_warning(_("NULL tooldata in tool_select_update"));
589 return;
592 if (tooldata->type != -1) {
593 gint x, y;
594 GdkModifierType mask;
595 /* get the modifiers */
596 gdk_window_get_pointer (gtk_widget_get_parent_window(w), &x, &y, &mask);
597 tool_select (tooldata->type, tooldata->extra_data, tooldata->user_data,
598 w, mask&1);
602 static gint
603 tool_button_press (GtkWidget *w,
604 GdkEventButton *event,
605 gpointer data)
607 ToolButtonData *tooldata = (ToolButtonData *) data;
609 if ((event->type == GDK_2BUTTON_PRESS) &&
610 (event->button == 1)) {
611 tool_options_dialog_show (tooldata->type, tooldata->extra_data,
612 tooldata->user_data, w, event->state&1);
613 return TRUE;
616 return FALSE;
619 static void
620 tool_drag_data_get (GtkWidget *widget, GdkDragContext *context,
621 GtkSelectionData *selection_data, guint info,
622 guint32 time, ToolButtonData *tooldata)
624 if (info == 0) {
625 gtk_selection_data_set(selection_data, selection_data->target,
626 8, (guchar *)&tooldata, sizeof(ToolButtonData *));
630 static void
631 tool_setup_drag_source(GtkWidget *button, ToolButtonData *tooldata,
632 GdkPixmap *pixmap, GdkBitmap *mask)
634 g_return_if_fail(tooldata->type == CREATE_OBJECT_TOOL);
636 gtk_drag_source_set(button, GDK_BUTTON1_MASK,
637 create_object_targets, 1,
638 GDK_ACTION_DEFAULT|GDK_ACTION_COPY);
639 g_signal_connect(GTK_OBJECT(button), "drag_data_get",
640 G_CALLBACK(tool_drag_data_get), tooldata);
641 if (pixmap)
642 gtk_drag_source_set_icon(button, gtk_widget_get_colormap(button),
643 pixmap, mask);
647 void
648 tool_select_callback(GtkWidget *widget, gpointer data) {
649 ToolButtonData *tooldata = (ToolButtonData *)data;
651 if (tooldata == NULL) {
652 g_warning("NULL tooldata in tool_select_callback");
653 return;
656 if (tooldata->type != -1) {
657 tool_select (tooldata->type, tooldata->extra_data,
658 tooldata->user_data,widget);
663 static void
664 create_tools(GtkWidget *parent)
666 GtkWidget *button;
667 GtkWidget *pixmapwidget;
668 GdkPixmap *pixmap;
669 GdkBitmap *mask;
670 GtkStyle *style;
671 char **pixmap_data;
672 int i;
674 for (i = 0; i < NUM_TOOLS; i++) {
675 tool_widgets[i] = button = gtk_radio_button_new (tool_group);
676 gtk_container_set_border_width (GTK_CONTAINER (button), 0);
677 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_HALF);
678 tool_group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
679 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
681 gtk_wrap_box_pack(GTK_WRAP_BOX(parent), button,
682 TRUE, TRUE, FALSE, TRUE);
684 if (tool_data[i].callback_data.type == MODIFY_TOOL) {
685 modify_tool_button = GTK_WIDGET(button);
688 if (tool_data[i].icon_data==NULL) {
689 DiaObjectType *type;
690 type =
691 object_get_type((char *)tool_data[i].callback_data.extra_data);
692 if (type == NULL)
693 pixmap_data = tool_data[0].icon_data;
694 else
695 pixmap_data = type->pixmap;
696 } else {
697 pixmap_data = tool_data[i].icon_data;
700 style = gtk_widget_get_style(button);
701 pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL,
702 gtk_widget_get_colormap(button), &mask,
703 &style->bg[GTK_STATE_NORMAL], pixmap_data);
705 pixmapwidget = gtk_pixmap_new(pixmap, mask);
707 /* GTKBUG:? padding changes */
708 gtk_misc_set_padding(GTK_MISC(pixmapwidget), 2, 2);
710 gtk_container_add (GTK_CONTAINER (button), pixmapwidget);
712 g_signal_connect (GTK_OBJECT (button), "clicked",
713 G_CALLBACK (tool_select_update),
714 &tool_data[i].callback_data);
716 g_signal_connect (GTK_OBJECT (button), "button_press_event",
717 G_CALLBACK (tool_button_press),
718 &tool_data[i].callback_data);
720 if (tool_data[i].callback_data.type == CREATE_OBJECT_TOOL)
721 tool_setup_drag_source(button, &tool_data[i].callback_data,
722 pixmap, mask);
724 gdk_pixmap_unref(pixmap);
725 if (mask) gdk_bitmap_unref(mask);
727 tool_data[i].callback_data.widget = button;
729 gtk_tooltips_set_tip (tool_tips, button,
730 gettext(tool_data[i].tool_desc), NULL);
732 gtk_widget_show (pixmapwidget);
733 gtk_widget_show (button);
737 static GtkWidget *sheet_option_menu;
738 static GtkWidget *sheet_menu;
739 static GtkWidget *sheet_wbox;
741 #if 0
742 static GtkWidget *
743 create_sheet_page(GtkWidget *parent, Sheet *sheet)
745 GSList *list;
746 SheetObject *sheet_obj;
747 GtkWidget *table;
748 GtkWidget *button;
749 GtkWidget *pixmapwidget;
750 GdkPixmap *pixmap;
751 GdkBitmap *mask;
752 ToolButtonData *data;
753 GtkStyle *style;
754 GtkWidget *scrolled_window;
755 int i;
756 int rows;
758 scrolled_window = gtk_scrolled_window_new(NULL, NULL);
759 gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(scrolled_window),
760 GTK_POLICY_AUTOMATIC,
761 GTK_POLICY_AUTOMATIC);
763 rows = ceil(g_slist_length(sheet->objects) / (double)COLUMNS);
764 if (rows<1)
765 rows = 1;
767 table = gtk_hwrap_box_new(FALSE);
768 gtk_wrap_box_set_aspect_ratio(GTK_WRAP_BOX(table), COLUMNS * 1.0 / rows);
769 gtk_wrap_box_set_justify(GTK_WRAP_BOX(table), GTK_JUSTIFY_TOP);
770 gtk_wrap_box_set_line_justify(GTK_WRAP_BOX(table), GTK_JUSTIFY_LEFT);
772 style = gtk_widget_get_style(parent);
774 i = 0;
775 list = sheet->objects;
776 while (list != NULL) {
777 sheet_obj = (SheetObject *) list->data;
780 if (sheet_obj->pixmap != NULL) {
781 pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL,
782 gtk_widget_get_colormap(parent), &mask,
783 &style->bg[GTK_STATE_NORMAL], sheet_obj->pixmap);
784 } else if (sheet_obj->pixmap_file != NULL) {
785 pixmap = gdk_pixmap_colormap_create_from_xpm(NULL,
786 gtk_widget_get_colormap(parent), &mask,
787 &style->bg[GTK_STATE_NORMAL], sheet_obj->pixmap_file);
788 } else {
789 DiaObjectType *type;
790 type = object_get_type(sheet_obj->object_type);
791 pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL,
792 gtk_widget_get_colormap(parent), &mask,
793 &style->bg[GTK_STATE_NORMAL], type->pixmap);
796 pixmapwidget = gtk_pixmap_new(pixmap, mask);
799 button = gtk_radio_button_new (tool_group);
800 gtk_container_set_border_width (GTK_CONTAINER (button), 0);
801 tool_group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
803 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
806 gtk_container_add (GTK_CONTAINER (button), pixmapwidget);
807 gtk_wrap_box_pack_wrapped(GTK_WRAP_BOX(table), button,
808 FALSE, TRUE, FALSE, sheet_obj->line_break);
810 /* This is a Memory leak, these can't be freed.
811 Doesn't matter much anyway... */
813 data = g_new(ToolButtonData, 1);
814 data->type = CREATE_OBJECT_TOOL;
815 data->extra_data = sheet_obj->object_type;
816 data->user_data = sheet_obj->user_data;
818 g_signal_connect (GTK_OBJECT (button), "clicked",
819 G_CALLBACK (tool_select_update),
820 data);
822 g_signal_connect (GTK_OBJECT (button), "button_press_event",
823 G_CALLBACK (tool_button_press),
824 data);
826 gtk_tooltips_set_tip (tool_tips, button,
827 gettext(sheet_obj->description), NULL);
829 list = g_slist_next(list);
830 i++;
833 gtk_widget_show(table);
834 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window), table);
836 return scrolled_window;
838 #endif
840 gchar *interface_current_sheet_name;
842 static void
843 fill_sheet_wbox(GtkWidget *menu_item, Sheet *sheet)
845 int rows;
846 GtkStyle *style;
847 GSList *tmp;
848 GtkWidget *first_button = NULL;
850 gtk_container_foreach(GTK_CONTAINER(sheet_wbox),
851 (GtkCallback)gtk_widget_destroy, NULL);
852 tool_group = gtk_radio_button_group(GTK_RADIO_BUTTON(tool_widgets[0]));
854 /* Remember sheet 'name' for 'Sheets and Objects' dialog */
855 interface_current_sheet_name = sheet->name;
857 /* set the aspect ratio on the wbox */
858 rows = ceil(g_slist_length(sheet->objects) / (double)COLUMNS);
859 if (rows<1) rows = 1;
860 gtk_wrap_box_set_aspect_ratio(GTK_WRAP_BOX(sheet_wbox),
861 COLUMNS * 1.0 / rows);
862 style = gtk_widget_get_style(sheet_wbox);
863 for (tmp = sheet->objects; tmp != NULL; tmp = tmp->next) {
864 SheetObject *sheet_obj = tmp->data;
865 GdkPixmap *pixmap = NULL;
866 GdkBitmap *mask = NULL;
867 GtkWidget *pixmapwidget;
868 GtkWidget *button;
869 ToolButtonData *data;
871 if (sheet_obj->pixmap != NULL) {
872 pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL,
873 gtk_widget_get_colormap(sheet_wbox), &mask,
874 &style->bg[GTK_STATE_NORMAL], sheet_obj->pixmap);
875 } else if (sheet_obj->pixmap_file != NULL) {
876 GdkPixbuf *pixbuf;
877 GError* gerror = NULL;
879 pixbuf = gdk_pixbuf_new_from_file(sheet_obj->pixmap_file, &gerror);
880 if (pixbuf != NULL) {
881 gdk_pixbuf_render_pixmap_and_mask(pixbuf, &pixmap, &mask, 1.0);
882 gdk_pixbuf_unref(pixbuf);
883 } else {
885 g_warning("failed to load pixbuf for file %s; cause=%s",
886 sheet_obj->pixmap_file,gerror?gerror->message:"[NULL]");
888 } else {
889 DiaObjectType *type;
890 type = object_get_type(sheet_obj->object_type);
891 pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL,
892 gtk_widget_get_colormap(sheet_wbox), &mask,
893 &style->bg[GTK_STATE_NORMAL], type->pixmap);
895 if (pixmap) {
896 pixmapwidget = gtk_pixmap_new(pixmap, mask);
897 gdk_pixmap_unref(pixmap);
898 if (mask) gdk_bitmap_unref(mask);
899 } else {
900 pixmapwidget = gtk_type_new(gtk_pixmap_get_type());
903 button = gtk_radio_button_new (tool_group);
904 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
905 gtk_container_set_border_width (GTK_CONTAINER (button), 0);
906 tool_group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
908 gtk_container_add (GTK_CONTAINER (button), pixmapwidget);
909 gtk_widget_show(pixmapwidget);
911 gtk_wrap_box_pack_wrapped(GTK_WRAP_BOX(sheet_wbox), button,
912 FALSE, TRUE, FALSE, TRUE, sheet_obj->line_break);
913 gtk_widget_show(button);
915 data = g_new(ToolButtonData, 1);
916 data->type = CREATE_OBJECT_TOOL;
917 data->extra_data = sheet_obj->object_type;
918 data->user_data = sheet_obj->user_data;
919 gtk_object_set_data_full(GTK_OBJECT(button), "Dia::ToolButtonData",
920 data, (GdkDestroyNotify)g_free);
921 if (first_button == NULL) first_button = button;
923 g_signal_connect (GTK_OBJECT (button), "clicked",
924 G_CALLBACK (tool_select_update), data);
925 g_signal_connect (GTK_OBJECT (button), "button_press_event",
926 G_CALLBACK (tool_button_press), data);
928 tool_setup_drag_source(button, data, pixmap, mask);
930 gtk_tooltips_set_tip (tool_tips, button,
931 gettext(sheet_obj->description), NULL);
933 /* If the selection is in the old sheet, steal it */
934 if (active_tool != NULL &&
935 active_tool->type == CREATE_OBJECT_TOOL &&
936 first_button != NULL)
937 gtk_signal_emit_by_name(GTK_OBJECT(first_button), "toggled",
938 GTK_BUTTON(first_button), NULL);
941 void
942 fill_sheet_menu(void)
944 GSList *tmp;
945 GtkWidget *activate = NULL;
946 int index = 0;
948 gtk_container_foreach(GTK_CONTAINER(sheet_menu),
949 (GtkCallback)gtk_widget_destroy, NULL);
950 gtk_widget_ref(sheet_menu);
951 gtk_option_menu_remove_menu(GTK_OPTION_MENU(sheet_option_menu));
952 gtk_container_add(GTK_CONTAINER(sheet_menu), gtk_tearoff_menu_item_new());
953 for (tmp = get_sheets_list(); tmp != NULL; tmp = tmp->next) {
954 Sheet *sheet = tmp->data;
955 GtkWidget *menuitem = NULL;
957 if (sheet->objects == NULL)
958 continue;
960 menuitem = gtk_menu_item_new_with_label(gettext(sheet->name));
961 g_signal_connect(GTK_OBJECT(menuitem), "activate",
962 G_CALLBACK(fill_sheet_wbox), sheet);
963 gtk_container_add(GTK_CONTAINER(sheet_menu), menuitem);
965 /* off by one with gtk_option_menu_<get/set>_history should start
966 * with 0 but it counts from one, gtk- or my-error ? --hb */
967 index++;
968 if (prefs.recent_sheet == index)
969 activate = menuitem;
971 gtk_option_menu_set_menu(GTK_OPTION_MENU(sheet_option_menu), sheet_menu);
972 gtk_widget_unref(sheet_menu);
974 if (activate)
976 gtk_option_menu_set_history(GTK_OPTION_MENU(sheet_option_menu), prefs.recent_sheet);
977 /* simple gtk_option_menu_set_history() isn't enough,
978 * cause we need fill_sheet_wbox to be called */
979 gtk_menu_item_activate(GTK_MENU_ITEM(activate));
981 gtk_widget_show_all(sheet_menu);
984 void
985 create_sheets(GtkWidget *parent)
987 GtkWidget *separator;
988 GtkWidget *label;
989 GtkWidget *swin;
991 separator = gtk_hseparator_new ();
992 /* add a bit of padding around the separator */
993 label = gtk_vbox_new(FALSE, 0);
994 gtk_box_pack_start(GTK_BOX(label), separator, TRUE, TRUE, 3);
995 gtk_widget_show(label);
997 gtk_wrap_box_pack_wrapped (GTK_WRAP_BOX(parent), label, TRUE,TRUE, FALSE,FALSE, TRUE);
998 gtk_widget_show(separator);
1000 sheet_option_menu = gtk_option_menu_new();
1001 gtk_widget_set_size_request(sheet_option_menu, 20, -1);
1002 sheet_menu = gtk_menu_new();
1003 gtk_option_menu_set_menu(GTK_OPTION_MENU(sheet_option_menu), sheet_menu);
1004 gtk_wrap_box_pack_wrapped(GTK_WRAP_BOX(parent), sheet_option_menu,
1005 TRUE, TRUE, FALSE, FALSE, TRUE);
1006 gtk_widget_show(sheet_option_menu);
1008 swin = gtk_scrolled_window_new(NULL, NULL);
1009 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swin),
1010 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1011 gtk_wrap_box_pack_wrapped(GTK_WRAP_BOX(parent), swin, TRUE, TRUE, TRUE, TRUE, TRUE);
1012 gtk_widget_show(swin);
1014 sheet_wbox = gtk_hwrap_box_new(FALSE);
1015 gtk_wrap_box_set_justify(GTK_WRAP_BOX(sheet_wbox), GTK_JUSTIFY_TOP);
1016 gtk_wrap_box_set_line_justify(GTK_WRAP_BOX(sheet_wbox), GTK_JUSTIFY_LEFT);
1017 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(swin), sheet_wbox);
1018 gtk_widget_show(sheet_wbox);
1020 fill_sheet_menu();
1023 static void
1024 create_color_area (GtkWidget *parent)
1026 GtkWidget *frame;
1027 GtkWidget *alignment;
1028 GtkWidget *col_area;
1029 GtkWidget *line_area;
1030 GdkPixmap *default_pixmap;
1031 GdkBitmap *default_mask;
1032 GdkPixmap *swap_pixmap;
1033 GdkBitmap *swap_mask;
1034 GtkStyle *style;
1035 GtkWidget *hbox;
1037 gtk_widget_ensure_style(parent);
1038 style = gtk_widget_get_style(parent);
1040 default_pixmap =
1041 gdk_pixmap_colormap_create_from_xpm_d(NULL,
1042 gtk_widget_get_colormap(parent), &default_mask,
1043 &style->bg[GTK_STATE_NORMAL], default_xpm);
1044 swap_pixmap =
1045 gdk_pixmap_colormap_create_from_xpm_d(NULL,
1046 gtk_widget_get_colormap(parent), &swap_mask,
1047 &style->bg[GTK_STATE_NORMAL], swap_xpm);
1049 frame = gtk_frame_new (NULL);
1050 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
1051 gtk_wrap_box_pack_wrapped(GTK_WRAP_BOX(parent), frame, TRUE, TRUE, FALSE, FALSE, TRUE);
1052 gtk_widget_realize (frame);
1054 hbox = gtk_hbox_new (FALSE, 1);
1055 gtk_container_set_border_width (GTK_CONTAINER (hbox), 0);
1056 gtk_container_add (GTK_CONTAINER (frame), hbox);
1058 /* Color area: */
1059 alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
1060 gtk_container_set_border_width (GTK_CONTAINER (alignment), 3);
1062 col_area = color_area_create (54, 42,
1063 default_pixmap, default_mask,
1064 swap_pixmap, swap_mask);
1065 gtk_container_add (GTK_CONTAINER (alignment), col_area);
1068 gtk_box_pack_start (GTK_BOX (hbox), alignment, TRUE, TRUE, 0);
1070 gtk_tooltips_set_tip (tool_tips, col_area,
1071 _("Foreground & background colors for new objects. "
1072 "The small black and white squares reset colors. "
1073 "The small arrows swap colors. Double click to "
1074 "change colors."),
1075 NULL);
1077 gtk_widget_show (alignment);
1079 /* Linewidth area: */
1080 alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
1081 gtk_container_set_border_width (GTK_CONTAINER (alignment), 3);
1083 line_area = linewidth_area_create ();
1084 gtk_container_add (GTK_CONTAINER (alignment), line_area);
1085 gtk_box_pack_start (GTK_BOX (hbox), alignment, TRUE, TRUE, 0);
1086 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);
1087 gtk_widget_show (alignment);
1089 gtk_widget_show (col_area);
1090 gtk_widget_show (line_area);
1091 gtk_widget_show (hbox);
1092 gtk_widget_show (frame);
1095 static void
1096 change_start_arrow_style(Arrow arrow, gpointer user_data)
1098 attributes_set_default_start_arrow(arrow);
1100 static void
1101 change_end_arrow_style(Arrow arrow, gpointer user_data)
1103 attributes_set_default_end_arrow(arrow);
1105 static void
1106 change_line_style(LineStyle lstyle, real dash_length, gpointer user_data)
1108 attributes_set_default_line_style(lstyle, dash_length);
1111 static void
1112 create_lineprops_area(GtkWidget *parent)
1114 GtkWidget *chooser;
1115 Arrow arrow;
1116 real dash_length;
1117 LineStyle style;
1119 chooser = dia_arrow_chooser_new(TRUE, change_start_arrow_style, NULL, tool_tips);
1120 gtk_wrap_box_pack_wrapped(GTK_WRAP_BOX(parent), chooser, FALSE, TRUE, FALSE, TRUE, TRUE);
1121 arrow.width = persistence_register_real("start-arrow-width", DEFAULT_ARROW_WIDTH);
1122 arrow.length = persistence_register_real("start-arrow-length", DEFAULT_ARROW_LENGTH);
1123 arrow.type = arrow_type_from_name(persistence_register_string("start-arrow-type", "None"));
1124 dia_arrow_chooser_set_arrow(DIA_ARROW_CHOOSER(chooser), &arrow);
1125 attributes_set_default_start_arrow(arrow);
1126 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);
1127 gtk_widget_show(chooser);
1129 chooser = dia_line_chooser_new(change_line_style, NULL);
1130 gtk_wrap_box_pack(GTK_WRAP_BOX(parent), chooser, TRUE, TRUE, FALSE, TRUE);
1131 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);
1132 style = persistence_register_integer("line-style", LINESTYLE_SOLID);
1133 dash_length = persistence_register_real("dash-length", DEFAULT_LINESTYLE_DASHLEN);
1134 dia_line_chooser_set_line_style(DIA_LINE_CHOOSER(chooser), style, dash_length);
1135 gtk_widget_show(chooser);
1137 chooser = dia_arrow_chooser_new(FALSE, change_end_arrow_style, NULL, tool_tips);
1138 arrow.width = persistence_register_real("end-arrow-width", DEFAULT_ARROW_WIDTH);
1139 arrow.length = persistence_register_real("end-arrow-length", DEFAULT_ARROW_LENGTH);
1140 arrow.type = arrow_type_from_name(persistence_register_string("end-arrow-type", "Filled Concave"));
1141 dia_arrow_chooser_set_arrow(DIA_ARROW_CHOOSER(chooser), &arrow);
1142 attributes_set_default_end_arrow(arrow);
1144 gtk_wrap_box_pack(GTK_WRAP_BOX(parent), chooser, FALSE, TRUE, FALSE, TRUE);
1145 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);
1146 gtk_widget_show(chooser);
1149 static void
1150 toolbox_destroy (GtkWidget *widget, gpointer data)
1152 prefs.recent_sheet = gtk_option_menu_get_history(GTK_OPTION_MENU(sheet_option_menu));
1154 app_exit();
1157 static gboolean
1158 toolbox_delete (GtkWidget *widget, GdkEvent *event, gpointer data)
1160 if (!app_is_embedded()) {
1161 gulong handlerid;
1162 /** Stop toolbox_destroy from being called */
1163 handlerid = g_signal_handler_find(widget, G_SIGNAL_MATCH_FUNC,
1164 0, 0, NULL, toolbox_destroy, NULL);
1165 if (handlerid != 0)
1166 g_signal_handler_disconnect (GTK_OBJECT (widget), handlerid);
1167 prefs.recent_sheet = gtk_option_menu_get_history(GTK_OPTION_MENU(sheet_option_menu));
1169 /** If the app didn't exit, don't close the window */
1170 return (!app_exit());
1175 /* HB: file dnd stuff lent by The Gimp, not fully understood but working ...
1177 enum
1179 DIA_DND_TYPE_URI_LIST,
1180 DIA_DND_TYPE_TEXT_PLAIN,
1183 static GtkTargetEntry toolbox_target_table[] =
1185 { "text/uri-list", 0, DIA_DND_TYPE_URI_LIST },
1186 { "text/plain", 0, DIA_DND_TYPE_TEXT_PLAIN }
1189 static guint toolbox_n_targets = (sizeof (toolbox_target_table) /
1190 sizeof (toolbox_target_table[0]));
1192 static void
1193 dia_dnd_file_drag_data_received (GtkWidget *widget,
1194 GdkDragContext *context,
1195 gint x,
1196 gint y,
1197 GtkSelectionData *data,
1198 guint info,
1199 guint time)
1201 switch (context->action)
1203 case GDK_ACTION_DEFAULT:
1204 case GDK_ACTION_COPY:
1205 case GDK_ACTION_MOVE:
1206 case GDK_ACTION_LINK:
1207 case GDK_ACTION_ASK:
1208 default:
1210 Diagram *diagram = NULL;
1211 DDisplay *ddisp;
1212 gchar *sPath = NULL, *pFrom, *pTo;
1214 pFrom = strstr((gchar *) data->data, "file:");
1215 while (pFrom) {
1216 GError *error = NULL;
1218 pTo = pFrom;
1219 while (*pTo != 0 && *pTo != 0xd && *pTo != 0xa) pTo ++;
1220 sPath = g_strndup(pFrom, pTo - pFrom);
1222 /* format changed with Gtk+2.0, use conversion */
1223 pFrom = g_filename_from_uri (sPath, NULL, &error);
1224 diagram = diagram_load (pFrom, NULL);
1225 g_free (pFrom);
1226 g_free(sPath);
1228 if (diagram != NULL) {
1229 diagram_update_extents(diagram);
1230 layer_dialog_set_diagram(diagram);
1232 ddisp = new_display(diagram);
1235 pFrom = strstr(pTo, "file:");
1236 } /* while */
1237 gtk_drag_finish (context, TRUE, FALSE, time);
1239 break;
1241 return;
1244 void
1245 create_toolbox ()
1247 GtkWidget *window;
1248 GtkWidget *main_vbox;
1249 GtkWidget *wrapbox;
1250 GtkWidget *menubar;
1251 GtkAccelGroup *accel_group;
1252 GdkPixbuf *pixbuf;
1254 #ifdef GNOME
1255 window = gnome_app_new ("Dia", _("Diagram Editor"));
1256 #else
1257 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1258 gtk_widget_ref (window);
1259 gtk_window_set_title (GTK_WINDOW (window), "Dia v" VERSION);
1260 #endif
1261 gtk_window_set_role (GTK_WINDOW (window), "toolbox_window");
1262 gtk_window_set_default_size(GTK_WINDOW(window), 146, 349);
1264 pixbuf = gdk_pixbuf_new_from_inline (-1, dia_app_icon, FALSE, NULL);
1265 if (pixbuf) {
1266 gtk_window_set_icon (GTK_WINDOW (window), pixbuf);
1267 g_object_unref (pixbuf);
1270 g_signal_connect (GTK_OBJECT (window), "delete_event",
1271 G_CALLBACK (toolbox_delete),
1272 window);
1274 g_signal_connect (GTK_OBJECT (window), "destroy",
1275 G_CALLBACK (toolbox_destroy),
1276 window);
1278 main_vbox = gtk_vbox_new (FALSE, 1);
1279 gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 1);
1280 #ifdef GNOME
1281 gnome_app_set_contents(GNOME_APP(window), main_vbox);
1282 #else
1283 gtk_container_add (GTK_CONTAINER (window), main_vbox);
1284 #endif
1285 gtk_widget_show (main_vbox);
1287 /* tooltips */
1288 tool_tips = gtk_tooltips_new ();
1290 /* gtk_tooltips_set_colors (tool_tips,
1291 &colors[11],
1292 &main_vbox->style->fg[GTK_STATE_NORMAL]);*/
1294 wrapbox = gtk_hwrap_box_new(FALSE);
1295 gtk_wrap_box_set_aspect_ratio(GTK_WRAP_BOX(wrapbox), 144.0 / 318.0);
1296 gtk_wrap_box_set_justify(GTK_WRAP_BOX(wrapbox), GTK_JUSTIFY_TOP);
1297 gtk_wrap_box_set_line_justify(GTK_WRAP_BOX(wrapbox), GTK_JUSTIFY_LEFT);
1300 /* pack the rest of the stuff */
1301 gtk_box_pack_end (GTK_BOX (main_vbox), wrapbox, TRUE, TRUE, 0);
1302 gtk_container_set_border_width (GTK_CONTAINER (wrapbox), 0);
1303 gtk_widget_show (wrapbox);
1305 create_tools (wrapbox);
1306 create_sheets (wrapbox);
1307 create_color_area (wrapbox);
1308 create_lineprops_area (wrapbox);
1310 /* Setup toolbox area as file drop destination */
1311 gtk_drag_dest_set (wrapbox,
1312 GTK_DEST_DEFAULT_ALL,
1313 toolbox_target_table, toolbox_n_targets,
1314 GDK_ACTION_COPY);
1315 g_signal_connect (GTK_OBJECT (wrapbox), "drag_data_received",
1316 G_CALLBACK (dia_dnd_file_drag_data_received),
1317 wrapbox);
1319 /* menus -- initialised afterwards, because initing the display menus
1320 * uses the tool buttons*/
1321 menus_get_toolbox_menubar(&menubar, &accel_group);
1322 gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
1323 #ifdef GNOME
1324 gnome_app_set_menus(GNOME_APP(window), GTK_MENU_BAR(menubar));
1325 #else
1326 gtk_box_pack_start (GTK_BOX (main_vbox), menubar, FALSE, TRUE, 0);
1327 gtk_widget_show (menubar);
1328 #endif
1329 persistence_register_window(GTK_WINDOW(window));
1331 toolbox_shell = window;
1334 void
1335 toolbox_show(void)
1337 gtk_widget_show(toolbox_shell);
1340 void
1341 toolbox_hide(void)
1343 gtk_widget_hide(toolbox_shell);
1346 void
1347 create_tree_window(void)
1349 GtkCheckMenuItem *item = GTK_CHECK_MENU_ITEM
1350 (menus_get_item_from_path("<Toolbox>/File/Diagram tree", NULL));
1351 create_diagram_tree_window(&prefs.dia_tree, GTK_WIDGET(item));
1354 GtkWidget *
1355 interface_get_toolbox_shell(void)
1357 return toolbox_shell;