2006-12-05 David Lodge <dave@cirt.net>
[dia.git] / app / commands.c
blobdcbdcc13ebf2a0d8b5429b802e30312ea487b63d
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 #ifdef GNOME
35 # include <gnome.h>
36 #endif
38 #ifdef G_OS_WIN32
40 * Instead of polluting the Dia namespace with windoze headers, declare the
41 * required prototype here. This is bad style, but not as bad as namespace
42 * clashes to be resolved without C++ --hb
44 long __stdcall
45 ShellExecuteA (long hwnd,
46 const char* lpOperation,
47 const char* lpFile,
48 const char* lpParameters,
49 const char* lpDirectory,
50 int nShowCmd);
51 #endif
53 #include "paginate_psprint.h"
54 #ifdef G_OS_WIN32
55 # include "paginate_gdiprint.h"
56 #endif
57 #include "intl.h"
58 #include "commands.h"
59 #include "app_procs.h"
60 #include "diagram.h"
61 #include "display.h"
62 #include "object_ops.h"
63 #include "cut_n_paste.h"
64 #include "load_save.h"
65 #include "utils.h"
66 #include "message.h"
67 #include "grid.h"
68 #include "properties.h"
69 #include "propinternals.h"
70 #include "preferences.h"
71 #include "layer_dialog.h"
72 #include "connectionpoint_ops.h"
73 #include "undo.h"
74 #include "pagesetup.h"
75 #include "text.h"
76 #include "dia_dirs.h"
77 #include "focus.h"
78 #include <gdk/gdk.h>
79 #include <gdk/gdkkeysyms.h>
80 #include "lib/properties.h"
81 #include "lib/parent.h"
82 #include "dia-props.h"
83 #include "diagram_tree_window.h"
84 #include "authors.h" /* master contributors data */
86 void
87 file_quit_callback (GtkAction *action)
89 app_exit();
92 void
93 file_pagesetup_callback (GtkAction *action)
95 Diagram *dia;
97 dia = ddisplay_active_diagram();
98 if (!dia) return;
99 create_page_setup_dlg(dia);
102 void
103 file_print_callback (GtkAction *action)
105 Diagram *dia;
107 dia = ddisplay_active_diagram();
108 if (!dia) return;
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 (GtkAction *action)
121 /* some people use tear-off menus and insist to close non existing displays */
122 if (ddisplay_active())
123 ddisplay_close(ddisplay_active());
126 void
127 file_new_callback (GtkAction *action)
129 Diagram *dia;
130 DDisplay *ddisp;
131 static int untitled_nr = 1;
132 gchar *name, *filename;
134 name = g_strdup_printf(_("Diagram%d.dia"), untitled_nr++);
135 filename = g_filename_from_utf8(name, -1, NULL, NULL, NULL);
136 dia = new_diagram(filename);
137 ddisp = new_display(dia);
138 diagram_tree_add(diagram_tree(), dia);
139 g_free (name);
140 g_free (filename);
143 void
144 file_preferences_callback (GtkAction *action)
146 prefs_show();
150 void
151 edit_copy_callback (GtkAction *action)
153 GList *copy_list;
154 DDisplay *ddisp;
156 ddisp = ddisplay_active();
157 if (!ddisp) return;
158 copy_list = parent_list_affected(diagram_get_sorted_selected(ddisp->diagram));
160 cnp_store_objects(object_copy_list(copy_list), 1);
161 g_list_free(copy_list);
163 ddisplay_do_update_menu_sensitivity(ddisp);
166 void
167 edit_cut_callback (GtkAction *action)
169 GList *cut_list;
170 DDisplay *ddisp;
171 Change *change;
173 ddisp = ddisplay_active();
174 if (!ddisp) return;
176 diagram_selected_break_external(ddisp->diagram);
178 cut_list = parent_list_affected(diagram_get_sorted_selected(ddisp->diagram));
180 cnp_store_objects(object_copy_list(cut_list), 0);
182 change = undo_delete_objects_children(ddisp->diagram, cut_list);
183 (change->apply)(change, ddisp->diagram);
185 ddisplay_do_update_menu_sensitivity(ddisp);
186 diagram_flush(ddisp->diagram);
188 diagram_modified(ddisp->diagram);
189 diagram_update_extents(ddisp->diagram);
190 undo_set_transactionpoint(ddisp->diagram->undo);
193 void
194 edit_paste_callback (GtkAction *action)
196 GList *paste_list;
197 DDisplay *ddisp;
198 Point paste_corner;
199 Point delta;
200 Change *change;
201 int generation = 0;
203 ddisp = ddisplay_active();
204 if (!ddisp) return;
206 if (!cnp_exist_stored_objects()) {
207 message_warning(_("No existing object to paste.\n"));
208 return;
211 paste_list = cnp_get_stored_objects(&generation); /* Gets a copy */
213 paste_corner = object_list_corner(paste_list);
215 delta.x = ddisp->visible.left - paste_corner.x;
216 delta.y = ddisp->visible.top - paste_corner.y;
218 /* Move down some 10% of the visible area. */
219 delta.x += (ddisp->visible.right - ddisp->visible.left) * 0.1 * generation;
220 delta.y += (ddisp->visible.bottom - ddisp->visible.top) * 0.1 * generation;
222 if (generation)
223 object_list_move_delta(paste_list, &delta);
225 change = undo_insert_objects(ddisp->diagram, paste_list, 0);
226 (change->apply)(change, ddisp->diagram);
228 diagram_modified(ddisp->diagram);
229 undo_set_transactionpoint(ddisp->diagram->undo);
231 diagram_remove_all_selected(ddisp->diagram, TRUE);
232 diagram_select_list(ddisp->diagram, paste_list);
234 diagram_update_extents(ddisp->diagram);
235 diagram_flush(ddisp->diagram);
239 * ALAN: Paste should probably paste to different position, feels
240 * wrong somehow. ALAN: The offset should increase a little each time
241 * if you paste/duplicate several times in a row, because it is
242 * clearer what is happening than if you were to piling them all in
243 * one place.
245 * completely untested, basically it is copy+paste munged together
247 void
248 edit_duplicate_callback (GtkAction *action)
250 GList *duplicate_list;
251 DDisplay *ddisp;
252 Point duplicate_corner;
253 Point delta;
254 Change *change;
256 ddisp = ddisplay_active();
257 if (!ddisp) return;
258 duplicate_list = object_copy_list(diagram_get_sorted_selected(ddisp->diagram));
259 duplicate_corner = object_list_corner(duplicate_list);
261 /* Move down some 10% of the visible area. */
262 delta.x = (ddisp->visible.right - ddisp->visible.left)*0.05;
263 delta.y = (ddisp->visible.bottom - ddisp->visible.top)*0.05;
265 object_list_move_delta(duplicate_list, &delta);
267 change = undo_insert_objects(ddisp->diagram, duplicate_list, 0);
268 (change->apply)(change, ddisp->diagram);
270 diagram_modified(ddisp->diagram);
271 undo_set_transactionpoint(ddisp->diagram->undo);
273 diagram_remove_all_selected(ddisp->diagram, TRUE);
274 diagram_select_list(ddisp->diagram, duplicate_list);
276 diagram_flush(ddisp->diagram);
278 ddisplay_do_update_menu_sensitivity(ddisp);
284 /* Signal handler for getting the clipboard contents */
285 /* Note that the clipboard is for M$-style cut/copy/paste copying, while
286 the selection is for Unix-style mark-and-copy. We can't really do
287 mark-and-copy.
290 static void
291 insert_text(DDisplay *ddisp, Focus *focus, const gchar *text)
293 ObjectChange *change = NULL;
294 int modified = FALSE, any_modified = FALSE;
295 DiaObject *obj = focus_get_object(focus);
297 while (text != NULL) {
298 gchar *next_line = g_utf8_strchr(text, -1, '\n');
299 if (next_line != text) {
300 gint len = g_utf8_strlen(text, (next_line-text));
301 modified = (*focus->key_event)(focus, GDK_A, text, len, &change);
303 if (next_line != NULL) {
304 modified = (*focus->key_event)(focus, GDK_Return, "\n", 1, &change);
305 text = g_utf8_next_char(next_line);
306 } else {
307 text = NULL;
309 { /* Make sure object updates its data: */
310 Point p = obj->position;
311 (obj->ops->move)(obj,&p); }
313 /* Perhaps this can be improved */
314 object_add_updates(obj, ddisp->diagram);
316 if (modified && (change != NULL)) {
317 undo_object_change(ddisp->diagram, obj, change);
318 any_modified = TRUE;
321 diagram_flush(ddisp->diagram);
324 if (any_modified) {
325 diagram_modified(ddisp->diagram);
326 undo_set_transactionpoint(ddisp->diagram->undo);
331 static void
332 received_clipboard_handler(GtkClipboard *clipboard,
333 const gchar *text,
334 gpointer data) {
335 Focus *focus = active_focus();
336 DDisplay *ddisp = (DDisplay *)data;
338 if (text == NULL) return;
340 if ((focus == NULL) || (!focus->has_focus)) return;
342 if (!g_utf8_validate(text, -1, NULL)) {
343 message_error("Not valid UTF8");
344 return;
347 insert_text(ddisp, focus, text);
350 static PropDescription text_prop_singleton_desc[] = {
351 { "text", PROP_TYPE_TEXT },
352 PROP_DESC_END};
354 static void
355 make_text_prop_singleton(GPtrArray **props, TextProperty **prop)
357 *props = prop_list_from_descs(text_prop_singleton_desc,pdtpp_true);
358 g_assert((*props)->len == 1);
360 *prop = g_ptr_array_index((*props),0);
361 g_free((*prop)->text_data);
362 (*prop)->text_data = NULL;
366 void
367 edit_copy_text_callback (GtkAction *action)
369 Focus *focus = active_focus();
370 DDisplay *ddisp;
371 DiaObject *obj;
372 GPtrArray *textprops;
373 TextProperty *prop;
375 if ((focus == NULL) || (!focus->has_focus)) return;
377 ddisp = ddisplay_active();
378 if (!ddisp) return;
380 obj = focus_get_object(focus);
382 if (obj->ops->get_props == NULL)
383 return;
385 make_text_prop_singleton(&textprops,&prop);
386 /* Get the first text property */
387 obj->ops->get_props(obj, textprops);
389 /* GTK docs claim the selection clipboard is ignored on Win32.
390 * The "clipboard" clipboard is mostly ignored in Unix
392 #ifdef G_OS_WIN32
393 gtk_clipboard_set_text(gtk_clipboard_get(GDK_NONE),
394 prop->text_data, -1);
395 #else
396 gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY),
397 prop->text_data, -1);
398 #endif
399 prop_list_free(textprops);
402 void
403 edit_cut_text_callback (GtkAction *action)
405 Focus *focus = active_focus();
406 DDisplay *ddisp;
407 DiaObject *obj;
408 Text *text;
409 GPtrArray *textprops;
410 TextProperty *prop;
411 ObjectChange *change;
413 if ((focus == NULL) || (!focus->has_focus)) return;
415 ddisp = ddisplay_active();
416 if (!ddisp) return;
418 obj = focus_get_object(focus);
419 text = (Text*)focus->user_data;
421 if (obj->ops->get_props == NULL)
422 return;
424 make_text_prop_singleton(&textprops,&prop);
425 /* Get the first text property */
426 obj->ops->get_props(obj, textprops);
428 /* GTK docs claim the selection clipboard is ignored on Win32.
429 * The "clipboard" clipboard is mostly ignored in Unix
431 #ifdef G_OS_WIN32
432 gtk_clipboard_set_text(gtk_clipboard_get(GDK_NONE),
433 prop->text_data, -1);
434 #else
435 gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY),
436 prop->text_data, -1);
437 #endif
439 prop_list_free(textprops);
441 if (text_delete_all(text, &change)) {
442 object_add_updates(obj, ddisp->diagram);
443 undo_object_change(ddisp->diagram, obj, change);
444 undo_set_transactionpoint(ddisp->diagram->undo);
445 diagram_modified(ddisp->diagram);
446 diagram_flush(ddisp->diagram);
450 void
451 edit_paste_text_callback (GtkAction *action)
453 DDisplay *ddisp;
455 ddisp = ddisplay_active();
456 if (!ddisp) return;
458 #ifdef G_OS_WIN32
459 gtk_clipboard_request_text(gtk_clipboard_get(GDK_NONE),
460 received_clipboard_handler, ddisp);
461 #else
462 gtk_clipboard_request_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY),
463 received_clipboard_handler, ddisp);
464 #endif
467 void
468 edit_delete_callback (GtkAction *action)
470 GList *delete_list;
471 DDisplay *ddisp;
473 Change *change;
475 ddisp = ddisplay_active();
476 if (!ddisp) return;
478 diagram_selected_break_external(ddisp->diagram);
480 delete_list = diagram_get_sorted_selected(ddisp->diagram);
481 change = undo_delete_objects_children(ddisp->diagram, delete_list);
482 (change->apply)(change, ddisp->diagram);
483 g_list_free(delete_list);
485 diagram_modified(ddisp->diagram);
486 diagram_update_extents(ddisp->diagram);
488 ddisplay_do_update_menu_sensitivity(ddisp);
489 diagram_flush(ddisp->diagram);
491 undo_set_transactionpoint(ddisp->diagram->undo);
494 void
495 edit_undo_callback (GtkAction *action)
497 Diagram *dia;
499 dia = ddisplay_active_diagram();
500 if (!dia) return;
502 undo_revert_to_last_tp(dia->undo);
503 diagram_modified(dia);
504 diagram_update_extents(dia);
506 diagram_flush(dia);
509 void
510 edit_redo_callback (GtkAction *action)
512 Diagram *dia;
514 dia = ddisplay_active_diagram();
515 if (!dia) return;
517 undo_apply_to_next_tp(dia->undo);
518 diagram_modified(dia);
519 diagram_update_extents(dia);
521 diagram_flush(dia);
524 void
525 help_manual_callback (GtkAction *action)
527 #ifdef GNOME
528 gnome_help_display("dia", NULL, NULL);
529 #else
530 char *helpdir, *helpindex = NULL, *command;
531 guint bestscore = G_MAXINT;
532 GDir *dp;
533 const char *dentry;
534 GError *error = NULL;
536 helpdir = dia_get_data_directory("help");
537 if (!helpdir) {
538 message_warning(_("Could not find help directory"));
539 return;
542 /* search through helpdir for the helpfile that matches the user's locale */
543 dp = g_dir_open (helpdir, 0, &error);
544 if (!dp) {
545 message_warning(_("Could not open help directory:\n%s"),
546 error->message);
547 g_error_free (error);
548 return;
551 while ((dentry = g_dir_read_name(dp)) != NULL) {
552 guint score;
554 score = intl_score_locale(dentry);
555 if (score < bestscore) {
556 if (helpindex)
557 g_free(helpindex);
558 #ifdef G_OS_WIN32
559 /* use HTML Help on win32 if available */
560 helpindex = g_strconcat(helpdir, G_DIR_SEPARATOR_S, dentry,
561 G_DIR_SEPARATOR_S "dia-manual.chm", NULL);
562 if (!g_file_test(helpindex, G_FILE_TEST_EXISTS)) {
563 helpindex = g_strconcat(helpdir, G_DIR_SEPARATOR_S, dentry,
564 G_DIR_SEPARATOR_S "index.html", NULL);
566 #else
567 helpindex = g_strconcat(helpdir, G_DIR_SEPARATOR_S, dentry,
568 G_DIR_SEPARATOR_S "index.html", NULL);
569 #endif
570 bestscore = score;
573 g_dir_close (dp);
574 g_free(helpdir);
575 if (!helpindex) {
576 message_warning(_("Could not find help directory"));
577 return;
580 #ifdef G_OS_WIN32
581 # define SW_SHOWNORMAL 1
582 ShellExecuteA (0, "open", helpindex, NULL, helpdir, SW_SHOWNORMAL);
583 #else
584 command = getenv("BROWSER");
585 command = g_strdup_printf("%s 'file://%s' &", command ? command : "gnome-open", helpindex);
586 system(command);
587 g_free(command);
588 #endif
590 g_free(helpindex);
591 #endif
594 static void
595 activate_url (GtkAboutDialog *about,
596 const gchar *link,
597 gpointer data)
599 #ifdef G_OS_WIN32
600 ShellExecuteA (0, "open", link, NULL, NULL, SW_SHOWNORMAL);
601 #else
602 gchar *command = getenv("BROWSER");
603 command = g_strdup_printf("%s '%s' &", command ? command : "gnome-open", link);
604 system(command);
605 g_free(command);
606 #endif
609 void
610 help_about_callback (GtkAction *action)
612 const gchar *translators = _("translator_credits-PLEASE_ADD_YOURSELF_HERE");
613 const gchar *license = _(
614 "This program is free software; you can redistribute it and/or modify\n"
615 "it under the terms of the GNU General Public License as published by\n"
616 "the Free Software Foundation; either version 2 of the License, or\n"
617 "(at your option) any later version.\n"
618 "\n"
619 "This program is distributed in the hope that it will be useful,\n"
620 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
621 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
622 "GNU General Public License for more details.\n"
623 "\n"
624 "You should have received a copy of the GNU General Public License\n"
625 "along with this program; if not, write to the Free Software\n"
626 "Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n");
628 gchar *dirname = dia_get_data_directory("");
629 gchar *filename = g_build_filename (dirname, "dia_logo.png", NULL);
630 GdkPixbuf *logo = gdk_pixbuf_new_from_file(filename, NULL);
632 gtk_about_dialog_set_url_hook (activate_url, NULL, NULL);
633 gtk_show_about_dialog (NULL,
634 "logo", logo,
635 "name", "Dia",
636 "version", VERSION,
637 "comments", _("A program for drawing structured diagrams."),
638 "copyright", "(C) 1998-2006 The Free Software Foundation and the authors",
639 "website", "http://www.gnome.org/projects/dia/",
640 "authors", authors,
641 "documenters", documentors,
642 "translator-credits", strcmp (translators, "translator_credits-PLEASE_ADD_YOURSELF_HERE")
643 ? translators : NULL,
644 "license", license,
645 NULL);
646 g_free (dirname);
647 g_free (filename);
648 if (logo)
649 g_object_unref (logo);
652 void
653 view_zoom_in_callback (GtkAction *action)
655 DDisplay *ddisp;
656 Point middle;
657 Rectangle *visible;
659 ddisp = ddisplay_active();
660 if (!ddisp) return;
661 visible = &ddisp->visible;
662 middle.x = visible->left*0.5 + visible->right*0.5;
663 middle.y = visible->top*0.5 + visible->bottom*0.5;
665 ddisplay_zoom(ddisp, &middle, M_SQRT2);
668 void
669 view_zoom_out_callback (GtkAction *action)
671 DDisplay *ddisp;
672 Point middle;
673 Rectangle *visible;
675 ddisp = ddisplay_active();
676 if (!ddisp) return;
677 visible = &ddisp->visible;
678 middle.x = visible->left*0.5 + visible->right*0.5;
679 middle.y = visible->top*0.5 + visible->bottom*0.5;
681 ddisplay_zoom(ddisp, &middle, M_SQRT1_2);
684 void
685 view_zoom_set_callback (GtkAction *action)
687 DDisplay *ddisp;
688 real scale;
689 Point middle;
690 Rectangle *visible;
691 int factor;
693 ddisp = ddisplay_active();
694 if (!ddisp) return;
696 /* HACK the actual factor is a suffix to the action name */
697 factor = atoi (gtk_action_get_name (action) + strlen ("ViewZoom"));
699 visible = &ddisp->visible;
700 middle.x = visible->left*0.5 + visible->right*0.5;
701 middle.y = visible->top*0.5 + visible->bottom*0.5;
703 scale = ((real) factor)/1000.0 * DDISPLAY_NORMAL_ZOOM;
705 ddisplay_zoom(ddisp, &middle, scale / ddisp->zoom_factor);
708 void
709 view_show_cx_pts_callback (GtkToggleAction *action)
711 DDisplay *ddisp;
712 int old_val;
714 ddisp = ddisplay_active();
715 if (!ddisp) return;
717 old_val = ddisp->show_cx_pts;
718 ddisp->show_cx_pts = gtk_toggle_action_get_active (action);
720 if (old_val != ddisp->show_cx_pts) {
721 ddisplay_add_update_all(ddisp);
722 ddisplay_flush(ddisp);
726 void
727 view_unfullscreen (void)
729 DDisplay *ddisp;
730 GtkToggleAction *item;
732 ddisp = ddisplay_active();
733 if (!ddisp) return;
735 /* find the menuitem */
736 item = GTK_TOGGLE_ACTION (menus_get_action ("ViewFullscreen"));
737 if (item && gtk_toggle_action_get_active (item)) {
738 gtk_toggle_action_set_active (item, FALSE);
742 void
743 view_fullscreen_callback (GtkToggleAction *action)
745 DDisplay *ddisp;
746 int fs;
748 ddisp = ddisplay_active();
749 if (!ddisp) return;
751 fs = gtk_toggle_action_get_active (action);
753 if (fs) /* it is already toggled */
754 gtk_window_fullscreen(GTK_WINDOW(ddisp->shell));
755 else
756 gtk_window_unfullscreen(GTK_WINDOW(ddisp->shell));
759 void
760 view_aa_callback (GtkToggleAction *action)
762 DDisplay *ddisp;
763 int aa;
765 ddisp = ddisplay_active();
766 if (!ddisp) return;
768 aa = gtk_toggle_action_get_active (action);
770 if (aa != ddisp->aa_renderer) {
771 ddisplay_set_renderer(ddisp, aa);
772 ddisplay_add_update_all(ddisp);
773 ddisplay_flush(ddisp);
777 void
778 view_visible_grid_callback (GtkToggleAction *action)
780 DDisplay *ddisp;
781 guint old_val;
783 ddisp = ddisplay_active();
784 if (!ddisp) return;
786 old_val = ddisp->grid.visible;
787 ddisp->grid.visible = gtk_toggle_action_get_active (action);
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 (GtkToggleAction *action)
798 DDisplay *ddisp;
800 ddisp = ddisplay_active();
801 if (!ddisp) return;
803 ddisplay_set_snap_to_grid(ddisp, gtk_toggle_action_get_active (action));
806 void
807 view_snap_to_objects_callback (GtkToggleAction *action)
809 DDisplay *ddisp;
811 ddisp = ddisplay_active();
812 if (!ddisp) return;
814 ddisplay_set_snap_to_objects(ddisp, gtk_toggle_action_get_active (action));
817 void
818 view_toggle_rulers_callback (GtkToggleAction *action)
820 DDisplay *ddisp;
822 ddisp = ddisplay_active();
823 if (!ddisp) return;
825 if (!gtk_toggle_action_get_active (action)) {
826 if (GTK_WIDGET_VISIBLE (ddisp->origin)) {
827 gtk_widget_unmap (ddisp->origin);
828 gtk_widget_unmap (ddisp->hrule);
829 gtk_widget_unmap (ddisp->vrule);
831 GTK_WIDGET_UNSET_FLAGS (ddisp->origin, GTK_VISIBLE);
832 GTK_WIDGET_UNSET_FLAGS (ddisp->hrule, GTK_VISIBLE);
833 GTK_WIDGET_UNSET_FLAGS (ddisp->vrule, GTK_VISIBLE);
835 gtk_widget_queue_resize (GTK_WIDGET (ddisp->origin->parent));
837 } else {
838 if (!GTK_WIDGET_VISIBLE (ddisp->origin)) {
839 GTK_WIDGET_SET_FLAGS (ddisp->origin, GTK_VISIBLE);
840 GTK_WIDGET_SET_FLAGS (ddisp->hrule, GTK_VISIBLE);
841 GTK_WIDGET_SET_FLAGS (ddisp->vrule, GTK_VISIBLE);
843 gtk_widget_map (ddisp->origin);
844 gtk_widget_map (ddisp->hrule);
845 gtk_widget_map (ddisp->vrule);
847 gtk_widget_queue_resize (GTK_WIDGET (ddisp->origin->parent));
852 extern void
853 view_new_view_callback (GtkAction *action)
855 Diagram *dia;
857 dia = ddisplay_active_diagram();
858 if (!dia) return;
860 new_display(dia);
863 extern void
864 view_clone_view_callback (GtkAction *action)
866 DDisplay *ddisp;
868 ddisp = ddisplay_active();
869 if (!ddisp) return;
871 copy_display(ddisp);
874 void
875 view_show_all_callback (GtkAction *action)
877 DDisplay *ddisp;
878 Diagram *dia;
879 real magnify_x, magnify_y;
880 int width, height;
881 Point middle;
883 ddisp = ddisplay_active();
884 if (!ddisp) return;
885 dia = ddisp->diagram;
887 width = dia_renderer_get_width_pixels (ddisp->renderer);
888 height = dia_renderer_get_height_pixels (ddisp->renderer);
890 /* if there is something selected show that instead of all exisiting objects */
891 if (dia->data->selected) {
892 GList *list = dia->data->selected;
893 Rectangle extents = ((DiaObject*)list->data)->bounding_box;
894 list = g_list_next(list);
895 while (list) {
896 DiaObject *obj = (DiaObject *)list->data;
897 rectangle_union(&extents, &(obj->bounding_box));
898 list = g_list_next(list);
900 magnify_x = (real)width / (extents.right - extents.left) / ddisp->zoom_factor;
901 magnify_y = (real)height / (extents.bottom - extents.top) / ddisp->zoom_factor;
902 middle.x = extents.left + (extents.right - extents.left) / 2.0;
903 middle.y = extents.top + (extents.bottom - extents.top) / 2.0;
904 } else {
905 magnify_x = (real)width /
906 (dia->data->extents.right - dia->data->extents.left) / ddisp->zoom_factor;
907 magnify_y = (real)height /
908 (dia->data->extents.bottom - dia->data->extents.top) / ddisp->zoom_factor;
910 middle.x = dia->data->extents.left +
911 (dia->data->extents.right - dia->data->extents.left) / 2.0;
912 middle.y = dia->data->extents.top +
913 (dia->data->extents.bottom - dia->data->extents.top) / 2.0;
916 ddisplay_zoom (ddisp, &middle,
917 ((magnify_x<magnify_y)?magnify_x:magnify_y)/1.05);
919 ddisplay_update_scrollbars(ddisp);
920 ddisplay_add_update_all(ddisp);
921 ddisplay_flush(ddisp);
924 void
925 view_redraw_callback (GtkAction *action)
927 DDisplay *ddisp;
928 ddisp = ddisplay_active();
929 if (!ddisp) return;
930 ddisplay_add_update_all(ddisp);
931 ddisplay_flush(ddisp);
934 void
935 view_diagram_properties_callback (GtkAction *action)
937 DDisplay *ddisp;
939 ddisp = ddisplay_active();
940 if (!ddisp) return;
941 diagram_properties_show(ddisp->diagram);
945 void
946 objects_place_over_callback (GtkAction *action)
948 diagram_place_over_selected(ddisplay_active_diagram());
951 void
952 objects_place_under_callback (GtkAction *action)
954 diagram_place_under_selected(ddisplay_active_diagram());
957 void
958 objects_place_up_callback (GtkAction *action)
960 diagram_place_up_selected(ddisplay_active_diagram());
963 void
964 objects_place_down_callback (GtkAction *action)
966 diagram_place_down_selected(ddisplay_active_diagram());
969 void
970 objects_parent_callback (GtkAction *action)
972 diagram_parent_selected(ddisplay_active_diagram());
975 void
976 objects_unparent_callback (GtkAction *action)
978 diagram_unparent_selected(ddisplay_active_diagram());
981 void
982 objects_unparent_children_callback (GtkAction *action)
984 diagram_unparent_children_selected(ddisplay_active_diagram());
987 void
988 objects_group_callback (GtkAction *action)
990 DDisplay *ddisp;
992 ddisp = ddisplay_active();
993 if (!ddisp) return;
994 diagram_group_selected(ddisplay_active_diagram());
995 ddisplay_do_update_menu_sensitivity(ddisp);
998 void
999 objects_ungroup_callback (GtkAction *action)
1001 DDisplay *ddisp;
1003 ddisp = ddisplay_active();
1004 if (!ddisp) return;
1005 diagram_ungroup_selected(ddisplay_active_diagram());
1006 ddisplay_do_update_menu_sensitivity(ddisp);
1009 void
1010 dialogs_properties_callback (GtkAction *action)
1012 Diagram *dia;
1013 DiaObject *selected;
1015 dia = ddisplay_active_diagram();
1016 if (!dia) return;
1018 if (dia->data->selected != NULL) {
1019 selected = dia->data->selected->data;
1020 properties_show(dia, selected);
1021 } else {
1022 diagram_properties_show(dia);
1026 void
1027 dialogs_layers_callback (GtkAction *action)
1029 layer_dialog_set_diagram(ddisplay_active_diagram());
1030 layer_dialog_show();
1034 void
1035 objects_align_h_callback (GtkAction *action)
1037 const gchar *a;
1038 int align = DIA_ALIGN_LEFT;
1039 Diagram *dia;
1040 GList *objects;
1042 /* HACK align is suffix to action name */
1043 a = gtk_action_get_name (action) + strlen ("ObjectsAlign");
1044 if (0 == strcmp ("Left", a)) {
1045 align = DIA_ALIGN_LEFT;
1047 else if (0 == strcmp ("Center", a)) {
1048 align = DIA_ALIGN_CENTER;
1050 else if (0 == strcmp ("Right", a)) {
1051 align = DIA_ALIGN_RIGHT;
1053 else if (0 == strcmp ("Spreadouthorizontally", a)) {
1054 align = DIA_ALIGN_EQUAL;
1056 else if (0 == strcmp ("Adjacent", a)) {
1057 align = DIA_ALIGN_ADJACENT;
1059 else {
1060 g_warning ("objects_align_v_callback() called without appropriate align");
1061 return;
1064 dia = ddisplay_active_diagram();
1065 if (!dia) return;
1066 objects = dia->data->selected;
1068 object_add_updates_list(objects, dia);
1069 object_list_align_h(objects, dia, align);
1070 diagram_update_connections_selection(dia);
1071 object_add_updates_list(objects, dia);
1072 diagram_modified(dia);
1073 diagram_flush(dia);
1075 undo_set_transactionpoint(dia->undo);
1078 void
1079 objects_align_v_callback (GtkAction *action)
1081 const gchar *a;
1082 int align;
1083 Diagram *dia;
1084 GList *objects;
1086 /* HACK align is suffix to action name */
1087 a = gtk_action_get_name (action) + strlen ("ObjectsAlign");
1088 if (0 == strcmp ("Top", a)) {
1089 align = DIA_ALIGN_TOP;
1091 else if (0 == strcmp ("Middle", a)) {
1092 align = DIA_ALIGN_CENTER;
1094 else if (0 == strcmp ("Bottom", a)) {
1095 align = DIA_ALIGN_BOTTOM;
1097 else if (0 == strcmp ("Spreadoutvertically", a)) {
1098 align = DIA_ALIGN_EQUAL;
1100 else if (0 == strcmp ("Stacked", a)) {
1101 align = DIA_ALIGN_ADJACENT;
1103 else {
1104 g_warning ("objects_align_v_callback() called without appropriate align");
1105 return;
1108 dia = ddisplay_active_diagram();
1109 if (!dia) return;
1110 objects = dia->data->selected;
1112 object_add_updates_list(objects, dia);
1113 object_list_align_v(objects, dia, align);
1114 diagram_update_connections_selection(dia);
1115 object_add_updates_list(objects, dia);
1116 diagram_modified(dia);
1117 diagram_flush(dia);
1119 undo_set_transactionpoint(dia->undo);