more leaks plugged and more *_OPTIONAL
[dia.git] / app / commands.c
blob4168537dd149a250b2ff4cab4a05125c024fe9fc
1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 #include <config.h>
20 #ifdef HAVE_UNISTD_H
21 # include <unistd.h>
22 #endif
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <math.h>
29 #include <glib.h>
31 #include <gdk-pixbuf/gdk-pixbuf.h>
32 #include <gtk/gtk.h>
34 /* Added by Andrew Ferrier: for use of gnome_about_new() */
36 #ifdef GNOME
37 # include <gnome.h>
38 #endif
40 #ifdef G_OS_WIN32
42 * Instead of polluting the Dia namespace with windoze headers, declare the
43 * required prototype here. This is bad style, but not as bad as namespace
44 * clashes to be resolved without C++ --hb
46 long __stdcall
47 ShellExecuteA (long hwnd,
48 const char* lpOperation,
49 const char* lpFile,
50 const char* lpParameters,
51 const char* lpDirectory,
52 int nShowCmd);
53 #endif
55 #include "paginate_psprint.h"
56 #ifdef G_OS_WIN32
57 # include "paginate_gdiprint.h"
58 #endif
59 #include "intl.h"
60 #include "commands.h"
61 #include "app_procs.h"
62 #include "diagram.h"
63 #include "display.h"
64 #include "object_ops.h"
65 #include "cut_n_paste.h"
66 #include "load_save.h"
67 #include "utils.h"
68 #include "message.h"
69 #include "grid.h"
70 #include "properties.h"
71 #include "propinternals.h"
72 #include "preferences.h"
73 #include "layer_dialog.h"
74 #include "connectionpoint_ops.h"
75 #include "undo.h"
76 #include "pagesetup.h"
77 #include "text.h"
78 #include "dia_dirs.h"
79 #include "focus.h"
80 #include "gdk/gdk.h"
81 #include "gdk/gdkkeysyms.h"
82 #include "lib/properties.h"
83 #include "dia-props.h"
84 #include "diagram_tree_window.h"
85 #include "authors.h" /* master contributors data */
87 GdkPixbuf *logo;
89 void file_quit_callback(gpointer data, guint action, GtkWidget *widget)
91 app_exit();
94 void
95 file_pagesetup_callback(gpointer data, guint action, GtkWidget *widget)
97 Diagram *dia;
99 dia = ddisplay_active()->diagram;
100 create_page_setup_dlg(dia);
103 void
104 file_print_callback(gpointer data, guint action, GtkWidget *widget)
106 Diagram *dia;
108 dia = ddisplay_active()->diagram;
109 #ifdef G_OS_WIN32
110 /* This option could be used with Gnome too. Does it make sense there ? */
111 if (!prefs.prefer_psprint)
112 diagram_print_gdi(dia);
113 else
114 #endif
115 diagram_print_ps(dia);
118 void
119 file_close_callback(gpointer data, guint action, GtkWidget *widget)
121 ddisplay_close(ddisplay_active());
124 void
125 file_new_callback(gpointer data, guint action, GtkWidget *widget)
127 Diagram *dia;
128 DDisplay *ddisp;
129 static int untitled_nr = 1;
130 char buffer[24];
132 g_snprintf(buffer, 24, _("Diagram%d.dia"), untitled_nr++);
134 dia = new_diagram(buffer);
135 ddisp = new_display(dia);
136 diagram_tree_add(diagram_tree(), dia);
139 void
140 file_preferences_callback(gpointer data, guint action, GtkWidget *widget)
142 prefs_show();
146 void
147 edit_copy_callback(gpointer data, guint action, GtkWidget *widget)
149 GList *copy_list;
150 DDisplay *ddisp;
152 ddisp = ddisplay_active();
153 copy_list = parent_list_affected(diagram_get_sorted_selected(ddisp->diagram));
155 cnp_store_objects(object_copy_list(copy_list));
156 g_list_free(copy_list);
158 ddisplay_do_update_menu_sensitivity(ddisp);
161 void
162 edit_cut_callback(gpointer data, guint action, GtkWidget *widget)
164 GList *cut_list;
165 DDisplay *ddisp;
166 Change *change;
168 ddisp = ddisplay_active();
170 diagram_selected_break_external(ddisp->diagram);
172 cut_list = parent_list_affected(diagram_get_sorted_selected(ddisp->diagram));
174 cnp_store_objects(object_copy_list(cut_list));
176 change = undo_delete_objects_children(ddisp->diagram, cut_list);
177 (change->apply)(change, ddisp->diagram);
179 ddisplay_do_update_menu_sensitivity(ddisp);
180 diagram_flush(ddisp->diagram);
183 diagram_modified(ddisp->diagram);
184 undo_set_transactionpoint(ddisp->diagram->undo);
188 void
189 edit_paste_callback(gpointer data, guint action, GtkWidget *widget)
191 GList *paste_list;
192 DDisplay *ddisp;
193 Point paste_corner;
194 Point delta;
195 Change *change;
197 ddisp = ddisplay_active();
199 if (!cnp_exist_stored_objects()) {
200 message_warning(_("No existing object to paste.\n"));
201 return;
204 paste_list = cnp_get_stored_objects(); /* Gets a copy */
206 paste_corner = object_list_corner(paste_list);
208 delta.x = ddisp->visible.left - paste_corner.x;
209 delta.y = ddisp->visible.top - paste_corner.y;
211 /* Move down some 10% of the visible area. */
212 delta.x += (ddisp->visible.right - ddisp->visible.left)*0.1;
213 delta.y += (ddisp->visible.bottom - ddisp->visible.top)*0.1;
215 object_list_move_delta(paste_list, &delta);
217 change = undo_insert_objects(ddisp->diagram, paste_list, 0);
218 (change->apply)(change, ddisp->diagram);
220 diagram_modified(ddisp->diagram);
221 undo_set_transactionpoint(ddisp->diagram->undo);
223 diagram_remove_all_selected(ddisp->diagram, TRUE);
224 diagram_select_list(ddisp->diagram, paste_list);
226 diagram_flush(ddisp->diagram);
229 /* Signal handler for getting the clipboard contents */
230 /* Note that the clipboard is for M$-style cut/copy/paste copying, while
231 the selection is for Unix-style mark-and-copy. We can't really do
232 mark-and-copy.
235 static void
236 insert_text(DDisplay *ddisp, Focus *focus, const gchar *text)
238 ObjectChange *change = NULL;
239 int modified = FALSE, any_modified = FALSE;
240 Object *obj = focus->obj;
242 while (text != NULL) {
243 gchar *next_line = g_utf8_strchr(text, -1, '\n');
244 if (next_line != text) {
245 gint len = g_utf8_strlen(text, (next_line-text));
246 modified = (*focus->key_event)(focus, GDK_A, text, len, &change);
248 if (next_line != NULL) {
249 modified = (*focus->key_event)(focus, GDK_Return, "\n", 1, &change);
250 text = g_utf8_next_char(next_line);
251 } else {
252 text = NULL;
254 { /* Make sure object updates its data: */
255 Point p = obj->position;
256 (obj->ops->move)(obj,&p); }
258 /* Perhaps this can be improved */
259 object_add_updates(obj, ddisp->diagram);
261 if (modified && (change != NULL)) {
262 undo_object_change(ddisp->diagram, obj, change);
263 any_modified = TRUE;
266 diagram_flush(ddisp->diagram);
269 if (any_modified)
270 undo_set_transactionpoint(ddisp->diagram->undo);
274 static void
275 received_clipboard_handler(GtkClipboard *clipboard,
276 const gchar *text,
277 gpointer data) {
278 Focus *focus = active_focus();
279 DDisplay *ddisp = (DDisplay *)data;
281 if (text == NULL) return;
283 if ((focus == NULL) || (!focus->has_focus)) return;
285 if (!g_utf8_validate(text, -1, NULL)) {
286 message_error("Not valid UTF8");
287 return;
290 insert_text(ddisp, focus, text);
293 static PropDescription text_prop_singleton_desc[] = {
294 { "text", PROP_TYPE_TEXT },
295 PROP_DESC_END};
297 static void
298 make_text_prop_singleton(GPtrArray **props, TextProperty **prop)
300 *props = prop_list_from_descs(text_prop_singleton_desc,pdtpp_true);
301 g_assert((*props)->len == 1);
303 *prop = g_ptr_array_index((*props),0);
304 g_free((*prop)->text_data);
305 (*prop)->text_data = NULL;
309 void
310 edit_copy_text_callback(gpointer data, guint action, GtkWidget *widget)
312 Focus *focus = active_focus();
313 DDisplay *ddisp;
314 Object *obj;
315 GPtrArray *textprops;
316 TextProperty *prop;
318 if ((focus == NULL) || (!focus->has_focus)) return;
320 ddisp = ddisplay_active();
322 obj = focus->obj;
324 if (obj->ops->get_props == NULL)
325 return;
327 make_text_prop_singleton(&textprops,&prop);
328 /* Get the first text property */
329 obj->ops->get_props(obj, textprops);
331 /* GTK docs claim the selection clipboard is ignored on Win32.
332 * The "clipboard" clipboard is mostly ignored in Unix
334 #ifdef G_OS_WIN32
335 gtk_clipboard_set_text(gtk_clipboard_get(GDK_NONE),
336 prop->text_data, -1);
337 #else
338 gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY),
339 prop->text_data, -1);
340 #endif
341 prop_list_free(textprops);
344 void
345 edit_cut_text_callback(gpointer data, guint action, GtkWidget *widget)
347 Focus *focus = active_focus();
348 DDisplay *ddisp;
349 Object *obj;
350 Text *text;
351 GPtrArray *textprops;
352 TextProperty *prop;
353 ObjectChange *change;
355 if ((focus == NULL) || (!focus->has_focus)) return;
357 ddisp = ddisplay_active();
359 obj = focus->obj;
360 text = (Text *)focus->user_data;
362 if (obj->ops->get_props == NULL)
363 return;
365 make_text_prop_singleton(&textprops,&prop);
366 /* Get the first text property */
367 obj->ops->get_props(obj, textprops);
369 /* GTK docs claim the selection clipboard is ignored on Win32.
370 * The "clipboard" clipboard is mostly ignored in Unix
372 #ifdef G_OS_WIN32
373 gtk_clipboard_set_text(gtk_clipboard_get(GDK_NONE),
374 prop->text_data, -1);
375 #else
376 gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY),
377 prop->text_data, -1);
378 #endif
380 prop_list_free(textprops);
382 if (text_delete_all(text, &change)) {
383 object_add_updates(obj, ddisp->diagram);
384 undo_object_change(ddisp->diagram, obj, change);
385 undo_set_transactionpoint(ddisp->diagram->undo);
386 diagram_flush(ddisp->diagram);
390 void
391 edit_paste_text_callback(gpointer data, guint action, GtkWidget *widget)
393 DDisplay *ddisp;
395 ddisp = ddisplay_active();
397 #ifdef G_OS_WIN32
398 gtk_clipboard_request_text(gtk_clipboard_get(GDK_NONE),
399 received_clipboard_handler, ddisp);
400 #else
401 gtk_clipboard_request_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY),
402 received_clipboard_handler, ddisp);
403 #endif
406 void
407 edit_delete_callback(gpointer data, guint action, GtkWidget *widget)
409 GList *delete_list;
410 GList *ptr;
411 DDisplay *ddisp;
413 Change *change;
415 ddisp = ddisplay_active();
417 diagram_selected_break_external(ddisp->diagram);
419 delete_list = diagram_get_sorted_selected(ddisp->diagram);
420 change = undo_delete_objects_children(ddisp->diagram, delete_list);
421 (change->apply)(change, ddisp->diagram);
423 diagram_modified(ddisp->diagram);
425 ddisplay_do_update_menu_sensitivity(ddisp);
426 diagram_flush(ddisp->diagram);
428 undo_set_transactionpoint(ddisp->diagram->undo);
431 void
432 edit_undo_callback(gpointer data, guint action, GtkWidget *widget)
434 DDisplay *ddisp;
435 Diagram *dia;
437 ddisp = ddisplay_active();
438 dia = ddisp->diagram;
440 undo_revert_to_last_tp(dia->undo);
442 diagram_flush(dia);
445 void
446 edit_redo_callback(gpointer data, guint action, GtkWidget *widget)
448 DDisplay *ddisp;
449 Diagram *dia;
451 ddisp = ddisplay_active();
452 dia = ddisp->diagram;
454 undo_apply_to_next_tp(dia->undo);
456 diagram_flush(dia);
459 void
460 help_manual_callback(gpointer data, guint action, GtkWidget *widget)
462 char *helpdir, *helpindex = NULL, *command;
463 guint bestscore = G_MAXINT;
464 GDir *dp;
465 const char *dentry;
466 GError *error = NULL;
468 helpdir = dia_get_data_directory("help");
469 if (!helpdir) {
470 message_warning(_("Could not find help directory"));
471 return;
474 /* search through helpdir for the helpfile that matches the user's locale */
475 dp = g_dir_open (helpdir, 0, &error);
476 if (!dp) {
477 message_warning(_("Could not open help directory:\n%s"),
478 error->message);
479 g_error_free (error);
480 return;
483 while ((dentry = g_dir_read_name(dp)) != NULL) {
484 guint score;
486 score = intl_score_locale(dentry);
487 if (score < bestscore) {
488 if (helpindex)
489 g_free(helpindex);
490 #ifdef G_OS_WIN32
491 /* use HTML Help on win32 if available */
492 helpindex = g_strconcat(helpdir, G_DIR_SEPARATOR_S, dentry,
493 G_DIR_SEPARATOR_S "dia-manual.chm", NULL);
494 if (!g_file_test(helpindex, G_FILE_TEST_EXISTS)) {
495 helpindex = g_strconcat(helpdir, G_DIR_SEPARATOR_S, dentry,
496 G_DIR_SEPARATOR_S "index.html", NULL);
498 #else
499 helpindex = g_strconcat(helpdir, G_DIR_SEPARATOR_S, dentry,
500 G_DIR_SEPARATOR_S "index.html", NULL);
501 #endif
502 bestscore = score;
505 g_dir_close (dp);
506 g_free(helpdir);
507 if (!helpindex) {
508 message_warning(_("Could not find help directory"));
509 return;
512 #ifdef G_OS_WIN32
513 #define SW_SHOWNORMAL 1
514 ShellExecuteA (0, "open", helpindex, NULL, helpdir, SW_SHOWNORMAL);
515 #else
516 command = getenv("BROWSER");
517 command = g_strdup_printf("%s 'file://%s' &", command ? command : "netscape", helpindex);
518 system(command);
519 g_free(command);
520 #endif
522 g_free(helpindex);
525 void
526 help_about_callback(gpointer data, guint action, GtkWidget *widget)
528 #ifdef GNOME
530 /* Take advantage of gnome_about_new(),
531 * which is much cleaner and GNOME2 HIG compliant,
532 * Originally implemented by Xing Wang, modified
533 * by Andrew Ferrier.
535 * Note: in this function there is no need to discriminate
536 * between the different kinds of 'authors'.
539 static GtkWidget *about;
542 * Translators should localize the following string
543 * which will give them credit in the About box.
544 * E.g. "Fulano de Tal <fulano@detal.com>"
547 gchar *translators = _("translator_credits-PLEASE_ADD_YOURSELF_HERE");
548 gchar logo_file[100];
550 if (!about) {
551 GdkPixbuf *logo;
553 gchar* datadir = dia_get_data_directory("");
554 g_snprintf(logo_file, sizeof(logo_file),
555 "%s%sdia_logo.png", datadir, G_DIR_SEPARATOR_S);
557 logo = gdk_pixbuf_new_from_file(logo_file, NULL);
558 g_free(datadir);
560 about = gnome_about_new(
561 _("Dia"),
562 VERSION,
563 _("Copyright (C) 1998-2002 The Free Software Foundation and the authors"),
564 _("Dia is a program for drawing structured diagrams.\n"
565 "Please visit http://www.lysator.liu.se/~alla/dia for more information."),
566 authors,
567 documentors,
568 (strcmp (translators, "translator_credits-PLEASE_ADD_YOURSELF_HERE")
569 ? translators : NULL),
570 logo);
572 if (logo)
573 g_object_unref (logo);
575 g_signal_connect (about, "destroy",
576 G_CALLBACK (gtk_widget_destroyed),
577 &about);
580 gtk_widget_show_now (about);
582 #else
584 /* No GNOME, fall back to the old GTK method */
586 const gint nauthors = (sizeof(authors) / sizeof(authors[0])) - 1;
587 const gint ndocumentors = (sizeof(documentors) / sizeof(documentors[0])) - 1;
589 GtkWidget *dialog;
590 GtkWidget *vbox;
591 GtkWidget *table;
592 GtkWidget *bbox;
593 GtkWidget *frame;
594 GtkWidget *label;
595 GtkWidget *button;
596 char str[100];
597 gint i;
599 GtkWidget *gpixmap;
601 dialog = gtk_dialog_new ();
602 gtk_window_set_role (GTK_WINDOW (dialog), "about_dialog");
603 gtk_window_set_title (GTK_WINDOW (dialog), _("About Dia"));
604 gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
605 gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
606 g_signal_connect (GTK_OBJECT (dialog), "destroy",
607 G_CALLBACK (gtk_widget_destroy),
608 GTK_OBJECT (dialog));
610 vbox = gtk_vbox_new (FALSE, 1);
611 gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
612 gtk_container_add (GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), vbox);
614 if (!logo) {
615 gchar* datadir = dia_get_data_directory("");
616 g_snprintf(str, sizeof(str), "%s%sdia_logo.png", datadir, G_DIR_SEPARATOR_S);
617 logo = gdk_pixbuf_new_from_file(str, NULL);
618 g_free(datadir);
621 if (logo) {
622 GdkPixmap *pixmap;
623 GdkBitmap *bitmap;
625 frame = gtk_frame_new (NULL);
626 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
627 gtk_container_set_border_width (GTK_CONTAINER (frame), 1);
628 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, TRUE, 1);
630 gdk_pixbuf_render_pixmap_and_mask(logo, &pixmap, &bitmap, 128);
631 gpixmap = gtk_pixmap_new(pixmap, bitmap);
632 gdk_pixmap_unref(pixmap);
633 if (bitmap) gdk_bitmap_unref(bitmap);
634 gtk_container_add (GTK_CONTAINER(frame), gpixmap);
637 frame = gtk_frame_new (NULL);
638 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
639 gtk_container_set_border_width (GTK_CONTAINER (frame), 1);
640 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, TRUE, 1);
642 table = gtk_table_new(3, 2, FALSE);
643 gtk_container_set_border_width (GTK_CONTAINER (table), 1);
644 gtk_container_add (GTK_CONTAINER (frame), table);
646 g_snprintf(str, sizeof(str), _("Dia v %s by Alexander Larsson"), VERSION);
647 label = gtk_label_new (str);
648 gtk_table_attach(GTK_TABLE(table), label, 0,2, 0,1,
649 GTK_FILL|GTK_EXPAND, GTK_FILL, 0,2);
651 /* Exact spelling is Ch&eacute;p&eacute;lov (using *ML entities) */
652 label = gtk_label_new(_("Maintainers: Lars Clausen and Cyrille Chepelov"));
653 gtk_table_attach(GTK_TABLE(table), label, 0,2, 1,2,
654 GTK_FILL|GTK_EXPAND, GTK_FILL, 0,2);
656 label = gtk_label_new (_("Please visit http://www.lysator.liu.se/~alla/dia "
657 "for more information"));
658 gtk_table_attach(GTK_TABLE(table), label, 0,2, 2,3,
659 GTK_FILL|GTK_EXPAND, GTK_FILL, 0,2);
661 label = gtk_label_new (_("Contributors:"));
662 gtk_table_attach(GTK_TABLE(table), label, 0,2, 3,4,
663 GTK_FILL|GTK_EXPAND, GTK_FILL, 0,2);
665 for (i = 0; i < nauthors; i++) {
666 label = gtk_label_new(authors[i]);
667 gtk_table_attach(GTK_TABLE(table), label, i%2,i%2+1, i/2+4,i/2+5,
668 GTK_FILL|GTK_EXPAND, GTK_FILL, 0,0);
671 for (i = nauthors; i < nauthors + ndocumentors; i++) {
672 label = gtk_label_new(documentors[i - nauthors]);
673 gtk_table_attach(GTK_TABLE(table), label, i%2,i%2+1, i/2+4,i/2+5,
674 GTK_FILL|GTK_EXPAND, GTK_FILL, 0,0);
677 gtk_table_set_col_spacings(GTK_TABLE(table), 1);
678 gtk_table_set_row_spacings(GTK_TABLE(table), 1);
680 bbox = gtk_hbutton_box_new();
681 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), bbox, TRUE, TRUE, 5);
682 gtk_button_box_set_child_size(GTK_BUTTON_BOX(bbox), 80, 0);
683 gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 10);
685 button = gtk_button_new_from_stock(GTK_STOCK_OK);
686 gtk_container_add(GTK_CONTAINER(bbox), button);
687 g_signal_connect_swapped(GTK_OBJECT (button), "clicked",
688 G_CALLBACK(gtk_widget_destroy),
689 GTK_OBJECT(dialog));
691 gtk_widget_show_all (dialog);
693 #endif /* GNOME */
696 void
697 view_zoom_in_callback(gpointer data, guint action, GtkWidget *widget)
699 DDisplay *ddisp;
700 Point middle;
701 Rectangle *visible;
703 ddisp = ddisplay_active();
704 visible = &ddisp->visible;
705 middle.x = visible->left*0.5 + visible->right*0.5;
706 middle.y = visible->top*0.5 + visible->bottom*0.5;
708 ddisplay_zoom(ddisp, &middle, M_SQRT2);
711 void
712 view_zoom_out_callback(gpointer data, guint action, GtkWidget *widget)
714 DDisplay *ddisp;
715 Point middle;
716 Rectangle *visible;
718 ddisp = ddisplay_active();
719 visible = &ddisp->visible;
720 middle.x = visible->left*0.5 + visible->right*0.5;
721 middle.y = visible->top*0.5 + visible->bottom*0.5;
723 ddisplay_zoom(ddisp, &middle, M_SQRT1_2);
726 void
727 view_zoom_set_callback(gpointer data, guint action, GtkWidget *widget)
729 DDisplay *ddisp;
730 real scale;
731 Point middle;
732 Rectangle *visible;
734 ddisp = ddisplay_active();
735 visible = &ddisp->visible;
736 middle.x = visible->left*0.5 + visible->right*0.5;
737 middle.y = visible->top*0.5 + visible->bottom*0.5;
739 scale = ((real) action)/1000.0 * DDISPLAY_NORMAL_ZOOM;
741 ddisplay_zoom(ddisp, &middle, scale / ddisp->zoom_factor);
744 void
745 view_show_cx_pts_callback(gpointer data, guint action, GtkWidget *widget)
747 DDisplay *ddisp;
748 int old_val;
750 ddisp = ddisplay_active();
752 old_val = ddisp->show_cx_pts;
753 ddisp->show_cx_pts = GTK_CHECK_MENU_ITEM(widget)->active;
755 if (old_val != ddisp->show_cx_pts) {
756 ddisplay_add_update_all(ddisp);
757 ddisplay_flush(ddisp);
761 void
762 view_aa_callback(gpointer data, guint action, GtkWidget *widget)
764 DDisplay *ddisp;
765 int aa;
767 ddisp = ddisplay_active();
769 aa = GTK_CHECK_MENU_ITEM(widget)->active;
771 if (aa != ddisp->aa_renderer) {
772 ddisplay_set_renderer(ddisp, aa);
773 ddisplay_add_update_all(ddisp);
774 ddisplay_flush(ddisp);
778 void
779 view_visible_grid_callback(gpointer data, guint action, GtkWidget *widget)
781 DDisplay *ddisp;
782 int old_val;
784 ddisp = ddisplay_active();
786 old_val = ddisp->grid.visible;
787 ddisp->grid.visible = GTK_CHECK_MENU_ITEM(widget)->active;
789 if (old_val != ddisp->grid.visible) {
790 ddisplay_add_update_all(ddisp);
791 ddisplay_flush(ddisp);
795 void
796 view_snap_to_grid_callback(gpointer data, guint action, GtkWidget *widget)
798 DDisplay *ddisp;
800 ddisp = ddisplay_active();
802 ddisplay_set_snap_to_grid(ddisp, GTK_CHECK_MENU_ITEM(widget)->active);
805 void view_toggle_rulers_callback(gpointer data, guint action, GtkWidget*widget)
807 DDisplay *ddisp;
809 ddisp = ddisplay_active();
811 /* The following is borrowed straight from the Gimp: */
813 /* This routine use promiscuous knowledge of gtk internals
814 * in order to hide and show the rulers "smoothly". This
815 * is kludgy and a hack and may break if gtk is changed
816 * internally.
818 if (!GTK_CHECK_MENU_ITEM(widget)->active) {
819 if (GTK_WIDGET_VISIBLE (ddisp->origin)) {
820 gtk_widget_unmap (ddisp->origin);
821 gtk_widget_unmap (ddisp->hrule);
822 gtk_widget_unmap (ddisp->vrule);
824 GTK_WIDGET_UNSET_FLAGS (ddisp->origin, GTK_VISIBLE);
825 GTK_WIDGET_UNSET_FLAGS (ddisp->hrule, GTK_VISIBLE);
826 GTK_WIDGET_UNSET_FLAGS (ddisp->vrule, GTK_VISIBLE);
828 gtk_widget_queue_resize (GTK_WIDGET (ddisp->origin->parent));
830 } else {
831 if (!GTK_WIDGET_VISIBLE (ddisp->origin)) {
832 GTK_WIDGET_SET_FLAGS (ddisp->origin, GTK_VISIBLE);
833 GTK_WIDGET_SET_FLAGS (ddisp->hrule, GTK_VISIBLE);
834 GTK_WIDGET_SET_FLAGS (ddisp->vrule, GTK_VISIBLE);
836 gtk_widget_map (ddisp->origin);
837 gtk_widget_map (ddisp->hrule);
838 gtk_widget_map (ddisp->vrule);
840 gtk_widget_queue_resize (GTK_WIDGET (ddisp->origin->parent));
845 extern void
846 view_new_view_callback(gpointer data, guint action, GtkWidget *widget)
848 DDisplay *ddisp;
849 Diagram *dia;
851 ddisp = ddisplay_active();
852 dia = ddisp->diagram;
854 ddisp = new_display(dia);
857 void
858 view_show_all_callback(gpointer data, guint action, GtkWidget *widget)
860 DDisplay *ddisp;
861 Diagram *dia;
862 real magnify_x, magnify_y;
863 int width, height;
864 Point middle;
866 ddisp = ddisplay_active();
867 dia = ddisp->diagram;
869 width = dia_renderer_get_width_pixels (ddisp->renderer);
870 height = dia_renderer_get_height_pixels (ddisp->renderer);
872 magnify_x = (real)width /
873 (dia->data->extents.right - dia->data->extents.left) / ddisp->zoom_factor;
874 magnify_y = (real)height /
875 (dia->data->extents.bottom - dia->data->extents.top) / ddisp->zoom_factor;
877 middle.x = dia->data->extents.left +
878 (dia->data->extents.right - dia->data->extents.left) / 2.0;
879 middle.y = dia->data->extents.top +
880 (dia->data->extents.bottom - dia->data->extents.top) / 2.0;
882 ddisplay_zoom (ddisp, &middle, (magnify_x<magnify_y)?magnify_x:magnify_y);
884 ddisplay_update_scrollbars(ddisp);
885 ddisplay_add_update_all(ddisp);
886 ddisplay_flush(ddisp);
889 void
890 view_redraw_callback(gpointer data, guint action, GtkWidget *widget)
892 DDisplay *ddisp;
893 ddisp = ddisplay_active();
894 ddisplay_add_update_all(ddisp);
895 ddisplay_flush(ddisp);
898 void
899 view_diagram_properties_callback(gpointer data, guint action, GtkWidget *widget)
901 DDisplay *ddisp;
903 ddisp = ddisplay_active();
904 diagram_properties_show(ddisp->diagram);
908 void
909 objects_place_over_callback(gpointer data, guint action, GtkWidget *widget)
911 diagram_place_over_selected(ddisplay_active()->diagram);
914 void
915 objects_place_under_callback(gpointer data, guint action, GtkWidget *widget)
917 diagram_place_under_selected(ddisplay_active()->diagram);
920 void
921 objects_place_up_callback(gpointer data, guint action, GtkWidget *widget)
923 diagram_place_up_selected(ddisplay_active()->diagram);
926 void
927 objects_place_down_callback(gpointer data, guint action, GtkWidget *widget)
929 diagram_place_down_selected(ddisplay_active()->diagram);
932 void
933 objects_parent_callback(gpointer data, guint action, GtkWidget *widget)
935 diagram_parent_selected(ddisplay_active()->diagram);
938 void
939 objects_unparent_callback(gpointer data, guint action, GtkWidget *widget)
941 diagram_unparent_selected(ddisplay_active()->diagram);
944 void
945 objects_unparent_children_callback(gpointer data, guint action, GtkWidget *widget)
947 diagram_unparent_children_selected(ddisplay_active()->diagram);
950 void
951 objects_group_callback(gpointer data, guint action, GtkWidget *widget)
953 diagram_group_selected(ddisplay_active()->diagram);
956 void
957 objects_ungroup_callback(gpointer data, guint action, GtkWidget *widget)
959 diagram_ungroup_selected(ddisplay_active()->diagram);
962 void
963 dialogs_properties_callback(gpointer data, guint action, GtkWidget *widget)
965 Diagram *dia;
966 Object *selected;
968 dia = ddisplay_active()->diagram;
970 if (dia->data->selected != NULL) {
971 selected = dia->data->selected->data;
972 properties_show(dia, selected);
973 } else {
974 diagram_properties_show(dia);
978 void
979 dialogs_layers_callback(gpointer data, guint action, GtkWidget *widget)
981 layer_dialog_set_diagram(ddisplay_active()->diagram);
982 layer_dialog_show();
986 void
987 objects_align_h_callback(gpointer data, guint action, GtkWidget *widget)
989 int align;
990 Diagram *dia;
991 GList *objects;
993 align = action;
995 dia = ddisplay_active()->diagram;
996 objects = dia->data->selected;
998 object_add_updates_list(objects, dia);
999 object_list_align_h(objects, dia, align);
1000 diagram_update_connections_selection(dia);
1001 object_add_updates_list(objects, dia);
1002 diagram_flush(dia);
1004 undo_set_transactionpoint(dia->undo);
1007 void
1008 objects_align_v_callback(gpointer data, guint action, GtkWidget *widget)
1010 int align;
1011 Diagram *dia;
1012 GList *objects;
1014 align = action;
1016 dia = ddisplay_active()->diagram;
1017 objects = dia->data->selected;
1019 object_add_updates_list(objects, dia);
1020 object_list_align_v(objects, dia, align);
1021 diagram_update_connections_selection(dia);
1022 object_add_updates_list(objects, dia);
1023 diagram_flush(dia);
1025 undo_set_transactionpoint(dia->undo);