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.
26 #include <sys/types.h>
31 #include <gdk-pixbuf/gdk-pixbuf.h>
34 /* Added by Andrew Ferrier: for use of gnome_about_new() */
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
47 ShellExecuteA (long hwnd
,
48 const char* lpOperation
,
50 const char* lpParameters
,
51 const char* lpDirectory
,
55 #include "paginate_psprint.h"
57 # include "paginate_gdiprint.h"
61 #include "app_procs.h"
64 #include "object_ops.h"
65 #include "cut_n_paste.h"
66 #include "load_save.h"
70 #include "properties.h"
71 #include "propinternals.h"
72 #include "preferences.h"
73 #include "layer_dialog.h"
74 #include "connectionpoint_ops.h"
76 #include "pagesetup.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 */
89 void file_quit_callback(gpointer data
, guint action
, GtkWidget
*widget
)
95 file_pagesetup_callback(gpointer data
, guint action
, GtkWidget
*widget
)
99 dia
= ddisplay_active_diagram();
101 create_page_setup_dlg(dia
);
105 file_print_callback(gpointer data
, guint action
, GtkWidget
*widget
)
109 dia
= ddisplay_active_diagram();
112 /* This option could be used with Gnome too. Does it make sense there ? */
113 if (!prefs
.prefer_psprint
)
114 diagram_print_gdi(dia
);
117 diagram_print_ps(dia
);
121 file_close_callback(gpointer data
, guint action
, GtkWidget
*widget
)
123 ddisplay_close(ddisplay_active());
127 file_new_callback(gpointer data
, guint action
, GtkWidget
*widget
)
131 static int untitled_nr
= 1;
134 g_snprintf(buffer
, 24, _("Diagram%d.dia"), untitled_nr
++);
136 dia
= new_diagram(buffer
);
137 ddisp
= new_display(dia
);
138 diagram_tree_add(diagram_tree(), dia
);
142 file_preferences_callback(gpointer data
, guint action
, GtkWidget
*widget
)
149 edit_copy_callback(gpointer data
, guint action
, GtkWidget
*widget
)
154 ddisp
= ddisplay_active();
156 copy_list
= parent_list_affected(diagram_get_sorted_selected(ddisp
->diagram
));
158 cnp_store_objects(object_copy_list(copy_list
));
159 g_list_free(copy_list
);
161 ddisplay_do_update_menu_sensitivity(ddisp
);
165 edit_cut_callback(gpointer data
, guint action
, GtkWidget
*widget
)
171 ddisp
= ddisplay_active();
174 diagram_selected_break_external(ddisp
->diagram
);
176 cut_list
= parent_list_affected(diagram_get_sorted_selected(ddisp
->diagram
));
178 cnp_store_objects(object_copy_list(cut_list
));
180 change
= undo_delete_objects_children(ddisp
->diagram
, cut_list
);
181 (change
->apply
)(change
, ddisp
->diagram
);
183 ddisplay_do_update_menu_sensitivity(ddisp
);
184 diagram_flush(ddisp
->diagram
);
187 diagram_modified(ddisp
->diagram
);
188 undo_set_transactionpoint(ddisp
->diagram
->undo
);
193 edit_paste_callback(gpointer data
, guint action
, GtkWidget
*widget
)
201 ddisp
= ddisplay_active();
204 if (!cnp_exist_stored_objects()) {
205 message_warning(_("No existing object to paste.\n"));
209 paste_list
= cnp_get_stored_objects(); /* Gets a copy */
211 paste_corner
= object_list_corner(paste_list
);
213 delta
.x
= ddisp
->visible
.left
- paste_corner
.x
;
214 delta
.y
= ddisp
->visible
.top
- paste_corner
.y
;
216 /* Move down some 10% of the visible area. */
217 delta
.x
+= (ddisp
->visible
.right
- ddisp
->visible
.left
)*0.1;
218 delta
.y
+= (ddisp
->visible
.bottom
- ddisp
->visible
.top
)*0.1;
220 object_list_move_delta(paste_list
, &delta
);
222 change
= undo_insert_objects(ddisp
->diagram
, paste_list
, 0);
223 (change
->apply
)(change
, ddisp
->diagram
);
225 diagram_modified(ddisp
->diagram
);
226 undo_set_transactionpoint(ddisp
->diagram
->undo
);
228 diagram_remove_all_selected(ddisp
->diagram
, TRUE
);
229 diagram_select_list(ddisp
->diagram
, paste_list
);
231 diagram_flush(ddisp
->diagram
);
235 * ALAN: Paste should probably paste to different position, feels
236 * wrong somehow. ALAN: The offset should increase a little each time
237 * if you paste/duplicate several times in a row, because it is
238 * clearer what is happening than if you were to piling them all in
241 * completely untested, basically it is copy+paste munged together
244 edit_duplicate_callback(gpointer data
, guint action
, GtkWidget
*widget
)
246 GList
*duplicate_list
;
248 Point duplicate_corner
;
252 ddisp
= ddisplay_active();
254 duplicate_list
= object_copy_list(diagram_get_sorted_selected(ddisp
->diagram
));
255 duplicate_corner
= object_list_corner(duplicate_list
);
257 /* Move down some 10% of the visible area. */
258 delta
.x
= (ddisp
->visible
.right
- ddisp
->visible
.left
)*0.05;
259 delta
.y
= (ddisp
->visible
.bottom
- ddisp
->visible
.top
)*0.05;
261 object_list_move_delta(duplicate_list
, &delta
);
263 change
= undo_insert_objects(ddisp
->diagram
, duplicate_list
, 0);
264 (change
->apply
)(change
, ddisp
->diagram
);
266 diagram_modified(ddisp
->diagram
);
267 undo_set_transactionpoint(ddisp
->diagram
->undo
);
269 diagram_remove_all_selected(ddisp
->diagram
, TRUE
);
270 diagram_select_list(ddisp
->diagram
, duplicate_list
);
272 diagram_flush(ddisp
->diagram
);
274 ddisplay_do_update_menu_sensitivity(ddisp
);
280 /* Signal handler for getting the clipboard contents */
281 /* Note that the clipboard is for M$-style cut/copy/paste copying, while
282 the selection is for Unix-style mark-and-copy. We can't really do
287 insert_text(DDisplay
*ddisp
, Focus
*focus
, const gchar
*text
)
289 ObjectChange
*change
= NULL
;
290 int modified
= FALSE
, any_modified
= FALSE
;
291 DiaObject
*obj
= focus
->obj
;
293 while (text
!= NULL
) {
294 gchar
*next_line
= g_utf8_strchr(text
, -1, '\n');
295 if (next_line
!= text
) {
296 gint len
= g_utf8_strlen(text
, (next_line
-text
));
297 modified
= (*focus
->key_event
)(focus
, GDK_A
, text
, len
, &change
);
299 if (next_line
!= NULL
) {
300 modified
= (*focus
->key_event
)(focus
, GDK_Return
, "\n", 1, &change
);
301 text
= g_utf8_next_char(next_line
);
305 { /* Make sure object updates its data: */
306 Point p
= obj
->position
;
307 (obj
->ops
->move
)(obj
,&p
); }
309 /* Perhaps this can be improved */
310 object_add_updates(obj
, ddisp
->diagram
);
312 if (modified
&& (change
!= NULL
)) {
313 undo_object_change(ddisp
->diagram
, obj
, change
);
317 diagram_flush(ddisp
->diagram
);
321 diagram_modified(ddisp
->diagram
);
322 undo_set_transactionpoint(ddisp
->diagram
->undo
);
328 received_clipboard_handler(GtkClipboard
*clipboard
,
331 Focus
*focus
= active_focus();
332 DDisplay
*ddisp
= (DDisplay
*)data
;
334 if (text
== NULL
) return;
336 if ((focus
== NULL
) || (!focus
->has_focus
)) return;
338 if (!g_utf8_validate(text
, -1, NULL
)) {
339 message_error("Not valid UTF8");
343 insert_text(ddisp
, focus
, text
);
346 static PropDescription text_prop_singleton_desc
[] = {
347 { "text", PROP_TYPE_TEXT
},
351 make_text_prop_singleton(GPtrArray
**props
, TextProperty
**prop
)
353 *props
= prop_list_from_descs(text_prop_singleton_desc
,pdtpp_true
);
354 g_assert((*props
)->len
== 1);
356 *prop
= g_ptr_array_index((*props
),0);
357 g_free((*prop
)->text_data
);
358 (*prop
)->text_data
= NULL
;
363 edit_copy_text_callback(gpointer data
, guint action
, GtkWidget
*widget
)
365 Focus
*focus
= active_focus();
368 GPtrArray
*textprops
;
371 if ((focus
== NULL
) || (!focus
->has_focus
)) return;
373 ddisp
= ddisplay_active();
378 if (obj
->ops
->get_props
== NULL
)
381 make_text_prop_singleton(&textprops
,&prop
);
382 /* Get the first text property */
383 obj
->ops
->get_props(obj
, textprops
);
385 /* GTK docs claim the selection clipboard is ignored on Win32.
386 * The "clipboard" clipboard is mostly ignored in Unix
389 gtk_clipboard_set_text(gtk_clipboard_get(GDK_NONE
),
390 prop
->text_data
, -1);
392 gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY
),
393 prop
->text_data
, -1);
395 prop_list_free(textprops
);
399 edit_cut_text_callback(gpointer data
, guint action
, GtkWidget
*widget
)
401 Focus
*focus
= active_focus();
405 GPtrArray
*textprops
;
407 ObjectChange
*change
;
409 if ((focus
== NULL
) || (!focus
->has_focus
)) return;
411 ddisp
= ddisplay_active();
415 text
= (Text
*)focus
->user_data
;
417 if (obj
->ops
->get_props
== NULL
)
420 make_text_prop_singleton(&textprops
,&prop
);
421 /* Get the first text property */
422 obj
->ops
->get_props(obj
, textprops
);
424 /* GTK docs claim the selection clipboard is ignored on Win32.
425 * The "clipboard" clipboard is mostly ignored in Unix
428 gtk_clipboard_set_text(gtk_clipboard_get(GDK_NONE
),
429 prop
->text_data
, -1);
431 gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY
),
432 prop
->text_data
, -1);
435 prop_list_free(textprops
);
437 if (text_delete_all(text
, &change
)) {
438 object_add_updates(obj
, ddisp
->diagram
);
439 undo_object_change(ddisp
->diagram
, obj
, change
);
440 undo_set_transactionpoint(ddisp
->diagram
->undo
);
441 diagram_modified(ddisp
->diagram
);
442 diagram_flush(ddisp
->diagram
);
447 edit_paste_text_callback(gpointer data
, guint action
, GtkWidget
*widget
)
451 ddisp
= ddisplay_active();
455 gtk_clipboard_request_text(gtk_clipboard_get(GDK_NONE
),
456 received_clipboard_handler
, ddisp
);
458 gtk_clipboard_request_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY
),
459 received_clipboard_handler
, ddisp
);
464 edit_delete_callback(gpointer data
, guint action
, GtkWidget
*widget
)
472 ddisp
= ddisplay_active();
475 diagram_selected_break_external(ddisp
->diagram
);
477 delete_list
= diagram_get_sorted_selected(ddisp
->diagram
);
478 change
= undo_delete_objects_children(ddisp
->diagram
, delete_list
);
479 (change
->apply
)(change
, ddisp
->diagram
);
480 g_list_free(delete_list
);
482 diagram_modified(ddisp
->diagram
);
484 ddisplay_do_update_menu_sensitivity(ddisp
);
485 diagram_flush(ddisp
->diagram
);
487 undo_set_transactionpoint(ddisp
->diagram
->undo
);
491 edit_undo_callback(gpointer data
, guint action
, GtkWidget
*widget
)
495 dia
= ddisplay_active_diagram();
498 undo_revert_to_last_tp(dia
->undo
);
499 diagram_modified(dia
);
505 edit_redo_callback(gpointer data
, guint action
, GtkWidget
*widget
)
509 dia
= ddisplay_active_diagram();
512 undo_apply_to_next_tp(dia
->undo
);
513 diagram_modified(dia
);
519 help_manual_callback(gpointer data
, guint action
, GtkWidget
*widget
)
521 char *helpdir
, *helpindex
= NULL
, *command
;
522 guint bestscore
= G_MAXINT
;
525 GError
*error
= NULL
;
527 helpdir
= dia_get_data_directory("help");
529 message_warning(_("Could not find help directory"));
533 /* search through helpdir for the helpfile that matches the user's locale */
534 dp
= g_dir_open (helpdir
, 0, &error
);
536 message_warning(_("Could not open help directory:\n%s"),
538 g_error_free (error
);
542 while ((dentry
= g_dir_read_name(dp
)) != NULL
) {
545 score
= intl_score_locale(dentry
);
546 if (score
< bestscore
) {
550 /* use HTML Help on win32 if available */
551 helpindex
= g_strconcat(helpdir
, G_DIR_SEPARATOR_S
, dentry
,
552 G_DIR_SEPARATOR_S
"dia-manual.chm", NULL
);
553 if (!g_file_test(helpindex
, G_FILE_TEST_EXISTS
)) {
554 helpindex
= g_strconcat(helpdir
, G_DIR_SEPARATOR_S
, dentry
,
555 G_DIR_SEPARATOR_S
"index.html", NULL
);
558 helpindex
= g_strconcat(helpdir
, G_DIR_SEPARATOR_S
, dentry
,
559 G_DIR_SEPARATOR_S
"index.html", NULL
);
567 message_warning(_("Could not find help directory"));
572 #define SW_SHOWNORMAL 1
573 ShellExecuteA (0, "open", helpindex
, NULL
, helpdir
, SW_SHOWNORMAL
);
575 command
= getenv("BROWSER");
576 command
= g_strdup_printf("%s 'file://%s' &", command
? command
: "netscape", helpindex
);
585 help_about_callback(gpointer data
, guint action
, GtkWidget
*widget
)
589 /* Take advantage of gnome_about_new(),
590 * which is much cleaner and GNOME2 HIG compliant,
591 * Originally implemented by Xing Wang, modified
594 * Note: in this function there is no need to discriminate
595 * between the different kinds of 'authors'.
598 static GtkWidget
*about
;
601 * Translators should localize the following string
602 * which will give them credit in the About box.
603 * E.g. "Fulano de Tal <fulano@detal.com>"
606 gchar
*translators
= _("translator_credits-PLEASE_ADD_YOURSELF_HERE");
607 gchar logo_file
[100];
612 gchar
* datadir
= dia_get_data_directory("");
613 g_snprintf(logo_file
, sizeof(logo_file
),
614 "%s%sdia_logo.png", datadir
, G_DIR_SEPARATOR_S
);
616 logo
= gdk_pixbuf_new_from_file(logo_file
, NULL
);
619 about
= gnome_about_new(
622 _("Copyright (C) 1998-2002 The Free Software Foundation and the authors"),
623 _("Dia is a program for drawing structured diagrams.\n"
624 "Please visit http://www.gnome.org/projects/dia for more information."),
627 (strcmp (translators
, "translator_credits-PLEASE_ADD_YOURSELF_HERE")
628 ? translators
: NULL
),
632 g_object_unref (logo
);
634 g_signal_connect (about
, "destroy",
635 G_CALLBACK (gtk_widget_destroyed
),
639 gtk_widget_show_now (about
);
643 /* No GNOME, fall back to the old GTK method */
645 const gint nauthors
= (sizeof(authors
) / sizeof(authors
[0])) - 1;
646 const gint ndocumentors
= (sizeof(documentors
) / sizeof(documentors
[0])) - 1;
660 dialog
= gtk_dialog_new ();
661 gtk_window_set_role (GTK_WINDOW (dialog
), "about_dialog");
662 gtk_window_set_title (GTK_WINDOW (dialog
), _("About Dia"));
663 gtk_window_set_resizable (GTK_WINDOW (dialog
), FALSE
);
664 gtk_window_set_position (GTK_WINDOW (dialog
), GTK_WIN_POS_CENTER
);
665 g_signal_connect (GTK_OBJECT (dialog
), "destroy",
666 G_CALLBACK (gtk_widget_destroy
),
667 GTK_OBJECT (dialog
));
669 vbox
= gtk_vbox_new (FALSE
, 1);
670 gtk_container_set_border_width (GTK_CONTAINER (vbox
), 5);
671 gtk_container_add (GTK_CONTAINER(GTK_DIALOG(dialog
)->vbox
), vbox
);
674 gchar
* datadir
= dia_get_data_directory("");
675 g_snprintf(str
, sizeof(str
), "%s%sdia_logo.png", datadir
, G_DIR_SEPARATOR_S
);
676 logo
= gdk_pixbuf_new_from_file(str
, NULL
);
684 frame
= gtk_frame_new (NULL
);
685 gtk_frame_set_shadow_type (GTK_FRAME (frame
), GTK_SHADOW_IN
);
686 gtk_container_set_border_width (GTK_CONTAINER (frame
), 1);
687 gtk_box_pack_start(GTK_BOX(vbox
), frame
, FALSE
, TRUE
, 1);
689 gdk_pixbuf_render_pixmap_and_mask(logo
, &pixmap
, &bitmap
, 128);
690 gpixmap
= gtk_pixmap_new(pixmap
, bitmap
);
691 gdk_pixmap_unref(pixmap
);
692 if (bitmap
) gdk_bitmap_unref(bitmap
);
693 gtk_container_add (GTK_CONTAINER(frame
), gpixmap
);
696 frame
= gtk_frame_new (NULL
);
697 gtk_frame_set_shadow_type (GTK_FRAME (frame
), GTK_SHADOW_IN
);
698 gtk_container_set_border_width (GTK_CONTAINER (frame
), 1);
699 gtk_box_pack_start(GTK_BOX(vbox
), frame
, FALSE
, TRUE
, 1);
701 table
= gtk_table_new(3, 2, FALSE
);
702 gtk_container_set_border_width (GTK_CONTAINER (table
), 1);
703 gtk_container_add (GTK_CONTAINER (frame
), table
);
705 g_snprintf(str
, sizeof(str
), _("Dia v %s by Alexander Larsson"), VERSION
);
706 label
= gtk_label_new (str
);
707 gtk_table_attach(GTK_TABLE(table
), label
, 0,2, 0,1,
708 GTK_FILL
|GTK_EXPAND
, GTK_FILL
, 0,2);
710 /* Exact spelling is Chépélov (using *ML entities) */
711 label
= gtk_label_new(_("Maintainers: Lars Clausen and Cyrille Chepelov"));
712 gtk_table_attach(GTK_TABLE(table
), label
, 0,2, 1,2,
713 GTK_FILL
|GTK_EXPAND
, GTK_FILL
, 0,2);
715 label
= gtk_label_new (_("Please visit http://www.gnome.org/projects/dia "
716 "for more information"));
717 gtk_table_attach(GTK_TABLE(table
), label
, 0,2, 2,3,
718 GTK_FILL
|GTK_EXPAND
, GTK_FILL
, 0,2);
720 label
= gtk_label_new (_("Contributors:"));
721 gtk_table_attach(GTK_TABLE(table
), label
, 0,2, 3,4,
722 GTK_FILL
|GTK_EXPAND
, GTK_FILL
, 0,2);
724 for (i
= 0; i
< nauthors
; i
++) {
725 label
= gtk_label_new(authors
[i
]);
726 gtk_table_attach(GTK_TABLE(table
), label
, i
%2,i
%2+1, i
/2+4,i
/2+5,
727 GTK_FILL
|GTK_EXPAND
, GTK_FILL
, 0,0);
730 for (i
= nauthors
; i
< nauthors
+ ndocumentors
; i
++) {
731 label
= gtk_label_new(documentors
[i
- nauthors
]);
732 gtk_table_attach(GTK_TABLE(table
), label
, i
%2,i
%2+1, i
/2+4,i
/2+5,
733 GTK_FILL
|GTK_EXPAND
, GTK_FILL
, 0,0);
736 gtk_table_set_col_spacings(GTK_TABLE(table
), 1);
737 gtk_table_set_row_spacings(GTK_TABLE(table
), 1);
739 bbox
= gtk_hbutton_box_new();
740 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog
)->action_area
), bbox
, TRUE
, TRUE
, 5);
741 gtk_button_box_set_child_size(GTK_BUTTON_BOX(bbox
), 80, 0);
742 gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox
), 10);
744 button
= gtk_button_new_from_stock(GTK_STOCK_OK
);
745 gtk_container_add(GTK_CONTAINER(bbox
), button
);
746 g_signal_connect_swapped(GTK_OBJECT (button
), "clicked",
747 G_CALLBACK(gtk_widget_destroy
),
750 gtk_widget_show_all (dialog
);
756 view_zoom_in_callback(gpointer data
, guint action
, GtkWidget
*widget
)
762 ddisp
= ddisplay_active();
764 visible
= &ddisp
->visible
;
765 middle
.x
= visible
->left
*0.5 + visible
->right
*0.5;
766 middle
.y
= visible
->top
*0.5 + visible
->bottom
*0.5;
768 ddisplay_zoom(ddisp
, &middle
, M_SQRT2
);
772 view_zoom_out_callback(gpointer data
, guint action
, GtkWidget
*widget
)
778 ddisp
= ddisplay_active();
780 visible
= &ddisp
->visible
;
781 middle
.x
= visible
->left
*0.5 + visible
->right
*0.5;
782 middle
.y
= visible
->top
*0.5 + visible
->bottom
*0.5;
784 ddisplay_zoom(ddisp
, &middle
, M_SQRT1_2
);
788 view_zoom_set_callback(gpointer data
, guint action
, GtkWidget
*widget
)
795 ddisp
= ddisplay_active();
797 visible
= &ddisp
->visible
;
798 middle
.x
= visible
->left
*0.5 + visible
->right
*0.5;
799 middle
.y
= visible
->top
*0.5 + visible
->bottom
*0.5;
801 scale
= ((real
) action
)/1000.0 * DDISPLAY_NORMAL_ZOOM
;
803 ddisplay_zoom(ddisp
, &middle
, scale
/ ddisp
->zoom_factor
);
807 view_show_cx_pts_callback(gpointer data
, guint action
, GtkWidget
*widget
)
812 ddisp
= ddisplay_active();
815 old_val
= ddisp
->show_cx_pts
;
816 ddisp
->show_cx_pts
= GTK_CHECK_MENU_ITEM(widget
)->active
;
818 if (old_val
!= ddisp
->show_cx_pts
) {
819 ddisplay_add_update_all(ddisp
);
820 ddisplay_flush(ddisp
);
825 view_aa_callback(gpointer data
, guint action
, GtkWidget
*widget
)
830 ddisp
= ddisplay_active();
833 aa
= GTK_CHECK_MENU_ITEM(widget
)->active
;
835 if (aa
!= ddisp
->aa_renderer
) {
836 ddisplay_set_renderer(ddisp
, aa
);
837 ddisplay_add_update_all(ddisp
);
838 ddisplay_flush(ddisp
);
843 view_visible_grid_callback(gpointer data
, guint action
, GtkWidget
*widget
)
848 ddisp
= ddisplay_active();
851 old_val
= ddisp
->grid
.visible
;
852 ddisp
->grid
.visible
= GTK_CHECK_MENU_ITEM(widget
)->active
;
854 if (old_val
!= ddisp
->grid
.visible
) {
855 ddisplay_add_update_all(ddisp
);
856 ddisplay_flush(ddisp
);
861 view_snap_to_grid_callback(gpointer data
, guint action
, GtkWidget
*widget
)
865 ddisp
= ddisplay_active();
868 ddisplay_set_snap_to_grid(ddisp
, GTK_CHECK_MENU_ITEM(widget
)->active
);
871 void view_toggle_rulers_callback(gpointer data
, guint action
, GtkWidget
*widget
)
875 ddisp
= ddisplay_active();
878 /* The following is borrowed straight from the Gimp: */
880 /* This routine use promiscuous knowledge of gtk internals
881 * in order to hide and show the rulers "smoothly". This
882 * is kludgy and a hack and may break if gtk is changed
885 if (!GTK_CHECK_MENU_ITEM(widget
)->active
) {
886 if (GTK_WIDGET_VISIBLE (ddisp
->origin
)) {
887 gtk_widget_unmap (ddisp
->origin
);
888 gtk_widget_unmap (ddisp
->hrule
);
889 gtk_widget_unmap (ddisp
->vrule
);
891 GTK_WIDGET_UNSET_FLAGS (ddisp
->origin
, GTK_VISIBLE
);
892 GTK_WIDGET_UNSET_FLAGS (ddisp
->hrule
, GTK_VISIBLE
);
893 GTK_WIDGET_UNSET_FLAGS (ddisp
->vrule
, GTK_VISIBLE
);
895 gtk_widget_queue_resize (GTK_WIDGET (ddisp
->origin
->parent
));
898 if (!GTK_WIDGET_VISIBLE (ddisp
->origin
)) {
899 GTK_WIDGET_SET_FLAGS (ddisp
->origin
, GTK_VISIBLE
);
900 GTK_WIDGET_SET_FLAGS (ddisp
->hrule
, GTK_VISIBLE
);
901 GTK_WIDGET_SET_FLAGS (ddisp
->vrule
, GTK_VISIBLE
);
903 gtk_widget_map (ddisp
->origin
);
904 gtk_widget_map (ddisp
->hrule
);
905 gtk_widget_map (ddisp
->vrule
);
907 gtk_widget_queue_resize (GTK_WIDGET (ddisp
->origin
->parent
));
913 view_new_view_callback(gpointer data
, guint action
, GtkWidget
*widget
)
917 dia
= ddisplay_active_diagram();
924 view_show_all_callback(gpointer data
, guint action
, GtkWidget
*widget
)
928 real magnify_x
, magnify_y
;
932 ddisp
= ddisplay_active();
934 dia
= ddisp
->diagram
;
936 width
= dia_renderer_get_width_pixels (ddisp
->renderer
);
937 height
= dia_renderer_get_height_pixels (ddisp
->renderer
);
939 magnify_x
= (real
)width
/
940 (dia
->data
->extents
.right
- dia
->data
->extents
.left
) / ddisp
->zoom_factor
;
941 magnify_y
= (real
)height
/
942 (dia
->data
->extents
.bottom
- dia
->data
->extents
.top
) / ddisp
->zoom_factor
;
944 middle
.x
= dia
->data
->extents
.left
+
945 (dia
->data
->extents
.right
- dia
->data
->extents
.left
) / 2.0;
946 middle
.y
= dia
->data
->extents
.top
+
947 (dia
->data
->extents
.bottom
- dia
->data
->extents
.top
) / 2.0;
949 ddisplay_zoom (ddisp
, &middle
, (magnify_x
<magnify_y
)?magnify_x
:magnify_y
);
951 ddisplay_update_scrollbars(ddisp
);
952 ddisplay_add_update_all(ddisp
);
953 ddisplay_flush(ddisp
);
957 view_redraw_callback(gpointer data
, guint action
, GtkWidget
*widget
)
960 ddisp
= ddisplay_active();
962 ddisplay_add_update_all(ddisp
);
963 ddisplay_flush(ddisp
);
967 view_diagram_properties_callback(gpointer data
, guint action
, GtkWidget
*widget
)
971 ddisp
= ddisplay_active();
973 diagram_properties_show(ddisp
->diagram
);
978 objects_place_over_callback(gpointer data
, guint action
, GtkWidget
*widget
)
980 diagram_place_over_selected(ddisplay_active_diagram());
984 objects_place_under_callback(gpointer data
, guint action
, GtkWidget
*widget
)
986 diagram_place_under_selected(ddisplay_active_diagram());
990 objects_place_up_callback(gpointer data
, guint action
, GtkWidget
*widget
)
992 diagram_place_up_selected(ddisplay_active_diagram());
996 objects_place_down_callback(gpointer data
, guint action
, GtkWidget
*widget
)
998 diagram_place_down_selected(ddisplay_active_diagram());
1002 objects_parent_callback(gpointer data
, guint action
, GtkWidget
*widget
)
1004 diagram_parent_selected(ddisplay_active_diagram());
1008 objects_unparent_callback(gpointer data
, guint action
, GtkWidget
*widget
)
1010 diagram_unparent_selected(ddisplay_active_diagram());
1014 objects_unparent_children_callback(gpointer data
, guint action
, GtkWidget
*widget
)
1016 diagram_unparent_children_selected(ddisplay_active_diagram());
1020 objects_group_callback(gpointer data
, guint action
, GtkWidget
*widget
)
1022 diagram_group_selected(ddisplay_active_diagram());
1026 objects_ungroup_callback(gpointer data
, guint action
, GtkWidget
*widget
)
1028 diagram_ungroup_selected(ddisplay_active_diagram());
1032 dialogs_properties_callback(gpointer data
, guint action
, GtkWidget
*widget
)
1035 DiaObject
*selected
;
1037 dia
= ddisplay_active_diagram();
1040 if (dia
->data
->selected
!= NULL
) {
1041 selected
= dia
->data
->selected
->data
;
1042 properties_show(dia
, selected
);
1044 diagram_properties_show(dia
);
1049 dialogs_layers_callback(gpointer data
, guint action
, GtkWidget
*widget
)
1051 layer_dialog_set_diagram(ddisplay_active_diagram());
1052 layer_dialog_show();
1057 objects_align_h_callback(gpointer data
, guint action
, GtkWidget
*widget
)
1065 dia
= ddisplay_active_diagram();
1067 objects
= dia
->data
->selected
;
1069 object_add_updates_list(objects
, dia
);
1070 object_list_align_h(objects
, dia
, align
);
1071 diagram_update_connections_selection(dia
);
1072 object_add_updates_list(objects
, dia
);
1073 diagram_modified(dia
);
1076 undo_set_transactionpoint(dia
->undo
);
1080 objects_align_v_callback(gpointer data
, guint action
, GtkWidget
*widget
)
1088 dia
= ddisplay_active_diagram();
1090 objects
= dia
->data
->selected
;
1092 object_add_updates_list(objects
, dia
);
1093 object_list_align_v(objects
, dia
, align
);
1094 diagram_update_connections_selection(dia
);
1095 object_add_updates_list(objects
, dia
);
1096 diagram_modified(dia
);
1099 undo_set_transactionpoint(dia
->undo
);