3 * Copyright (C) 2002-2009 Jim Evins <evins@snaught.com>.
5 * This file is part of gLabels.
7 * gLabels is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * gLabels is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with gLabels. If not, see <http://www.gnu.org/licenses/>.
25 #include <glib/gi18n.h>
29 #include "ui-commands.h"
30 #include "file-util.h"
31 #include "xml-label.h"
34 #include "units-util.h"
39 /*===========================================================================*/
40 /* Private macros and constants. */
41 /*===========================================================================*/
43 #define DEFAULT_WINDOW_WIDTH 788
44 #define DEFAULT_WINDOW_HEIGHT 600
46 #define CURSOR_INFO_WIDTH 150
47 #define ZOOM_INFO_WIDTH 75
50 /*===========================================================================*/
52 /*===========================================================================*/
54 static GList *window_list = NULL;
57 /*===========================================================================*/
58 /* Local function prototypes */
59 /*===========================================================================*/
61 static void gl_window_finalize (GObject *object);
62 static void gl_window_dispose (GObject *object);
64 static void set_window_title (glWindow *window,
67 static gboolean window_delete_event_cb (glWindow *window,
71 static void selection_changed_cb (glLabel *label,
74 static void context_menu_activate_cb (glView *view,
76 guint32 activate_time,
79 static void zoom_changed_cb (glView *view,
83 static void pointer_moved_cb (glView *view,
88 static void pointer_exit_cb (glView *view,
91 static void name_changed_cb (glLabel *label,
94 static void modified_changed_cb (glLabel *label,
97 static void clipboard_changed_cb (GtkClipboard *clipboard,
101 static void focus_widget_changed_cb(GtkWindow *gtk_window,
105 static void set_copy_paste_sensitivity (glWindow *window,
106 GtkWidget *focus_widget);
108 static void label_changed_cb (glLabel *label,
112 /****************************************************************************/
113 /* Boilerplate Object stuff. */
114 /****************************************************************************/
115 G_DEFINE_TYPE (glWindow, gl_window, GTK_TYPE_WINDOW)
119 gl_window_class_init (glWindowClass *class)
121 GObjectClass *object_class = G_OBJECT_CLASS (class);
123 gl_debug (DEBUG_WINDOW, "START");
125 gl_window_parent_class = g_type_class_peek_parent (class);
127 object_class->finalize = gl_window_finalize;
128 object_class->dispose = gl_window_dispose;
130 gl_debug (DEBUG_WINDOW, "END");
135 gl_window_init (glWindow *window)
139 GtkWidget *status_hbox;
141 gl_debug (DEBUG_WINDOW, "START");
143 vbox1 = gtk_vbox_new (FALSE, 0);
144 gtk_container_add (GTK_CONTAINER (window), vbox1);
146 window->ui = ui = gl_ui_new (window);
147 gtk_box_pack_start (GTK_BOX (vbox1),
148 gtk_ui_manager_get_widget (ui, "/MenuBar"),
150 gtk_box_pack_start (GTK_BOX (vbox1),
151 gtk_ui_manager_get_widget (ui, "/MainToolBar"),
153 gtk_box_pack_start (GTK_BOX (vbox1),
154 gtk_ui_manager_get_widget (ui, "/DrawingToolBar"),
157 window->hbox = gtk_hbox_new (FALSE, 0);
158 gtk_box_pack_start (GTK_BOX (vbox1), window->hbox, TRUE, TRUE, 0);
160 window->sidebar = GL_UI_SIDEBAR (gl_ui_sidebar_new ());
161 gtk_box_pack_end (GTK_BOX (window->hbox), GTK_WIDGET (window->sidebar), FALSE, FALSE, 0);
163 window->property_bar = GL_UI_PROPERTY_BAR (gl_ui_property_bar_new ());
164 gtk_box_pack_start (GTK_BOX (vbox1), GTK_WIDGET (window->property_bar), FALSE, FALSE, 0);
166 status_hbox = gtk_hbox_new (FALSE, 0);
167 gtk_box_pack_start (GTK_BOX (vbox1), status_hbox, FALSE, FALSE, 0);
169 window->status_bar = gtk_statusbar_new ();
170 gtk_box_pack_start (GTK_BOX (status_hbox),
173 window->zoom_info = gtk_label_new (NULL);
174 gtk_widget_set_size_request (window->zoom_info, ZOOM_INFO_WIDTH, -1);
175 window->zoom_info_frame = gtk_frame_new (NULL);
176 gtk_frame_set_shadow_type (GTK_FRAME(window->zoom_info_frame), GTK_SHADOW_IN);
177 gtk_container_add (GTK_CONTAINER(window->zoom_info_frame), window->zoom_info);
178 gtk_widget_show_all (window->zoom_info_frame);
179 gtk_box_pack_end (GTK_BOX (status_hbox),
180 window->zoom_info_frame,
183 window->cursor_info = gtk_label_new (NULL);
184 gtk_widget_set_size_request (window->cursor_info, CURSOR_INFO_WIDTH, -1);
185 window->cursor_info_frame = gtk_frame_new (NULL);
186 gtk_frame_set_shadow_type (GTK_FRAME(window->cursor_info_frame), GTK_SHADOW_IN);
187 gtk_container_add (GTK_CONTAINER(window->cursor_info_frame), window->cursor_info);
188 gtk_widget_show_all (window->cursor_info_frame);
189 gtk_box_pack_end (GTK_BOX (status_hbox),
190 window->cursor_info_frame,
193 gtk_window_set_default_size (GTK_WINDOW (window),
194 DEFAULT_WINDOW_WIDTH,
195 DEFAULT_WINDOW_HEIGHT);
197 g_signal_connect (G_OBJECT(window), "delete-event",
198 G_CALLBACK(window_delete_event_cb), NULL);
200 window->menu_tips_context_id =
201 gtk_statusbar_get_context_id (GTK_STATUSBAR (window->status_bar), "menu_tips");
203 window->print_settings = NULL;
204 window->merge_dialog = NULL;
205 window->context_menu = GTK_MENU (gtk_ui_manager_get_widget (ui, "/ContextMenu"));
206 window->empty_selection_context_menu =
207 GTK_MENU (gtk_ui_manager_get_widget (ui, "/EmptySelectionContextMenu"));
211 window_list = g_list_append (window_list, window);
213 gl_debug (DEBUG_WINDOW, "END");
218 gl_window_finalize (GObject *object)
220 gl_debug (DEBUG_WINDOW, "START");
222 g_return_if_fail (object != NULL);
223 g_return_if_fail (GL_IS_WINDOW (object));
225 G_OBJECT_CLASS (gl_window_parent_class)->finalize (object);
227 gl_debug (DEBUG_WINDOW, "END");
232 gl_window_dispose (GObject *object)
235 GtkClipboard *clipboard;
237 gl_debug (DEBUG_WINDOW, "START");
239 g_return_if_fail (object != NULL);
240 g_return_if_fail (GL_IS_WINDOW (object));
242 window = GL_WINDOW (object);
243 window_list = g_list_remove (window_list, window);
246 gl_ui_unref(window->ui);
252 clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window),
253 GDK_SELECTION_CLIPBOARD);
255 g_signal_handlers_disconnect_by_func (G_OBJECT (clipboard),
256 G_CALLBACK (clipboard_changed_cb),
259 g_object_unref (window->label);
262 if (G_OBJECT_CLASS (gl_window_parent_class)->dispose) {
263 G_OBJECT_CLASS (gl_window_parent_class)->dispose (object);
266 gl_debug (DEBUG_WINDOW, "END");
270 /****************************************************************************/
271 /** Create a glabels window. */
272 /****************************************************************************/
278 gl_debug (DEBUG_WINDOW, "START");
280 window = g_object_new (GL_TYPE_WINDOW,
281 "title", _("(none) - gLabels"),
284 gl_debug (DEBUG_WINDOW, "window=%p", window);
285 gl_debug (DEBUG_WINDOW, "view=%p", window->view);
287 gl_debug (DEBUG_WINDOW, "END");
289 return GTK_WIDGET(window);
293 /****************************************************************************/
294 /** Create a glabels window from a label. */
295 /****************************************************************************/
297 gl_window_new_from_label (glLabel *label)
301 gl_debug (DEBUG_WINDOW, "START");
303 window = GL_WINDOW (gl_window_new ());
305 gl_window_set_label (window, label);
307 gl_debug (DEBUG_WINDOW, "END");
309 return GTK_WIDGET(window);
313 /****************************************************************************/
314 /** Create a glabels window from a glabels file. */
315 /****************************************************************************/
317 gl_window_new_from_file (const gchar *filename)
322 glXMLLabelStatus status;
324 gl_debug (DEBUG_WINDOW, "START");
326 window = GL_WINDOW (gl_window_new ());
328 abs_filename = gl_file_util_make_absolute (filename);
329 label = gl_xml_label_open (abs_filename, &status);
330 g_free (abs_filename);
332 gl_window_set_label (window, label);
334 gl_debug (DEBUG_WINDOW, "END");
336 return GTK_WIDGET(window);
340 /****************************************************************************/
341 /** Is window empty? */
342 /****************************************************************************/
344 gl_window_is_empty (glWindow *window)
346 g_return_val_if_fail (GL_IS_WINDOW (window), FALSE);
348 gl_debug (DEBUG_WINDOW, "return %d", (window->view == NULL) );
349 return ( window->view == NULL );
353 /****************************************************************************/
354 /** Create view from label and place in window. */
355 /****************************************************************************/
357 gl_window_set_label (glWindow *window,
361 GtkClipboard *clipboard;
362 GtkWidget *focus_widget;
364 gl_debug (DEBUG_WINDOW, "START");
366 g_return_if_fail (GL_IS_WINDOW (window));
367 g_return_if_fail (GL_IS_LABEL (label));
369 window->label = g_object_ref (label);
371 gl_label_clear_modified (label);
373 set_window_title (window, label);
375 if ( window->view != NULL ) {
376 gtk_widget_destroy (window->view);
380 window->view = gl_view_new (label);
381 gtk_box_pack_start (GTK_BOX (window->hbox), window->view, TRUE, TRUE, 0);
383 gtk_widget_show_all (window->view);
385 gl_view_zoom_to_fit (GL_VIEW(window->view));
387 if (gl_prefs_model_get_grid_visible (gl_prefs)) {
388 gl_view_show_grid (GL_VIEW(window->view));
390 gl_view_hide_grid (GL_VIEW(window->view));
393 if (gl_prefs_model_get_markup_visible (gl_prefs)) {
394 gl_view_show_markup (GL_VIEW(window->view));
396 gl_view_hide_markup (GL_VIEW(window->view));
399 gl_ui_update_all (window->ui, GL_VIEW(window->view));
401 gl_ui_property_bar_set_label (window->property_bar, window->label);
402 gl_ui_sidebar_set_label (window->sidebar, window->label);
404 string = g_strdup_printf ("%3.0f%%",
405 100.0*gl_view_get_zoom (GL_VIEW(window->view)));
406 gtk_label_set_text (GTK_LABEL(window->zoom_info), string);
410 clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window),
411 GDK_SELECTION_CLIPBOARD);
414 g_signal_connect (G_OBJECT(window->label), "selection_changed",
415 G_CALLBACK(selection_changed_cb), window);
417 g_signal_connect (G_OBJECT(window->view), "context_menu_activate",
418 G_CALLBACK(context_menu_activate_cb), window);
420 g_signal_connect (G_OBJECT(window->view), "zoom_changed",
421 G_CALLBACK(zoom_changed_cb), window);
423 g_signal_connect (G_OBJECT(window->view), "pointer_moved",
424 G_CALLBACK(pointer_moved_cb), window);
426 g_signal_connect (G_OBJECT(window->view), "pointer_exit",
427 G_CALLBACK(pointer_exit_cb), window);
429 g_signal_connect (G_OBJECT(label), "name_changed",
430 G_CALLBACK(name_changed_cb), window);
432 g_signal_connect (G_OBJECT(label), "modified_changed",
433 G_CALLBACK(modified_changed_cb), window);
435 g_signal_connect (G_OBJECT(clipboard), "owner_change",
436 G_CALLBACK(clipboard_changed_cb), window);
438 g_signal_connect (G_OBJECT(window), "set_focus",
439 G_CALLBACK(focus_widget_changed_cb), window);
441 /* Initialize "Paste" sensitivity. */
442 focus_widget = gtk_window_get_focus (GTK_WINDOW (window));
443 set_copy_paste_sensitivity (window, focus_widget);
445 g_signal_connect (G_OBJECT(label), "changed",
446 G_CALLBACK(label_changed_cb), window);
448 gl_debug (DEBUG_WINDOW, "END");
452 /****************************************************************************/
453 /** Return list of glabels windows. */
454 /****************************************************************************/
456 gl_window_get_window_list (void)
458 gl_debug (DEBUG_WINDOW, "");
463 /*---------------------------------------------------------------------------*/
464 /** PRIVATE. Set window title based on name and state of label. */
465 /*---------------------------------------------------------------------------*/
467 set_window_title (glWindow *window,
472 gl_debug (DEBUG_WINDOW, "START");
474 g_return_if_fail (window && GL_IS_WINDOW (window));
475 g_return_if_fail (label && GL_IS_LABEL (label));
477 name = gl_label_get_short_name (label);
478 g_return_if_fail (name != NULL);
480 if (gl_label_is_modified (label)) {
481 title = g_strdup_printf ("%s %s - gLabels",
482 name, _("(modified)"));
484 title = g_strdup_printf ("%s - gLabels", name);
487 gtk_window_set_title (GTK_WINDOW(window), title);
492 gl_debug (DEBUG_WINDOW, "END");
496 /*-------------------------------------------------------------------------*/
497 /** PRIVATE. Window "delete-event" callback. */
498 /*-------------------------------------------------------------------------*/
500 window_delete_event_cb (glWindow *window,
504 gl_debug (DEBUG_WINDOW, "START");
506 g_return_val_if_fail (window && GL_IS_WINDOW (window), TRUE);
508 gl_file_close (window);
510 gl_debug (DEBUG_WINDOW, "END");
516 /*---------------------------------------------------------------------------*/
517 /** PRIVATE. View "selection state changed" callback. */
518 /*---------------------------------------------------------------------------*/
520 selection_changed_cb (glLabel *label,
523 gl_debug (DEBUG_WINDOW, "START");
525 g_return_if_fail (label && GL_IS_LABEL (label));
526 g_return_if_fail (window && GL_IS_WINDOW (window));
528 gl_ui_update_selection_verbs (window->ui, GL_VIEW (window->view), TRUE);
530 gl_debug (DEBUG_WINDOW, "END");
534 /*---------------------------------------------------------------------------*/
535 /** PRIVATE. View "context menu activate" callback. */
536 /*---------------------------------------------------------------------------*/
538 context_menu_activate_cb (glView *view,
540 guint32 activate_time,
543 gl_debug (DEBUG_WINDOW, "START");
545 g_return_if_fail (view && GL_IS_VIEW (view));
546 g_return_if_fail (window && GL_IS_WINDOW (window));
548 if (gl_label_is_selection_empty (view->label)) {
550 gtk_menu_popup (GTK_MENU (window->empty_selection_context_menu),
551 NULL, NULL, NULL, NULL, button, activate_time);
555 gtk_menu_popup (GTK_MENU (window->context_menu),
556 NULL, NULL, NULL, NULL, button, activate_time);
560 gl_debug (DEBUG_WINDOW, "END");
564 /*---------------------------------------------------------------------------*/
565 /** PRIVATE. View "zoom state changed" callback. */
566 /*---------------------------------------------------------------------------*/
568 zoom_changed_cb (glView *view,
574 gl_debug (DEBUG_WINDOW, "START");
576 g_return_if_fail (view && GL_IS_VIEW (view));
577 g_return_if_fail (window && GL_IS_WINDOW (window));
579 string = g_strdup_printf ("%3.0f%%", 100.0*zoom);
580 gtk_label_set_text (GTK_LABEL(window->zoom_info), string);
583 gl_ui_update_zoom_verbs (window->ui, view);
585 gl_debug (DEBUG_WINDOW, "END");
589 /*---------------------------------------------------------------------------*/
590 /** PRIVATE. View "pointer moved" callback. */
591 /*---------------------------------------------------------------------------*/
593 pointer_moved_cb (glView *view,
600 gdouble units_per_point;
601 gint units_precision;
603 gl_debug (DEBUG_WINDOW, "START");
605 g_return_if_fail (view && GL_IS_VIEW (view));
606 g_return_if_fail (window && GL_IS_WINDOW (window));
608 units = gl_prefs_model_get_units (gl_prefs);
609 units_per_point = lgl_units_get_units_per_point (units);
610 units_precision = gl_units_util_get_precision (units);
612 string = g_strdup_printf ("%.*f, %.*f",
613 units_precision, x*units_per_point,
614 units_precision, y*units_per_point);
615 gtk_label_set_text (GTK_LABEL(window->cursor_info), string);
618 gl_debug (DEBUG_WINDOW, "END");
622 /*---------------------------------------------------------------------------*/
623 /** PRIVATE. View "pointer exit" callback. */
624 /*---------------------------------------------------------------------------*/
626 pointer_exit_cb (glView *view,
629 gl_debug (DEBUG_WINDOW, "START");
631 g_return_if_fail (view && GL_IS_VIEW (view));
632 g_return_if_fail (window && GL_IS_WINDOW (window));
634 gtk_label_set_text (GTK_LABEL(window->cursor_info), "");
636 gl_debug (DEBUG_WINDOW, "END");
640 /*---------------------------------------------------------------------------*/
641 /** PRIVATE. Label "name changed" callback. */
642 /*---------------------------------------------------------------------------*/
644 name_changed_cb (glLabel *label,
647 gl_debug (DEBUG_WINDOW, "START");
649 g_return_if_fail (label && GL_IS_LABEL (label));
650 g_return_if_fail (window && GL_IS_WINDOW (window));
652 set_window_title (window, label);
654 gl_debug (DEBUG_WINDOW, "END");
658 /*---------------------------------------------------------------------------*/
659 /** PRIVATE. Label "modified state changed" callback. */
660 /*---------------------------------------------------------------------------*/
662 modified_changed_cb (glLabel *label,
665 gl_debug (DEBUG_WINDOW, "START");
667 g_return_if_fail (label && GL_IS_LABEL (label));
668 g_return_if_fail (window && GL_IS_WINDOW (window));
670 set_window_title (window, label);
672 gl_ui_update_modified_verbs (window->ui, label);
674 gl_debug (DEBUG_WINDOW, "END");
678 /*---------------------------------------------------------------------------*/
679 /** PRIVATE. Label "changed" callback. */
680 /*---------------------------------------------------------------------------*/
682 label_changed_cb (glLabel *label,
685 gl_debug (DEBUG_WINDOW, "START");
687 g_return_if_fail (label && GL_IS_LABEL (label));
688 g_return_if_fail (window && GL_IS_WINDOW (window));
690 gl_ui_update_undo_redo_verbs (window->ui, label);
692 gl_debug (DEBUG_WINDOW, "END");
697 /*---------------------------------------------------------------------------*/
698 /** PRIVATE. Clipboard "owner change" callback. */
699 /*---------------------------------------------------------------------------*/
701 clipboard_changed_cb (GtkClipboard *clipboard,
705 GtkWidget *focus_widget;
707 gl_debug (DEBUG_WINDOW, "START");
709 g_return_if_fail (window && GL_IS_WINDOW (window));
711 focus_widget = gtk_window_get_focus (GTK_WINDOW (window));
712 set_copy_paste_sensitivity (window, focus_widget);
714 gl_debug (DEBUG_WINDOW, "END");
718 /*---------------------------------------------------------------------------*/
719 /** PRIVATE. Window "set-focus" callback. */
720 /*---------------------------------------------------------------------------*/
722 focus_widget_changed_cb (GtkWindow *gtk_window,
726 gl_debug (DEBUG_WINDOW, "START");
728 g_return_if_fail (window && GL_IS_WINDOW (window));
732 gl_debug (DEBUG_WINDOW, "SET-FOCUS %x %s\n",
734 G_OBJECT_TYPE_NAME (widget));
736 set_copy_paste_sensitivity (window, widget);
739 gl_debug (DEBUG_WINDOW, "END");
743 /*---------------------------------------------------------------------------*/
744 /** PRIVATE. Set paste sensitivity. */
745 /*---------------------------------------------------------------------------*/
747 set_copy_paste_sensitivity (glWindow *window,
748 GtkWidget *focus_widget)
750 gl_debug (DEBUG_WINDOW, "START");
752 g_return_if_fail (window && GL_IS_WINDOW (window));
754 if ( focus_widget == GL_VIEW(window->view)->canvas )
756 gl_ui_update_selection_verbs (window->ui, GL_VIEW (window->view), TRUE);
758 gl_ui_update_paste_verbs (window->ui, gl_label_can_paste (window->label));
762 gl_ui_update_selection_verbs (window->ui, GL_VIEW (window->view), FALSE);
763 gl_ui_update_paste_verbs (window->ui, FALSE);
766 gl_debug (DEBUG_WINDOW, "END");
771 * Local Variables: -- emacs
773 * c-basic-offset: 8 -- emacs
774 * tab-width: 8 -- emacs
775 * indent-tabs-mode: nil -- emacs