fixed dia_image_rgb_data() for non-alpha images
[dia.git] / app / commands.c
blob55075c271cff52709a9e6b8c92a906172e23a8bb
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, _("Untitled-%d"), 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 = 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 = diagram_get_sorted_selected(ddisp->diagram);
174 cnp_store_objects(object_copy_list(cut_list));
176 change = undo_delete_objects(ddisp->diagram, cut_list);
177 (change->apply)(change, ddisp->diagram);
179 ddisplay_do_update_menu_sensitivity(ddisp);
180 diagram_flush(ddisp->diagram);
182 diagram_modified(ddisp->diagram);
183 undo_set_transactionpoint(ddisp->diagram->undo);
186 void
187 edit_paste_callback(gpointer data, guint action, GtkWidget *widget)
189 GList *paste_list;
190 DDisplay *ddisp;
191 Point paste_corner;
192 Point delta;
193 Change *change;
195 ddisp = ddisplay_active();
197 if (!cnp_exist_stored_objects()) {
198 message_warning(_("No existing object to paste.\n"));
199 return;
202 paste_list = cnp_get_stored_objects(); /* Gets a copy */
204 paste_corner = object_list_corner(paste_list);
206 delta.x = ddisp->visible.left - paste_corner.x;
207 delta.y = ddisp->visible.top - paste_corner.y;
209 /* Move down some 10% of the visible area. */
210 delta.x += (ddisp->visible.right - ddisp->visible.left)*0.1;
211 delta.y += (ddisp->visible.bottom - ddisp->visible.top)*0.1;
213 object_list_move_delta(paste_list, &delta);
215 change = undo_insert_objects(ddisp->diagram, paste_list, 0);
216 (change->apply)(change, ddisp->diagram);
218 diagram_modified(ddisp->diagram);
219 undo_set_transactionpoint(ddisp->diagram->undo);
221 diagram_remove_all_selected(ddisp->diagram, TRUE);
222 diagram_select_list(ddisp->diagram, paste_list);
224 diagram_flush(ddisp->diagram);
227 /* Signal handler for getting the clipboard contents */
228 /* Note that the clipboard is for M$-style cut/copy/paste copying, while
229 the selection is for Unix-style mark-and-copy. We can't really do
230 mark-and-copy.
233 static void
234 insert_text(DDisplay *ddisp, Focus *focus, const gchar *text)
236 ObjectChange *change = NULL;
237 int modified = FALSE, any_modified = FALSE;
238 Object *obj = focus->obj;
240 while (text != NULL) {
241 gchar *next_line = g_utf8_strchr(text, -1, '\n');
242 if (next_line != text) {
243 gint len = g_utf8_strlen(text, (next_line-text));
244 modified = (*focus->key_event)(focus, GDK_A, text, len, &change);
246 if (next_line != NULL) {
247 modified = (*focus->key_event)(focus, GDK_Return, "\n", 1, &change);
248 text = g_utf8_next_char(next_line);
249 } else {
250 text = NULL;
252 { /* Make sure object updates its data: */
253 Point p = obj->position;
254 (obj->ops->move)(obj,&p); }
256 /* Perhaps this can be improved */
257 object_add_updates(obj, ddisp->diagram);
259 if (modified && (change != NULL)) {
260 undo_object_change(ddisp->diagram, obj, change);
261 any_modified = TRUE;
264 diagram_flush(ddisp->diagram);
267 if (any_modified)
268 undo_set_transactionpoint(ddisp->diagram->undo);
272 static void
273 received_clipboard_handler(GtkClipboard *clipboard,
274 const gchar *text,
275 gpointer data) {
276 Focus *focus = active_focus();
277 DDisplay *ddisp = (DDisplay *)data;
279 if (text == NULL) return;
281 if ((focus == NULL) || (!focus->has_focus)) return;
283 if (!g_utf8_validate(text, -1, NULL)) {
284 message_error("Not valid UTF8");
285 return;
288 insert_text(ddisp, focus, text);
291 static PropDescription text_prop_singleton_desc[] = {
292 { "text", PROP_TYPE_TEXT },
293 PROP_DESC_END};
295 static void
296 make_text_prop_singleton(GPtrArray **props, TextProperty **prop)
298 *props = prop_list_from_descs(text_prop_singleton_desc,pdtpp_true);
299 g_assert((*props)->len == 1);
301 *prop = g_ptr_array_index((*props),0);
302 g_free((*prop)->text_data);
303 (*prop)->text_data = NULL;
307 void
308 edit_copy_text_callback(gpointer data, guint action, GtkWidget *widget)
310 Focus *focus = active_focus();
311 DDisplay *ddisp;
312 Object *obj;
313 GPtrArray *textprops;
314 TextProperty *prop;
316 if ((focus == NULL) || (!focus->has_focus)) return;
318 ddisp = ddisplay_active();
320 obj = focus->obj;
322 if (obj->ops->get_props == NULL)
323 return;
325 make_text_prop_singleton(&textprops,&prop);
326 /* Get the first text property */
327 obj->ops->get_props(obj, textprops);
329 /* GTK docs claim the selection clipboard is ignored on Win32.
330 * The "clipboard" clipboard is mostly ignored in Unix
332 #ifdef G_OS_WIN32
333 gtk_clipboard_set_text(gtk_clipboard_get(GDK_NONE),
334 prop->text_data, -1);
335 #else
336 gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY),
337 prop->text_data, -1);
338 #endif
339 prop_list_free(textprops);
342 void
343 edit_cut_text_callback(gpointer data, guint action, GtkWidget *widget)
345 Focus *focus = active_focus();
346 DDisplay *ddisp;
347 Object *obj;
348 Text *text;
349 GPtrArray *textprops;
350 TextProperty *prop;
351 ObjectChange *change;
353 if ((focus == NULL) || (!focus->has_focus)) return;
355 ddisp = ddisplay_active();
357 obj = focus->obj;
358 text = (Text *)focus->user_data;
360 if (obj->ops->get_props == NULL)
361 return;
363 make_text_prop_singleton(&textprops,&prop);
364 /* Get the first text property */
365 obj->ops->get_props(obj, textprops);
367 /* GTK docs claim the selection clipboard is ignored on Win32.
368 * The "clipboard" clipboard is mostly ignored in Unix
370 #ifdef G_OS_WIN32
371 gtk_clipboard_set_text(gtk_clipboard_get(GDK_NONE),
372 prop->text_data, -1);
373 #else
374 gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY),
375 prop->text_data, -1);
376 #endif
378 prop_list_free(textprops);
380 if (text_delete_all(text, &change)) {
381 object_add_updates(obj, ddisp->diagram);
382 undo_object_change(ddisp->diagram, obj, change);
383 undo_set_transactionpoint(ddisp->diagram->undo);
384 diagram_flush(ddisp->diagram);
388 void
389 edit_paste_text_callback(gpointer data, guint action, GtkWidget *widget)
391 DDisplay *ddisp;
393 ddisp = ddisplay_active();
395 #ifdef G_OS_WIN32
396 gtk_clipboard_request_text(gtk_clipboard_get(GDK_NONE),
397 received_clipboard_handler, ddisp);
398 #else
399 gtk_clipboard_request_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY),
400 received_clipboard_handler, ddisp);
401 #endif
404 void
405 edit_delete_callback(gpointer data, guint action, GtkWidget *widget)
407 GList *delete_list;
408 DDisplay *ddisp;
410 Change *change;
412 ddisp = ddisplay_active();
414 diagram_selected_break_external(ddisp->diagram);
416 delete_list = diagram_get_sorted_selected(ddisp->diagram);
418 change = undo_delete_objects(ddisp->diagram, delete_list);
419 (change->apply)(change, ddisp->diagram);
421 diagram_modified(ddisp->diagram);
423 ddisplay_do_update_menu_sensitivity(ddisp);
424 diagram_flush(ddisp->diagram);
426 undo_set_transactionpoint(ddisp->diagram->undo);
429 void
430 edit_undo_callback(gpointer data, guint action, GtkWidget *widget)
432 DDisplay *ddisp;
433 Diagram *dia;
435 ddisp = ddisplay_active();
436 dia = ddisp->diagram;
438 undo_revert_to_last_tp(dia->undo);
440 diagram_flush(dia);
443 void
444 edit_redo_callback(gpointer data, guint action, GtkWidget *widget)
446 DDisplay *ddisp;
447 Diagram *dia;
449 ddisp = ddisplay_active();
450 dia = ddisp->diagram;
452 undo_apply_to_next_tp(dia->undo);
454 diagram_flush(dia);
457 void
458 help_manual_callback(gpointer data, guint action, GtkWidget *widget)
460 char *helpdir, *helpindex = NULL, *command;
461 guint bestscore = G_MAXINT;
462 GDir *dp;
463 const char *dentry;
464 GError *error = NULL;
466 helpdir = dia_get_data_directory("help");
467 if (!helpdir) {
468 message_warning(_("Could not find help directory"));
469 return;
472 /* search through helpdir for the helpfile that matches the user's locale */
473 dp = g_dir_open (helpdir, 0, &error);
474 if (!dp) {
475 message_warning(_("Could not open help directory:\n%s"),
476 error->message);
477 g_error_free (error);
478 return;
481 while ((dentry = g_dir_read_name(dp)) != NULL) {
482 guint score;
484 score = intl_score_locale(dentry);
485 if (score < bestscore) {
486 if (helpindex)
487 g_free(helpindex);
488 helpindex = g_strconcat(helpdir, G_DIR_SEPARATOR_S, dentry,
489 G_DIR_SEPARATOR_S "index.html", NULL);
490 bestscore = score;
493 g_dir_close (dp);
494 g_free(helpdir);
495 if (!helpindex) {
496 message_warning(_("Could not find help directory"));
497 return;
500 #ifdef G_OS_WIN32
501 ShellExecuteA (0, NULL, helpindex, NULL, helpdir, 0);
502 #else
503 command = getenv("BROWSER");
504 if (command == NULL)
505 command = g_strdup_printf("netscape");
506 command = g_strdup_printf("%s '%s' &", command, helpindex);
507 system(command);
508 g_free(command);
509 #endif
511 g_free(helpindex);
514 void
515 help_about_callback(gpointer data, guint action, GtkWidget *widget)
517 #ifdef GNOME
519 /* Take advantage of gnome_about_new(),
520 * which is much cleaner and GNOME2 HIG compliant,
521 * Originally implemented by Xing Wang, modified
522 * by Andrew Ferrier.
524 * Note: in this function there is no need to discriminate
525 * between the different kinds of 'authors'.
528 static GtkWidget *about;
531 * Translators should localize the following string
532 * which will give them credit in the About box.
533 * E.g. "Fulano de Tal <fulano@detal.com>"
536 gchar *translators = _("translator_credits-PLEASE_ADD_YOURSELF_HERE");
537 gchar logo_file[100];
539 if (!about) {
540 GdkPixbuf *logo;
542 gchar* datadir = dia_get_data_directory("");
543 g_snprintf(logo_file, sizeof(logo_file),
544 "%s%sdia_logo.png", datadir, G_DIR_SEPARATOR_S);
546 logo = gdk_pixbuf_new_from_file(logo_file, NULL);
547 g_free(datadir);
549 about = gnome_about_new(
550 _("Dia"),
551 VERSION,
552 _("Copyright (C) 1998-2002 The Free Software Foundation and the authors"),
553 _("Dia is a program for drawing structured diagrams.\n"
554 "Please visit http://www.lysator.liu.se/~alla/dia for more information."),
555 authors,
556 documentors,
557 (strcmp (translators, "translator_credits-PLEASE_ADD_YOURSELF_HERE")
558 ? translators : NULL),
559 logo);
561 if (logo)
562 g_object_unref (logo);
564 g_signal_connect (about, "destroy",
565 G_CALLBACK (gtk_widget_destroyed),
566 &about);
569 gtk_widget_show_now (about);
571 #else
573 /* No GNOME, fall back to the old GTK method */
575 const gint nauthors = (sizeof(authors) / sizeof(authors[0])) - 1;
576 const gint ndocumentors = (sizeof(documentors) / sizeof(documentors[0])) - 1;
578 GtkWidget *dialog;
579 GtkWidget *vbox;
580 GtkWidget *table;
581 GtkWidget *bbox;
582 GtkWidget *frame;
583 GtkWidget *label;
584 GtkWidget *button;
585 char str[100];
586 gint i;
588 GtkWidget *gpixmap;
590 dialog = gtk_dialog_new ();
591 gtk_window_set_role (GTK_WINDOW (dialog), "about_dialog");
592 gtk_window_set_title (GTK_WINDOW (dialog), _("About Dia"));
593 gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
594 gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
595 gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
596 GTK_SIGNAL_FUNC (gtk_widget_destroy),
597 GTK_OBJECT (dialog));
599 vbox = gtk_vbox_new (FALSE, 1);
600 gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
601 gtk_container_add (GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), vbox);
603 if (!logo) {
604 gchar* datadir = dia_get_data_directory("");
605 g_snprintf(str, sizeof(str), "%s%sdia_logo.png", datadir, G_DIR_SEPARATOR_S);
606 logo = gdk_pixbuf_new_from_file(str, NULL);
607 g_free(datadir);
610 if (logo) {
611 GdkPixmap *pixmap;
612 GdkBitmap *bitmap;
614 frame = gtk_frame_new (NULL);
615 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
616 gtk_container_set_border_width (GTK_CONTAINER (frame), 1);
617 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, TRUE, 1);
619 gdk_pixbuf_render_pixmap_and_mask(logo, &pixmap, &bitmap, 128);
620 gpixmap = gtk_pixmap_new(pixmap, bitmap);
621 gdk_pixmap_unref(pixmap);
622 if (bitmap) gdk_bitmap_unref(bitmap);
623 gtk_container_add (GTK_CONTAINER(frame), gpixmap);
626 frame = gtk_frame_new (NULL);
627 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
628 gtk_container_set_border_width (GTK_CONTAINER (frame), 1);
629 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, TRUE, 1);
631 table = gtk_table_new(3, 2, FALSE);
632 gtk_container_set_border_width (GTK_CONTAINER (table), 1);
633 gtk_container_add (GTK_CONTAINER (frame), table);
635 g_snprintf(str, sizeof(str), _("Dia v %s by Alexander Larsson"), VERSION);
636 label = gtk_label_new (str);
637 gtk_table_attach(GTK_TABLE(table), label, 0,2, 0,1,
638 GTK_FILL|GTK_EXPAND, GTK_FILL, 0,2);
640 /* Exact spelling is Ch&eacute;p&eacute;lov (using *ML entities) */
641 label = gtk_label_new(_("Maintainers: Lars Clausen and Cyrille Chepelov"));
642 gtk_table_attach(GTK_TABLE(table), label, 0,2, 1,2,
643 GTK_FILL|GTK_EXPAND, GTK_FILL, 0,2);
645 label = gtk_label_new (_("Please visit http://www.lysator.liu.se/~alla/dia "
646 "for more information"));
647 gtk_table_attach(GTK_TABLE(table), label, 0,2, 2,3,
648 GTK_FILL|GTK_EXPAND, GTK_FILL, 0,2);
650 label = gtk_label_new (_("Contributors:"));
651 gtk_table_attach(GTK_TABLE(table), label, 0,2, 3,4,
652 GTK_FILL|GTK_EXPAND, GTK_FILL, 0,2);
654 for (i = 0; i < nauthors; i++) {
655 label = gtk_label_new(authors[i]);
656 gtk_table_attach(GTK_TABLE(table), label, i%2,i%2+1, i/2+4,i/2+5,
657 GTK_FILL|GTK_EXPAND, GTK_FILL, 0,0);
660 for (i = nauthors; i < nauthors + ndocumentors; i++) {
661 label = gtk_label_new(documentors[i - nauthors]);
662 gtk_table_attach(GTK_TABLE(table), label, i%2,i%2+1, i/2+4,i/2+5,
663 GTK_FILL|GTK_EXPAND, GTK_FILL, 0,0);
666 gtk_table_set_col_spacings(GTK_TABLE(table), 1);
667 gtk_table_set_row_spacings(GTK_TABLE(table), 1);
669 bbox = gtk_hbutton_box_new();
670 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), bbox, TRUE, TRUE, 5);
671 gtk_button_box_set_child_size(GTK_BUTTON_BOX(bbox), 80, 0);
672 gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 10);
674 button = gtk_button_new_from_stock(GTK_STOCK_OK);
675 gtk_container_add(GTK_CONTAINER(bbox), button);
676 gtk_signal_connect_object(GTK_OBJECT (button), "clicked",
677 GTK_SIGNAL_FUNC(gtk_widget_destroy),
678 GTK_OBJECT(dialog));
680 gtk_widget_show_all (dialog);
682 #endif /* GNOME */
685 void
686 view_zoom_in_callback(gpointer data, guint action, GtkWidget *widget)
688 DDisplay *ddisp;
689 Point middle;
690 Rectangle *visible;
692 ddisp = ddisplay_active();
693 visible = &ddisp->visible;
694 middle.x = visible->left*0.5 + visible->right*0.5;
695 middle.y = visible->top*0.5 + visible->bottom*0.5;
697 ddisplay_zoom(ddisp, &middle, M_SQRT2);
700 void
701 view_zoom_out_callback(gpointer data, guint action, GtkWidget *widget)
703 DDisplay *ddisp;
704 Point middle;
705 Rectangle *visible;
707 ddisp = ddisplay_active();
708 visible = &ddisp->visible;
709 middle.x = visible->left*0.5 + visible->right*0.5;
710 middle.y = visible->top*0.5 + visible->bottom*0.5;
712 ddisplay_zoom(ddisp, &middle, M_SQRT1_2);
715 void
716 view_zoom_set_callback(gpointer data, guint action, GtkWidget *widget)
718 DDisplay *ddisp;
719 real scale;
720 Point middle;
721 Rectangle *visible;
723 ddisp = ddisplay_active();
724 visible = &ddisp->visible;
725 middle.x = visible->left*0.5 + visible->right*0.5;
726 middle.y = visible->top*0.5 + visible->bottom*0.5;
728 scale = ((real) action)/1000.0 * DDISPLAY_NORMAL_ZOOM;
730 ddisplay_zoom(ddisp, &middle, scale / ddisp->zoom_factor);
733 void
734 view_show_cx_pts_callback(gpointer data, guint action, GtkWidget *widget)
736 DDisplay *ddisp;
737 int old_val;
739 ddisp = ddisplay_active();
741 old_val = ddisp->show_cx_pts;
742 ddisp->show_cx_pts = GTK_CHECK_MENU_ITEM(widget)->active;
744 if (old_val != ddisp->show_cx_pts) {
745 ddisplay_add_update_all(ddisp);
746 ddisplay_flush(ddisp);
750 void
751 view_aa_callback(gpointer data, guint action, GtkWidget *widget)
753 DDisplay *ddisp;
754 int aa;
755 static gboolean shown_warning = FALSE;
757 ddisp = ddisplay_active();
759 aa = GTK_CHECK_MENU_ITEM(widget)->active;
761 if (aa && !shown_warning)
762 message_warning(_("The anti aliased renderer is buggy, and may cause\n"
763 "crashes. We know there are bugs in it, so don't\n"
764 "bother submitting another report if it crashes"));
765 shown_warning = TRUE;
767 if (aa != ddisp->aa_renderer) {
768 ddisplay_set_renderer(ddisp, aa);
769 ddisplay_add_update_all(ddisp);
770 ddisplay_flush(ddisp);
774 void
775 view_visible_grid_callback(gpointer data, guint action, GtkWidget *widget)
777 DDisplay *ddisp;
778 int old_val;
780 ddisp = ddisplay_active();
782 old_val = ddisp->grid.visible;
783 ddisp->grid.visible = GTK_CHECK_MENU_ITEM(widget)->active;
785 if (old_val != ddisp->grid.visible) {
786 ddisplay_add_update_all(ddisp);
787 ddisplay_flush(ddisp);
791 void
792 view_snap_to_grid_callback(gpointer data, guint action, GtkWidget *widget)
794 DDisplay *ddisp;
795 int old_val;
797 ddisp = ddisplay_active();
799 old_val = ddisp->grid.snap;
800 ddisp->grid.snap = GTK_CHECK_MENU_ITEM(widget)->active;
803 void view_toggle_rulers_callback(gpointer data, guint action, GtkWidget*widget)
805 DDisplay *ddisp;
807 ddisp = ddisplay_active();
809 /* The following is borrowed straight from the Gimp: */
811 /* This routine use promiscuous knowledge of gtk internals
812 * in order to hide and show the rulers "smoothly". This
813 * is kludgy and a hack and may break if gtk is changed
814 * internally.
816 if (!GTK_CHECK_MENU_ITEM(widget)->active) {
817 if (GTK_WIDGET_VISIBLE (ddisp->origin)) {
818 gtk_widget_unmap (ddisp->origin);
819 gtk_widget_unmap (ddisp->hrule);
820 gtk_widget_unmap (ddisp->vrule);
822 GTK_WIDGET_UNSET_FLAGS (ddisp->origin, GTK_VISIBLE);
823 GTK_WIDGET_UNSET_FLAGS (ddisp->hrule, GTK_VISIBLE);
824 GTK_WIDGET_UNSET_FLAGS (ddisp->vrule, GTK_VISIBLE);
826 gtk_widget_queue_resize (GTK_WIDGET (ddisp->origin->parent));
828 } else {
829 if (!GTK_WIDGET_VISIBLE (ddisp->origin)) {
830 GTK_WIDGET_SET_FLAGS (ddisp->origin, GTK_VISIBLE);
831 GTK_WIDGET_SET_FLAGS (ddisp->hrule, GTK_VISIBLE);
832 GTK_WIDGET_SET_FLAGS (ddisp->vrule, GTK_VISIBLE);
834 gtk_widget_map (ddisp->origin);
835 gtk_widget_map (ddisp->hrule);
836 gtk_widget_map (ddisp->vrule);
838 gtk_widget_queue_resize (GTK_WIDGET (ddisp->origin->parent));
843 extern void
844 view_new_view_callback(gpointer data, guint action, GtkWidget *widget)
846 DDisplay *ddisp;
847 Diagram *dia;
849 ddisp = ddisplay_active();
850 dia = ddisp->diagram;
852 ddisp = new_display(dia);
855 void
856 view_show_all_callback(gpointer data, guint action, GtkWidget *widget)
858 DDisplay *ddisp;
859 Diagram *dia;
860 real magnify_x, magnify_y;
861 int width, height;
862 Point middle;
864 ddisp = ddisplay_active();
865 dia = ddisp->diagram;
867 width = dia_renderer_get_width_pixels (ddisp->renderer);
868 height = dia_renderer_get_height_pixels (ddisp->renderer);
870 magnify_x = (real)width /
871 (dia->data->extents.right - dia->data->extents.left) / ddisp->zoom_factor;
872 magnify_y = (real)height /
873 (dia->data->extents.bottom - dia->data->extents.top) / ddisp->zoom_factor;
875 middle.x = dia->data->extents.left +
876 (dia->data->extents.right - dia->data->extents.left) / 2.0;
877 middle.y = dia->data->extents.top +
878 (dia->data->extents.bottom - dia->data->extents.top) / 2.0;
880 ddisplay_zoom (ddisp, &middle, (magnify_x<magnify_y)?magnify_x:magnify_y);
882 ddisplay_update_scrollbars(ddisp);
883 ddisplay_add_update_all(ddisp);
884 ddisplay_flush(ddisp);
887 void
888 view_redraw_callback(gpointer data, guint action, GtkWidget *widget)
890 DDisplay *ddisp;
891 ddisp = ddisplay_active();
892 ddisplay_add_update_all(ddisp);
893 ddisplay_flush(ddisp);
896 void
897 view_diagram_properties_callback(gpointer data, guint action, GtkWidget *widget)
899 DDisplay *ddisp;
901 ddisp = ddisplay_active();
902 diagram_properties_show(ddisp->diagram);
906 void
907 objects_place_over_callback(gpointer data, guint action, GtkWidget *widget)
909 diagram_place_over_selected(ddisplay_active()->diagram);
912 void
913 objects_place_under_callback(gpointer data, guint action, GtkWidget *widget)
915 diagram_place_under_selected(ddisplay_active()->diagram);
918 void
919 objects_place_up_callback(gpointer data, guint action, GtkWidget *widget)
921 diagram_place_up_selected(ddisplay_active()->diagram);
924 void
925 objects_place_down_callback(gpointer data, guint action, GtkWidget *widget)
927 diagram_place_down_selected(ddisplay_active()->diagram);
930 void
931 objects_group_callback(gpointer data, guint action, GtkWidget *widget)
933 diagram_group_selected(ddisplay_active()->diagram);
936 void
937 objects_ungroup_callback(gpointer data, guint action, GtkWidget *widget)
939 diagram_ungroup_selected(ddisplay_active()->diagram);
942 void
943 dialogs_properties_callback(gpointer data, guint action, GtkWidget *widget)
945 Diagram *dia;
946 Object *selected;
948 dia = ddisplay_active()->diagram;
950 if (dia->data->selected != NULL) {
951 selected = dia->data->selected->data;
952 properties_show(dia, selected);
953 } else {
954 diagram_properties_show(dia);
958 void
959 dialogs_layers_callback(gpointer data, guint action, GtkWidget *widget)
961 layer_dialog_set_diagram(ddisplay_active()->diagram);
962 layer_dialog_show();
966 void
967 objects_align_h_callback(gpointer data, guint action, GtkWidget *widget)
969 int align;
970 Diagram *dia;
971 GList *objects;
973 align = action;
975 dia = ddisplay_active()->diagram;
976 objects = dia->data->selected;
978 object_add_updates_list(objects, dia);
979 object_list_align_h(objects, dia, align);
980 diagram_update_connections_selection(dia);
981 object_add_updates_list(objects, dia);
982 diagram_flush(dia);
984 undo_set_transactionpoint(dia->undo);
987 void
988 objects_align_v_callback(gpointer data, guint action, GtkWidget *widget)
990 int align;
991 Diagram *dia;
992 GList *objects;
994 align = action;
996 dia = ddisplay_active()->diagram;
997 objects = dia->data->selected;
999 object_add_updates_list(objects, dia);
1000 object_list_align_v(objects, dia, align);
1001 diagram_update_connections_selection(dia);
1002 object_add_updates_list(objects, dia);
1003 diagram_flush(dia);
1005 undo_set_transactionpoint(dia->undo);