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.
7 *
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.
12 *
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.
16 */
17
18 #include <config.h>
19
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 <math.h>
28 #include <glib.h>
29
30 #ifdef GNOME
31 #undef GTK_DISABLE_DEPRECATED
32 # include <gnome.h>
33 #endif
34
35 #include <gdk-pixbuf/gdk-pixbuf.h>
36 #include <gtk/gtk.h>
37
38 #include <textedit.h>
39 #include <focus.h>
40 #include "confirm.h"
41
42 /** Functions called on menu selects.
43 * Note that GTK (at least up to 2.12) doesn't disable the keyboard shortcuts
44 * when the menu is made insensitive, so we have to check the constrains again
45 * in the functions.
46 */
47 #ifdef G_OS_WIN32
48 /*
49 * Instead of polluting the Dia namespace with windoze headers, declare the
50 * required prototype here. This is bad style, but not as bad as namespace
51 * clashes to be resolved without C++ --hb
52 */
53 long __stdcall
54 ShellExecuteA (long hwnd,
55 const char* lpOperation,
56 const char* lpFile,
57 const char* lpParameters,
58 const char* lpDirectory,
59 int nShowCmd);
60 #endif
61
62 #include "intl.h"
63 #include "commands.h"
64 #include "app_procs.h"
65 #include "diagram.h"
66 #include "display.h"
67 #include "object_ops.h"
68 #include "cut_n_paste.h"
69 #include "interface.h"
70 #include "load_save.h"
71 #include "utils.h"
72 #include "message.h"
73 #include "grid.h"
74 #include "properties-dialog.h"
75 #include "propinternals.h"
76 #include "preferences.h"
77 #include "layer_dialog.h"
78 #include "connectionpoint_ops.h"
79 #include "undo.h"
80 #include "pagesetup.h"
81 #include "text.h"
82 #include "dia_dirs.h"
83 #include "focus.h"
84 #include <gdk/gdk.h>
85 #include <gdk/gdkkeysyms.h>
86 #include "lib/properties.h"
87 #include "lib/parent.h"
88 #include "dia-props.h"
89 #include "diagram_tree_window.h"
90 #include "authors.h" /* master contributors data */
91
92 void
file_quit_callback(GtkAction * action)93 file_quit_callback (GtkAction *action)
94 {
95 app_exit();
96 }
97
98 void
file_pagesetup_callback(GtkAction * action)99 file_pagesetup_callback (GtkAction *action)
100 {
101 Diagram *dia;
102
103 dia = ddisplay_active_diagram();
104 if (!dia) return;
105 create_page_setup_dlg(dia);
106 }
107
108 void
file_print_callback(GtkAction * _action)109 file_print_callback (GtkAction *_action)
110 {
111 Diagram *dia;
112 DDisplay *ddisp;
113 GtkAction *action;
114
115 dia = ddisplay_active_diagram();
116 if (!dia) return;
117 ddisp = ddisplay_active();
118 if (!ddisp) return;
119
120 action = menus_get_action ("FilePrintGTK");
121 if (!action)
122 action = menus_get_action ("FilePrintGDI");
123 if (!action)
124 action = menus_get_action ("FilePrintPS");
125
126 if (action) {
127 if (confirm_export_size (dia, GTK_WINDOW(ddisp->shell), CONFIRM_PRINT|CONFIRM_PAGES))
128 gtk_action_activate (action);
129 } else {
130 message_error (_("No print plug-in found!"));
131 }
132 }
133
134 void
file_close_callback(GtkAction * action)135 file_close_callback (GtkAction *action)
136 {
137 /* some people use tear-off menus and insist to close non existing displays */
138 if (ddisplay_active())
139 ddisplay_close(ddisplay_active());
140 }
141
142 void
file_new_callback(GtkAction * action)143 file_new_callback (GtkAction *action)
144 {
145 Diagram *dia;
146 DDisplay *ddisp;
147 static int untitled_nr = 1;
148 gchar *name, *filename;
149
150 name = g_strdup_printf(_("Diagram%d.dia"), untitled_nr++);
151 filename = g_filename_from_utf8(name, -1, NULL, NULL, NULL);
152 dia = new_diagram(filename);
153 ddisp = new_display(dia);
154 diagram_tree_add(diagram_tree(), dia);
155 g_free (name);
156 g_free (filename);
157 }
158
159 void
file_preferences_callback(GtkAction * action)160 file_preferences_callback (GtkAction *action)
161 {
162 prefs_show();
163 }
164
165
166
167 /* Signal handler for getting the clipboard contents */
168 /* Note that the clipboard is for M$-style cut/copy/paste copying, while
169 the selection is for Unix-style mark-and-copy. We can't really do
170 mark-and-copy.
171 */
172
173 static void
insert_text(DDisplay * ddisp,Focus * focus,const gchar * text)174 insert_text(DDisplay *ddisp, Focus *focus, const gchar *text)
175 {
176 ObjectChange *change = NULL;
177 int modified = FALSE, any_modified = FALSE;
178 DiaObject *obj = focus_get_object(focus);
179
180 while (text != NULL) {
181 gchar *next_line = g_utf8_strchr(text, -1, '\n');
182 if (next_line != text) {
183 gint len = g_utf8_strlen(text, (next_line-text));
184 modified = (*focus->key_event)(focus, GDK_A, text, len, &change);
185 }
186 if (next_line != NULL) {
187 modified = (*focus->key_event)(focus, GDK_Return, "\n", 1, &change);
188 text = g_utf8_next_char(next_line);
189 } else {
190 text = NULL;
191 }
192 { /* Make sure object updates its data: */
193 Point p = obj->position;
194 (obj->ops->move)(obj,&p); }
195
196 /* Perhaps this can be improved */
197 object_add_updates(obj, ddisp->diagram);
198
199 if (modified && (change != NULL)) {
200 undo_object_change(ddisp->diagram, obj, change);
201 any_modified = TRUE;
202 }
203
204 diagram_flush(ddisp->diagram);
205 }
206
207 if (any_modified) {
208 diagram_modified(ddisp->diagram);
209 diagram_update_extents(ddisp->diagram);
210 undo_set_transactionpoint(ddisp->diagram->undo);
211 }
212 }
213
214
215 static void
received_clipboard_handler(GtkClipboard * clipboard,const gchar * text,gpointer data)216 received_clipboard_handler(GtkClipboard *clipboard,
217 const gchar *text,
218 gpointer data) {
219 DDisplay *ddisp = (DDisplay *)data;
220 Focus *focus = get_active_focus((DiagramData *) ddisp->diagram);
221
222 if (text == NULL) return;
223
224 if ((focus == NULL) || (!focus->has_focus)) return;
225
226 if (!g_utf8_validate(text, -1, NULL)) {
227 message_error("Not valid UTF8");
228 return;
229 }
230
231 insert_text(ddisp, focus, text);
232 }
233
234 static PropDescription text_prop_singleton_desc[] = {
235 { "text", PROP_TYPE_TEXT },
236 PROP_DESC_END};
237
238 static void
make_text_prop_singleton(GPtrArray ** props,TextProperty ** prop)239 make_text_prop_singleton(GPtrArray **props, TextProperty **prop)
240 {
241 *props = prop_list_from_descs(text_prop_singleton_desc,pdtpp_true);
242 g_assert((*props)->len == 1);
243
244 *prop = g_ptr_array_index((*props),0);
245 g_free((*prop)->text_data);
246 (*prop)->text_data = NULL;
247 }
248
249
250 void
edit_copy_callback(GtkAction * action)251 edit_copy_callback (GtkAction *action)
252 {
253 GList *copy_list;
254 DDisplay *ddisp;
255
256 ddisp = ddisplay_active();
257 if (!ddisp) return;
258 if (textedit_mode(ddisp)) {
259 Focus *focus = get_active_focus((DiagramData *) ddisp->diagram);
260 DiaObject *obj = focus_get_object(focus);
261 GPtrArray *textprops;
262 TextProperty *prop;
263
264 if (obj->ops->get_props == NULL)
265 return;
266
267 make_text_prop_singleton(&textprops,&prop);
268 /* Get the first text property */
269 obj->ops->get_props(obj, textprops);
270
271 /* GTK docs claim the selection clipboard is ignored on Win32.
272 * The "clipboard" clipboard is mostly ignored in Unix
273 */
274 #ifdef G_OS_WIN32
275 gtk_clipboard_set_text(gtk_clipboard_get(GDK_NONE),
276 prop->text_data, -1);
277 #else
278 gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY),
279 prop->text_data, -1);
280 #endif
281 prop_list_free(textprops);
282 } else {
283 copy_list = parent_list_affected(diagram_get_sorted_selected(ddisp->diagram));
284
285 cnp_store_objects(object_copy_list(copy_list), 1);
286 g_list_free(copy_list);
287
288 ddisplay_do_update_menu_sensitivity(ddisp);
289 }
290 }
291
292 void
edit_cut_callback(GtkAction * action)293 edit_cut_callback (GtkAction *action)
294 {
295 GList *cut_list;
296 DDisplay *ddisp;
297 Change *change;
298
299 ddisp = ddisplay_active();
300 if (!ddisp) return;
301
302 if (textedit_mode(ddisp)) {
303 } else {
304 diagram_selected_break_external(ddisp->diagram);
305
306 cut_list = parent_list_affected(diagram_get_sorted_selected(ddisp->diagram));
307
308 cnp_store_objects(object_copy_list(cut_list), 0);
309
310 change = undo_delete_objects_children(ddisp->diagram, cut_list);
311 (change->apply)(change, ddisp->diagram);
312
313 ddisplay_do_update_menu_sensitivity(ddisp);
314 diagram_flush(ddisp->diagram);
315
316 diagram_modified(ddisp->diagram);
317 diagram_update_extents(ddisp->diagram);
318 undo_set_transactionpoint(ddisp->diagram->undo);
319 }
320 }
321
322 void
edit_paste_callback(GtkAction * action)323 edit_paste_callback (GtkAction *action)
324 {
325 GList *paste_list;
326 DDisplay *ddisp;
327 Point paste_corner;
328 Point delta;
329 Change *change;
330 int generation = 0;
331
332 ddisp = ddisplay_active();
333 if (!ddisp) return;
334 if (textedit_mode(ddisp)) {
335 #ifdef G_OS_WIN32
336 gtk_clipboard_request_text(gtk_clipboard_get(GDK_NONE),
337 received_clipboard_handler, ddisp);
338 #else
339 gtk_clipboard_request_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY),
340 received_clipboard_handler, ddisp);
341 #endif
342 } else {
343 if (!cnp_exist_stored_objects()) {
344 message_warning(_("No existing object to paste.\n"));
345 return;
346 }
347
348 paste_list = cnp_get_stored_objects(&generation); /* Gets a copy */
349
350 paste_corner = object_list_corner(paste_list);
351
352 delta.x = ddisp->visible.left - paste_corner.x;
353 delta.y = ddisp->visible.top - paste_corner.y;
354
355 /* Move down some 10% of the visible area. */
356 delta.x += (ddisp->visible.right - ddisp->visible.left) * 0.1 * generation;
357 delta.y += (ddisp->visible.bottom - ddisp->visible.top) * 0.1 * generation;
358
359 if (generation)
360 object_list_move_delta(paste_list, &delta);
361
362 change = undo_insert_objects(ddisp->diagram, paste_list, 0);
363 (change->apply)(change, ddisp->diagram);
364
365 diagram_modified(ddisp->diagram);
366 undo_set_transactionpoint(ddisp->diagram->undo);
367
368 diagram_remove_all_selected(ddisp->diagram, TRUE);
369 diagram_select_list(ddisp->diagram, paste_list);
370
371 diagram_update_extents(ddisp->diagram);
372 diagram_flush(ddisp->diagram);
373 }
374 }
375
376 /*
377 * ALAN: Paste should probably paste to different position, feels
378 * wrong somehow. ALAN: The offset should increase a little each time
379 * if you paste/duplicate several times in a row, because it is
380 * clearer what is happening than if you were to piling them all in
381 * one place.
382 *
383 * completely untested, basically it is copy+paste munged together
384 */
385 void
edit_duplicate_callback(GtkAction * action)386 edit_duplicate_callback (GtkAction *action)
387 {
388 GList *duplicate_list;
389 DDisplay *ddisp;
390 Point duplicate_corner;
391 Point delta;
392 Change *change;
393
394 ddisp = ddisplay_active();
395 if (!ddisp || textedit_mode(ddisp)) return;
396 duplicate_list = object_copy_list(diagram_get_sorted_selected(ddisp->diagram));
397 duplicate_corner = object_list_corner(duplicate_list);
398
399 /* Move down some 10% of the visible area. */
400 delta.x = (ddisp->visible.right - ddisp->visible.left)*0.05;
401 delta.y = (ddisp->visible.bottom - ddisp->visible.top)*0.05;
402
403 object_list_move_delta(duplicate_list, &delta);
404
405 change = undo_insert_objects(ddisp->diagram, duplicate_list, 0);
406 (change->apply)(change, ddisp->diagram);
407
408 diagram_modified(ddisp->diagram);
409 undo_set_transactionpoint(ddisp->diagram->undo);
410
411 diagram_remove_all_selected(ddisp->diagram, TRUE);
412 diagram_select_list(ddisp->diagram, duplicate_list);
413
414 diagram_flush(ddisp->diagram);
415
416 ddisplay_do_update_menu_sensitivity(ddisp);
417 }
418
419 void
objects_move_up_layer(GtkAction * action)420 objects_move_up_layer(GtkAction *action)
421 {
422 DDisplay *ddisp = ddisplay_active();
423 GList *selected_list;
424 Change *change;
425
426 if (!ddisp || textedit_mode(ddisp)) return;
427 selected_list = diagram_get_sorted_selected(ddisp->diagram);
428
429 change = undo_move_object_other_layer(ddisp->diagram, selected_list, TRUE);
430
431 (change->apply)(change, ddisp->diagram);
432
433 diagram_modified(ddisp->diagram);
434 undo_set_transactionpoint(ddisp->diagram->undo);
435
436 diagram_flush(ddisp->diagram);
437
438 ddisplay_do_update_menu_sensitivity(ddisp);
439 }
440
441 void
objects_move_down_layer(GtkAction * action)442 objects_move_down_layer(GtkAction *action)
443 {
444 DDisplay *ddisp = ddisplay_active();
445 GList *selected_list;
446 Change *change;
447
448 if (!ddisp || textedit_mode(ddisp)) return;
449 selected_list = diagram_get_sorted_selected(ddisp->diagram);
450
451 /* Must check if move is legal here */
452
453 change = undo_move_object_other_layer(ddisp->diagram, selected_list, FALSE);
454
455 (change->apply)(change, ddisp->diagram);
456
457 diagram_modified(ddisp->diagram);
458 undo_set_transactionpoint(ddisp->diagram->undo);
459
460 diagram_flush(ddisp->diagram);
461
462 ddisplay_do_update_menu_sensitivity(ddisp);
463 }
464
465 void
edit_copy_text_callback(GtkAction * action)466 edit_copy_text_callback (GtkAction *action)
467 {
468 Focus *focus;
469 DDisplay *ddisp = ddisplay_active();
470 DiaObject *obj;
471 GPtrArray *textprops;
472 TextProperty *prop;
473
474 if (ddisp == NULL) return;
475
476 focus = get_active_focus((DiagramData *) ddisp->diagram);
477
478 if ((focus == NULL) || (!focus->has_focus)) return;
479
480 obj = focus_get_object(focus);
481
482 if (obj->ops->get_props == NULL)
483 return;
484
485 make_text_prop_singleton(&textprops,&prop);
486 /* Get the first text property */
487 obj->ops->get_props(obj, textprops);
488
489 /* GTK docs claim the selection clipboard is ignored on Win32.
490 * The "clipboard" clipboard is mostly ignored in Unix
491 */
492 #ifdef G_OS_WIN32
493 gtk_clipboard_set_text(gtk_clipboard_get(GDK_NONE),
494 prop->text_data, -1);
495 #else
496 gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY),
497 prop->text_data, -1);
498 #endif
499 prop_list_free(textprops);
500 }
501
502 void
edit_cut_text_callback(GtkAction * action)503 edit_cut_text_callback (GtkAction *action)
504 {
505 Focus *focus;
506 DDisplay *ddisp;
507 DiaObject *obj;
508 Text *text;
509 GPtrArray *textprops;
510 TextProperty *prop;
511 ObjectChange *change;
512
513 ddisp = ddisplay_active();
514 if (!ddisp) return;
515
516 focus = get_active_focus((DiagramData *) ddisp->diagram);
517 if ((focus == NULL) || (!focus->has_focus)) return;
518
519 obj = focus_get_object(focus);
520 text = (Text*)focus->user_data;
521
522 if (obj->ops->get_props == NULL)
523 return;
524
525 make_text_prop_singleton(&textprops,&prop);
526 /* Get the first text property */
527 obj->ops->get_props(obj, textprops);
528
529 /* GTK docs claim the selection clipboard is ignored on Win32.
530 * The "clipboard" clipboard is mostly ignored in Unix
531 */
532 #ifdef G_OS_WIN32
533 gtk_clipboard_set_text(gtk_clipboard_get(GDK_NONE),
534 prop->text_data, -1);
535 #else
536 gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY),
537 prop->text_data, -1);
538 #endif
539
540 prop_list_free(textprops);
541
542 if (text_delete_all(text, &change)) {
543 object_add_updates(obj, ddisp->diagram);
544 undo_object_change(ddisp->diagram, obj, change);
545 undo_set_transactionpoint(ddisp->diagram->undo);
546 diagram_modified(ddisp->diagram);
547 diagram_flush(ddisp->diagram);
548 }
549 }
550
551 void
edit_paste_text_callback(GtkAction * action)552 edit_paste_text_callback (GtkAction *action)
553 {
554 DDisplay *ddisp;
555
556 ddisp = ddisplay_active();
557 if (!ddisp) return;
558
559 #ifdef G_OS_WIN32
560 gtk_clipboard_request_text(gtk_clipboard_get(GDK_NONE),
561 received_clipboard_handler, ddisp);
562 #else
563 gtk_clipboard_request_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY),
564 received_clipboard_handler, ddisp);
565 #endif
566 }
567
568 void
edit_delete_callback(GtkAction * action)569 edit_delete_callback (GtkAction *action)
570 {
571 GList *delete_list;
572 DDisplay *ddisp;
573
574 /* Avoid crashing while moving or resizing and deleting ... */
575 if (gdk_pointer_is_grabbed ()) {
576 gdk_beep (); /* ... no matter how much sense it makes. */
577 return;
578 }
579
580 ddisp = ddisplay_active();
581 if (!ddisp) return;
582 if (textedit_mode(ddisp)) {
583 ObjectChange *change = NULL;
584 Focus *focus = get_active_focus((DiagramData *) ddisp->diagram);
585 if (!text_delete_key_handler(focus, &change)) {
586 return;
587 }
588 object_add_updates(focus->obj, ddisp->diagram);
589 } else {
590 Change *change = NULL;
591 diagram_selected_break_external(ddisp->diagram);
592
593 delete_list = diagram_get_sorted_selected(ddisp->diagram);
594 change = undo_delete_objects_children(ddisp->diagram, delete_list);
595 g_list_free(delete_list);
596 (change->apply)(change, ddisp->diagram);
597 }
598 diagram_modified(ddisp->diagram);
599 diagram_update_extents(ddisp->diagram);
600
601 ddisplay_do_update_menu_sensitivity(ddisp);
602 diagram_flush(ddisp->diagram);
603
604 undo_set_transactionpoint(ddisp->diagram->undo);
605 }
606
607 void
edit_undo_callback(GtkAction * action)608 edit_undo_callback (GtkAction *action)
609 {
610 Diagram *dia;
611
612 dia = ddisplay_active_diagram();
613 if (!dia) return;
614
615 /* Handle text undo edit here! */
616 undo_revert_to_last_tp(dia->undo);
617 diagram_modified(dia);
618 diagram_update_extents(dia);
619
620 diagram_flush(dia);
621 }
622
623 void
edit_redo_callback(GtkAction * action)624 edit_redo_callback (GtkAction *action)
625 {
626 Diagram *dia;
627
628 /* Handle text undo edit here! */
629 dia = ddisplay_active_diagram();
630 if (!dia) return;
631
632 undo_apply_to_next_tp(dia->undo);
633 diagram_modified(dia);
634 diagram_update_extents(dia);
635
636 diagram_flush(dia);
637 }
638
639 void
help_manual_callback(GtkAction * action)640 help_manual_callback (GtkAction *action)
641 {
642 #ifdef GNOME
643 gnome_help_display("dia", NULL, NULL);
644 #else
645 char *helpdir, *helpindex = NULL, *command;
646 guint bestscore = G_MAXINT;
647 GDir *dp;
648 const char *dentry;
649 GError *error = NULL;
650
651 helpdir = dia_get_data_directory("help");
652 if (!helpdir) {
653 message_warning(_("Could not find help directory"));
654 return;
655 }
656
657 /* search through helpdir for the helpfile that matches the user's locale */
658 dp = g_dir_open (helpdir, 0, &error);
659 if (!dp) {
660 message_warning(_("Could not open help directory:\n%s"),
661 error->message);
662 g_error_free (error);
663 return;
664 }
665
666 while ((dentry = g_dir_read_name(dp)) != NULL) {
667 guint score;
668
669 score = intl_score_locale(dentry);
670 if (score < bestscore) {
671 if (helpindex)
672 g_free(helpindex);
673 #ifdef G_OS_WIN32
674 /* use HTML Help on win32 if available */
675 helpindex = g_strconcat(helpdir, G_DIR_SEPARATOR_S, dentry,
676 G_DIR_SEPARATOR_S "dia-manual.chm", NULL);
677 if (!g_file_test(helpindex, G_FILE_TEST_EXISTS)) {
678 helpindex = g_strconcat(helpdir, G_DIR_SEPARATOR_S, dentry,
679 G_DIR_SEPARATOR_S "index.html", NULL);
680 }
681 #else
682 helpindex = g_strconcat(helpdir, G_DIR_SEPARATOR_S, dentry,
683 G_DIR_SEPARATOR_S "index.html", NULL);
684 #endif
685 bestscore = score;
686 }
687 }
688 g_dir_close (dp);
689 g_free(helpdir);
690 if (!helpindex) {
691 message_warning(_("Could not find help directory"));
692 return;
693 }
694
695 #ifdef G_OS_WIN32
696 # define SW_SHOWNORMAL 1
697 ShellExecuteA (0, "open", helpindex, NULL, helpdir, SW_SHOWNORMAL);
698 #else
699 command = getenv("BROWSER");
700 command = g_strdup_printf("%s 'file://%s' &", command ? command : "xdg-open", helpindex);
701 system(command);
702 g_free(command);
703 #endif
704
705 g_free(helpindex);
706 #endif
707 }
708
709 static void
activate_url(GtkAboutDialog * about,const gchar * link,gpointer data)710 activate_url (GtkAboutDialog *about,
711 const gchar *link,
712 gpointer data)
713 {
714 #ifdef G_OS_WIN32
715 ShellExecuteA (0, "open", link, NULL, NULL, SW_SHOWNORMAL);
716 #else
717 gchar *command = getenv("BROWSER");
718 command = g_strdup_printf("%s '%s' &", command ? command : "xdg-open", link);
719 system(command);
720 g_free(command);
721 #endif
722 }
723
724 void
help_about_callback(GtkAction * action)725 help_about_callback (GtkAction *action)
726 {
727 const gchar *translators = _("translator_credits-PLEASE_ADD_YOURSELF_HERE");
728 const gchar *license = _(
729 "This program is free software; you can redistribute it and/or modify\n"
730 "it under the terms of the GNU General Public License as published by\n"
731 "the Free Software Foundation; either version 2 of the License, or\n"
732 "(at your option) any later version.\n"
733 "\n"
734 "This program is distributed in the hope that it will be useful,\n"
735 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
736 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
737 "GNU General Public License for more details.\n"
738 "\n"
739 "You should have received a copy of the GNU General Public License\n"
740 "along with this program; if not, write to the Free Software\n"
741 "Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n");
742
743 gchar *dirname = dia_get_data_directory("");
744 gchar *filename = g_build_filename (dirname, "dia-splash.png", NULL);
745 GdkPixbuf *logo = gdk_pixbuf_new_from_file(filename, NULL);
746
747 gtk_about_dialog_set_url_hook (activate_url, NULL, NULL);
748 gtk_show_about_dialog (NULL,
749 "logo", logo,
750 "name", "Dia",
751 "version", VERSION,
752 "comments", _("A program for drawing structured diagrams."),
753 "copyright", "(C) 1998-2009 The Free Software Foundation and the authors",
754 "website", "http://live.gnome.org/Dia",
755 "authors", authors,
756 "documenters", documentors,
757 "translator-credits", strcmp (translators, "translator_credits-PLEASE_ADD_YOURSELF_HERE")
758 ? translators : NULL,
759 "license", license,
760 NULL);
761 g_free (dirname);
762 g_free (filename);
763 if (logo)
764 g_object_unref (logo);
765 }
766
767 void
view_zoom_in_callback(GtkAction * action)768 view_zoom_in_callback (GtkAction *action)
769 {
770 DDisplay *ddisp;
771 Point middle;
772 Rectangle *visible;
773
774 ddisp = ddisplay_active();
775 if (!ddisp) return;
776 visible = &ddisp->visible;
777 middle.x = visible->left*0.5 + visible->right*0.5;
778 middle.y = visible->top*0.5 + visible->bottom*0.5;
779
780 ddisplay_zoom(ddisp, &middle, M_SQRT2);
781 }
782
783 void
view_zoom_out_callback(GtkAction * action)784 view_zoom_out_callback (GtkAction *action)
785 {
786 DDisplay *ddisp;
787 Point middle;
788 Rectangle *visible;
789
790 ddisp = ddisplay_active();
791 if (!ddisp) return;
792 visible = &ddisp->visible;
793 middle.x = visible->left*0.5 + visible->right*0.5;
794 middle.y = visible->top*0.5 + visible->bottom*0.5;
795
796 ddisplay_zoom(ddisp, &middle, M_SQRT1_2);
797 }
798
799 void
view_zoom_set_callback(GtkAction * action)800 view_zoom_set_callback (GtkAction *action)
801 {
802 int factor;
803 /* HACK the actual factor is a suffix to the action name */
804 factor = atoi (gtk_action_get_name (action) + strlen ("ViewZoom"));
805 view_zoom_set (factor);
806 }
807
808 void
view_show_cx_pts_callback(GtkToggleAction * action)809 view_show_cx_pts_callback (GtkToggleAction *action)
810 {
811 DDisplay *ddisp;
812 int old_val;
813
814 ddisp = ddisplay_active();
815 if (!ddisp) return;
816
817 old_val = ddisp->show_cx_pts;
818 ddisp->show_cx_pts = gtk_toggle_action_get_active (action);
819
820 if (old_val != ddisp->show_cx_pts) {
821 ddisplay_add_update_all(ddisp);
822 ddisplay_flush(ddisp);
823 }
824 }
825
826 void
view_unfullscreen(void)827 view_unfullscreen (void)
828 {
829 DDisplay *ddisp;
830 GtkToggleAction *item;
831
832 ddisp = ddisplay_active();
833 if (!ddisp) return;
834
835 /* find the menuitem */
836 item = GTK_TOGGLE_ACTION (menus_get_action ("ViewFullscreen"));
837 if (item && gtk_toggle_action_get_active (item)) {
838 gtk_toggle_action_set_active (item, FALSE);
839 }
840 }
841
842 void
view_fullscreen_callback(GtkToggleAction * action)843 view_fullscreen_callback (GtkToggleAction *action)
844 {
845 DDisplay *ddisp;
846 int fs;
847
848 ddisp = ddisplay_active();
849 if (!ddisp) return;
850
851 fs = gtk_toggle_action_get_active (action);
852
853 if (fs) /* it is already toggled */
854 gtk_window_fullscreen(GTK_WINDOW(ddisp->shell));
855 else
856 gtk_window_unfullscreen(GTK_WINDOW(ddisp->shell));
857 }
858
859 void
view_aa_callback(GtkToggleAction * action)860 view_aa_callback (GtkToggleAction *action)
861 {
862 DDisplay *ddisp;
863 int aa;
864
865 ddisp = ddisplay_active();
866 if (!ddisp) return;
867
868 aa = gtk_toggle_action_get_active (action);
869
870 if (aa != ddisp->aa_renderer) {
871 ddisplay_set_renderer(ddisp, aa);
872 ddisplay_add_update_all(ddisp);
873 ddisplay_flush(ddisp);
874 }
875 }
876
877 void
view_visible_grid_callback(GtkToggleAction * action)878 view_visible_grid_callback (GtkToggleAction *action)
879 {
880 DDisplay *ddisp;
881 guint old_val;
882
883 ddisp = ddisplay_active();
884 if (!ddisp) return;
885
886 old_val = ddisp->grid.visible;
887 ddisp->grid.visible = gtk_toggle_action_get_active (action);
888
889 if (old_val != ddisp->grid.visible) {
890 ddisplay_add_update_all(ddisp);
891 ddisplay_flush(ddisp);
892 }
893 }
894
895 void
view_snap_to_grid_callback(GtkToggleAction * action)896 view_snap_to_grid_callback (GtkToggleAction *action)
897 {
898 DDisplay *ddisp;
899
900 ddisp = ddisplay_active();
901 if (!ddisp) return;
902
903 ddisplay_set_snap_to_grid(ddisp, gtk_toggle_action_get_active (action));
904 }
905
906 void
view_snap_to_objects_callback(GtkToggleAction * action)907 view_snap_to_objects_callback (GtkToggleAction *action)
908 {
909 DDisplay *ddisp;
910
911 ddisp = ddisplay_active();
912 if (!ddisp) return;
913
914 ddisplay_set_snap_to_objects(ddisp, gtk_toggle_action_get_active (action));
915 }
916
917 void
view_toggle_rulers_callback(GtkToggleAction * action)918 view_toggle_rulers_callback (GtkToggleAction *action)
919 {
920 DDisplay *ddisp;
921
922 ddisp = ddisplay_active();
923 if (!ddisp) return;
924
925 if (!gtk_toggle_action_get_active (action)) {
926 if (display_get_rulers_showing(ddisp)) {
927 display_rulers_hide (ddisp);
928 }
929 } else {
930 if (!display_get_rulers_showing(ddisp)) {
931 display_rulers_show (ddisp);
932 }
933 }
934 }
935
936 extern void
view_new_view_callback(GtkAction * action)937 view_new_view_callback (GtkAction *action)
938 {
939 Diagram *dia;
940
941 dia = ddisplay_active_diagram();
942 if (!dia) return;
943
944 new_display(dia);
945 }
946
947 extern void
view_clone_view_callback(GtkAction * action)948 view_clone_view_callback (GtkAction *action)
949 {
950 DDisplay *ddisp;
951
952 ddisp = ddisplay_active();
953 if (!ddisp) return;
954
955 copy_display(ddisp);
956 }
957
958 void
view_show_all_callback(GtkAction * action)959 view_show_all_callback (GtkAction *action)
960 {
961 DDisplay *ddisp;
962
963 ddisp = ddisplay_active();
964 if (!ddisp) return;
965
966 ddisplay_show_all (ddisp);
967 }
968
969 void
view_redraw_callback(GtkAction * action)970 view_redraw_callback (GtkAction *action)
971 {
972 DDisplay *ddisp;
973 ddisp = ddisplay_active();
974 if (!ddisp) return;
975 ddisplay_add_update_all(ddisp);
976 ddisplay_flush(ddisp);
977 }
978
979 void
view_diagram_properties_callback(GtkAction * action)980 view_diagram_properties_callback (GtkAction *action)
981 {
982 DDisplay *ddisp;
983
984 ddisp = ddisplay_active();
985 if (!ddisp) return;
986 diagram_properties_show(ddisp->diagram);
987 }
988
989 void
view_main_toolbar_callback(GtkAction * action)990 view_main_toolbar_callback (GtkAction *action)
991 {
992 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action)) == TRUE)
993 {
994 integrated_ui_main_toolbar_show ();
995 }
996 else
997 {
998 integrated_ui_main_toolbar_hide ();
999 }
1000 }
1001
1002 void
view_main_statusbar_callback(GtkAction * action)1003 view_main_statusbar_callback (GtkAction *action)
1004 {
1005 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action)) == TRUE)
1006 {
1007 integrated_ui_main_statusbar_show ();
1008 }
1009 else
1010 {
1011 integrated_ui_main_statusbar_hide ();
1012 }
1013 }
1014
1015 void
view_layers_callback(GtkAction * action)1016 view_layers_callback (GtkAction *action)
1017 {
1018 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action)) == TRUE)
1019 {
1020 integrated_ui_layer_view_show ();
1021 }
1022 else
1023 {
1024 integrated_ui_layer_view_hide ();
1025 }
1026 }
1027
1028 void
layers_add_layer_callback(GtkAction * action)1029 layers_add_layer_callback (GtkAction *action)
1030 {
1031 Diagram *dia;
1032
1033 dia = ddisplay_active_diagram();
1034 if (!dia) return;
1035
1036 diagram_edit_layer (dia, NULL);
1037 }
1038
1039 void
layers_rename_layer_callback(GtkAction * action)1040 layers_rename_layer_callback (GtkAction *action)
1041 {
1042 Diagram *dia;
1043
1044 dia = ddisplay_active_diagram();
1045 if (!dia) return;
1046
1047 diagram_edit_layer (dia, dia->data->active_layer);
1048 }
1049
1050 void
objects_place_over_callback(GtkAction * action)1051 objects_place_over_callback (GtkAction *action)
1052 {
1053 diagram_place_over_selected(ddisplay_active_diagram());
1054 }
1055
1056 void
objects_place_under_callback(GtkAction * action)1057 objects_place_under_callback (GtkAction *action)
1058 {
1059 diagram_place_under_selected(ddisplay_active_diagram());
1060 }
1061
1062 void
objects_place_up_callback(GtkAction * action)1063 objects_place_up_callback (GtkAction *action)
1064 {
1065 diagram_place_up_selected(ddisplay_active_diagram());
1066 }
1067
1068 void
objects_place_down_callback(GtkAction * action)1069 objects_place_down_callback (GtkAction *action)
1070 {
1071 DDisplay *ddisp = ddisplay_active();
1072 if (!ddisp || textedit_mode(ddisp)) return;
1073
1074 diagram_place_down_selected(ddisplay_active_diagram());
1075 }
1076
1077 void
objects_parent_callback(GtkAction * action)1078 objects_parent_callback (GtkAction *action)
1079 {
1080 DDisplay *ddisp = ddisplay_active();
1081 if (!ddisp || textedit_mode(ddisp)) return;
1082
1083 diagram_parent_selected(ddisplay_active_diagram());
1084 }
1085
1086 void
objects_unparent_callback(GtkAction * action)1087 objects_unparent_callback (GtkAction *action)
1088 {
1089 DDisplay *ddisp = ddisplay_active();
1090 if (!ddisp || textedit_mode(ddisp)) return;
1091
1092 diagram_unparent_selected(ddisplay_active_diagram());
1093 }
1094
1095 void
objects_unparent_children_callback(GtkAction * action)1096 objects_unparent_children_callback (GtkAction *action)
1097 {
1098 DDisplay *ddisp = ddisplay_active();
1099 if (!ddisp || textedit_mode(ddisp)) return;
1100
1101 diagram_unparent_children_selected(ddisplay_active_diagram());
1102 }
1103
1104 void
objects_group_callback(GtkAction * action)1105 objects_group_callback (GtkAction *action)
1106 {
1107 DDisplay *ddisp = ddisplay_active();
1108 if (!ddisp || textedit_mode(ddisp)) return;
1109
1110 diagram_group_selected(ddisplay_active_diagram());
1111 ddisplay_do_update_menu_sensitivity(ddisp);
1112 }
1113
1114 void
objects_ungroup_callback(GtkAction * action)1115 objects_ungroup_callback (GtkAction *action)
1116 {
1117 DDisplay *ddisp = ddisplay_active();
1118 if (!ddisp || textedit_mode(ddisp)) return;
1119
1120 diagram_ungroup_selected(ddisplay_active_diagram());
1121 ddisplay_do_update_menu_sensitivity(ddisp);
1122 }
1123
1124 void
dialogs_properties_callback(GtkAction * action)1125 dialogs_properties_callback (GtkAction *action)
1126 {
1127 Diagram *dia;
1128 DiaObject *selected;
1129
1130 dia = ddisplay_active_diagram();
1131 if (!dia || textedit_mode(ddisplay_active())) return;
1132
1133 if (dia->data->selected != NULL) {
1134 object_list_properties_show(dia, dia->data->selected);
1135 } else {
1136 diagram_properties_show(dia);
1137 }
1138 }
1139
1140 void
dialogs_layers_callback(GtkAction * action)1141 dialogs_layers_callback (GtkAction *action)
1142 {
1143 layer_dialog_set_diagram(ddisplay_active_diagram());
1144 layer_dialog_show();
1145 }
1146
1147
1148 void
objects_align_h_callback(GtkAction * action)1149 objects_align_h_callback (GtkAction *action)
1150 {
1151 const gchar *a;
1152 int align = DIA_ALIGN_LEFT;
1153 Diagram *dia;
1154 GList *objects;
1155
1156 DDisplay *ddisp = ddisplay_active();
1157 if (!ddisp || textedit_mode(ddisp)) return;
1158
1159 /* HACK align is suffix to action name */
1160 a = gtk_action_get_name (action) + strlen ("ObjectsAlign");
1161 if (0 == strcmp ("Left", a)) {
1162 align = DIA_ALIGN_LEFT;
1163 }
1164 else if (0 == strcmp ("Center", a)) {
1165 align = DIA_ALIGN_CENTER;
1166 }
1167 else if (0 == strcmp ("Right", a)) {
1168 align = DIA_ALIGN_RIGHT;
1169 }
1170 else if (0 == strcmp ("Spreadouthorizontally", a)) {
1171 align = DIA_ALIGN_EQUAL;
1172 }
1173 else if (0 == strcmp ("Adjacent", a)) {
1174 align = DIA_ALIGN_ADJACENT;
1175 }
1176 else {
1177 g_warning ("objects_align_v_callback() called without appropriate align");
1178 return;
1179 }
1180
1181 dia = ddisplay_active_diagram();
1182 if (!dia) return;
1183 objects = dia->data->selected;
1184
1185 object_add_updates_list(objects, dia);
1186 object_list_align_h(objects, dia, align);
1187 diagram_update_connections_selection(dia);
1188 object_add_updates_list(objects, dia);
1189 diagram_modified(dia);
1190 diagram_flush(dia);
1191
1192 undo_set_transactionpoint(dia->undo);
1193 }
1194
1195 void
objects_align_v_callback(GtkAction * action)1196 objects_align_v_callback (GtkAction *action)
1197 {
1198 const gchar *a;
1199 int align;
1200 Diagram *dia;
1201 GList *objects;
1202
1203 DDisplay *ddisp = ddisplay_active();
1204 if (!ddisp || textedit_mode(ddisp)) return;
1205
1206 /* HACK align is suffix to action name */
1207 a = gtk_action_get_name (action) + strlen ("ObjectsAlign");
1208 if (0 == strcmp ("Top", a)) {
1209 align = DIA_ALIGN_TOP;
1210 }
1211 else if (0 == strcmp ("Middle", a)) {
1212 align = DIA_ALIGN_CENTER;
1213 }
1214 else if (0 == strcmp ("Bottom", a)) {
1215 align = DIA_ALIGN_BOTTOM;
1216 }
1217 else if (0 == strcmp ("Spreadoutvertically", a)) {
1218 align = DIA_ALIGN_EQUAL;
1219 }
1220 else if (0 == strcmp ("Stacked", a)) {
1221 align = DIA_ALIGN_ADJACENT;
1222 }
1223 else {
1224 g_warning ("objects_align_v_callback() called without appropriate align");
1225 return;
1226 }
1227
1228 dia = ddisplay_active_diagram();
1229 if (!dia) return;
1230 objects = dia->data->selected;
1231
1232 object_add_updates_list(objects, dia);
1233 object_list_align_v(objects, dia, align);
1234 diagram_update_connections_selection(dia);
1235 object_add_updates_list(objects, dia);
1236 diagram_modified(dia);
1237 diagram_flush(dia);
1238
1239 undo_set_transactionpoint(dia->undo);
1240 }
1241
1242
1243