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 50
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_destroy (GtkObject *gtk_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);
122 GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (class);
124 gl_debug (DEBUG_WINDOW, "START");
126 gl_window_parent_class = g_type_class_peek_parent (class);
128 object_class->finalize = gl_window_finalize;
130 gtk_object_class->destroy = gl_window_destroy;
132 gl_debug (DEBUG_WINDOW, "END");
137 gl_window_init (glWindow *window)
141 GtkWidget *status_hbox;
143 gl_debug (DEBUG_WINDOW, "START");
145 vbox1 = gtk_vbox_new (FALSE, 0);
146 gtk_container_add (GTK_CONTAINER (window), vbox1);
148 window->ui = ui = gl_ui_new (window);
149 gtk_box_pack_start (GTK_BOX (vbox1),
150 gtk_ui_manager_get_widget (ui, "/MenuBar"),
152 gtk_box_pack_start (GTK_BOX (vbox1),
153 gtk_ui_manager_get_widget (ui, "/MainToolBar"),
155 gtk_box_pack_start (GTK_BOX (vbox1),
156 gtk_ui_manager_get_widget (ui, "/DrawingToolBar"),
159 window->hbox = gtk_hbox_new (FALSE, 0);
160 gtk_box_pack_start (GTK_BOX (vbox1), window->hbox, TRUE, TRUE, 0);
162 window->sidebar = GL_UI_SIDEBAR (gl_ui_sidebar_new ());
163 gtk_box_pack_end (GTK_BOX (window->hbox), GTK_WIDGET (window->sidebar), FALSE, FALSE, 0);
165 window->property_bar = GL_UI_PROPERTY_BAR (gl_ui_property_bar_new ());
166 gtk_box_pack_start (GTK_BOX (vbox1), GTK_WIDGET (window->property_bar), FALSE, FALSE, 0);
168 status_hbox = gtk_hbox_new (FALSE, 0);
169 gtk_box_pack_start (GTK_BOX (vbox1), status_hbox, FALSE, FALSE, 0);
171 window->status_bar = gtk_statusbar_new ();
172 gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR (window->status_bar), FALSE);
173 gtk_box_pack_start (GTK_BOX (status_hbox),
176 window->zoom_info = gtk_label_new (NULL);
177 gtk_widget_set_size_request (window->zoom_info, ZOOM_INFO_WIDTH, -1);
178 window->zoom_info_frame = gtk_frame_new (NULL);
179 gtk_frame_set_shadow_type (GTK_FRAME(window->zoom_info_frame), GTK_SHADOW_IN);
180 gtk_container_add (GTK_CONTAINER(window->zoom_info_frame), window->zoom_info);
181 gtk_widget_show_all (window->zoom_info_frame);
182 gtk_box_pack_end (GTK_BOX (status_hbox),
183 window->zoom_info_frame,
186 window->cursor_info = gtk_label_new (NULL);
187 gtk_widget_set_size_request (window->cursor_info, CURSOR_INFO_WIDTH, -1);
188 window->cursor_info_frame = gtk_frame_new (NULL);
189 gtk_frame_set_shadow_type (GTK_FRAME(window->cursor_info_frame), GTK_SHADOW_IN);
190 gtk_container_add (GTK_CONTAINER(window->cursor_info_frame), window->cursor_info);
191 gtk_widget_show_all (window->cursor_info_frame);
192 gtk_box_pack_end (GTK_BOX (status_hbox),
193 window->cursor_info_frame,
196 gtk_window_set_default_size (GTK_WINDOW (window),
197 DEFAULT_WINDOW_WIDTH,
198 DEFAULT_WINDOW_HEIGHT);
200 g_signal_connect (G_OBJECT(window), "delete-event",
201 G_CALLBACK(window_delete_event_cb), NULL);
203 window->menu_tips_context_id =
204 gtk_statusbar_get_context_id (GTK_STATUSBAR (window->status_bar), "menu_tips");
206 window->print_settings = NULL;
207 window->merge_dialog = NULL;
208 window->context_menu = GTK_MENU (gtk_ui_manager_get_widget (ui, "/ContextMenu"));
209 window->empty_selection_context_menu =
210 GTK_MENU (gtk_ui_manager_get_widget (ui, "/EmptySelectionContextMenu"));
214 window_list = g_list_append (window_list, window);
216 gl_debug (DEBUG_WINDOW, "END");
221 gl_window_finalize (GObject *object)
223 gl_debug (DEBUG_WINDOW, "START");
225 g_return_if_fail (object != NULL);
226 g_return_if_fail (GL_IS_WINDOW (object));
228 G_OBJECT_CLASS (gl_window_parent_class)->finalize (object);
230 gl_debug (DEBUG_WINDOW, "END");
235 gl_window_destroy (GtkObject *gtk_object)
238 GtkClipboard *clipboard;
240 gl_debug (DEBUG_WINDOW, "START");
242 g_return_if_fail (gtk_object != NULL);
243 g_return_if_fail (GL_IS_WINDOW (gtk_object));
245 window = GL_WINDOW (gtk_object);
246 window_list = g_list_remove (window_list, window);
249 gl_ui_unref(window->ui);
255 clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window),
256 GDK_SELECTION_CLIPBOARD);
258 g_signal_handlers_disconnect_by_func (G_OBJECT (clipboard),
259 G_CALLBACK (clipboard_changed_cb),
262 g_object_unref (window->label);
265 if (GTK_OBJECT_CLASS (gl_window_parent_class)->destroy) {
266 GTK_OBJECT_CLASS (gl_window_parent_class)->destroy (gtk_object);
269 gl_debug (DEBUG_WINDOW, "END");
273 /****************************************************************************/
274 /** Create a glabels window. */
275 /****************************************************************************/
281 gl_debug (DEBUG_WINDOW, "START");
283 window = g_object_new (GL_TYPE_WINDOW,
284 "title", _("(none) - gLabels"),
287 gl_debug (DEBUG_WINDOW, "window=%p", window);
288 gl_debug (DEBUG_WINDOW, "view=%p", window->view);
290 gl_debug (DEBUG_WINDOW, "END");
292 return GTK_WIDGET(window);
296 /****************************************************************************/
297 /** Create a glabels window from a label. */
298 /****************************************************************************/
300 gl_window_new_from_label (glLabel *label)
304 gl_debug (DEBUG_WINDOW, "START");
306 window = GL_WINDOW (gl_window_new ());
308 gl_window_set_label (window, label);
310 gl_debug (DEBUG_WINDOW, "END");
312 return GTK_WIDGET(window);
316 /****************************************************************************/
317 /** Create a glabels window from a glabels file. */
318 /****************************************************************************/
320 gl_window_new_from_file (const gchar *filename)
325 glXMLLabelStatus status;
327 gl_debug (DEBUG_WINDOW, "START");
329 window = GL_WINDOW (gl_window_new ());
331 abs_filename = gl_file_util_make_absolute (filename);
332 label = gl_xml_label_open (abs_filename, &status);
333 g_free (abs_filename);
335 gl_window_set_label (window, label);
337 gl_debug (DEBUG_WINDOW, "END");
339 return GTK_WIDGET(window);
343 /****************************************************************************/
344 /** Is window empty? */
345 /****************************************************************************/
347 gl_window_is_empty (glWindow *window)
349 g_return_val_if_fail (GL_IS_WINDOW (window), FALSE);
351 gl_debug (DEBUG_WINDOW, "return %d", (window->view == NULL) );
352 return ( window->view == NULL );
356 /****************************************************************************/
357 /** Create view from label and place in window. */
358 /****************************************************************************/
360 gl_window_set_label (glWindow *window,
364 GtkClipboard *clipboard;
365 GtkWidget *focus_widget;
367 gl_debug (DEBUG_WINDOW, "START");
369 g_return_if_fail (GL_IS_WINDOW (window));
370 g_return_if_fail (GL_IS_LABEL (label));
372 window->label = g_object_ref (label);
374 gl_label_clear_modified (label);
376 set_window_title (window, label);
378 if ( window->view != NULL ) {
379 gtk_widget_destroy (window->view);
383 window->view = gl_view_new (label);
384 gtk_box_pack_start (GTK_BOX (window->hbox), window->view, TRUE, TRUE, 0);
386 gtk_widget_show_all (window->view);
388 gl_view_zoom_to_fit (GL_VIEW(window->view));
390 if (gl_prefs_model_get_grid_visible (gl_prefs)) {
391 gl_view_show_grid (GL_VIEW(window->view));
393 gl_view_hide_grid (GL_VIEW(window->view));
396 if (gl_prefs_model_get_markup_visible (gl_prefs)) {
397 gl_view_show_markup (GL_VIEW(window->view));
399 gl_view_hide_markup (GL_VIEW(window->view));
402 gl_ui_update_all (window->ui, GL_VIEW(window->view));
404 gl_ui_property_bar_set_label (window->property_bar, window->label);
405 gl_ui_sidebar_set_label (window->sidebar, window->label);
407 string = g_strdup_printf ("%3.0f%%",
408 100.0*gl_view_get_zoom (GL_VIEW(window->view)));
409 gtk_label_set_text (GTK_LABEL(window->zoom_info), string);
413 clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window),
414 GDK_SELECTION_CLIPBOARD);
417 g_signal_connect (G_OBJECT(window->label), "selection_changed",
418 G_CALLBACK(selection_changed_cb), window);
420 g_signal_connect (G_OBJECT(window->view), "context_menu_activate",
421 G_CALLBACK(context_menu_activate_cb), window);
423 g_signal_connect (G_OBJECT(window->view), "zoom_changed",
424 G_CALLBACK(zoom_changed_cb), window);
426 g_signal_connect (G_OBJECT(window->view), "pointer_moved",
427 G_CALLBACK(pointer_moved_cb), window);
429 g_signal_connect (G_OBJECT(window->view), "pointer_exit",
430 G_CALLBACK(pointer_exit_cb), window);
432 g_signal_connect (G_OBJECT(label), "name_changed",
433 G_CALLBACK(name_changed_cb), window);
435 g_signal_connect (G_OBJECT(label), "modified_changed",
436 G_CALLBACK(modified_changed_cb), window);
438 g_signal_connect (G_OBJECT(clipboard), "owner_change",
439 G_CALLBACK(clipboard_changed_cb), window);
441 g_signal_connect (G_OBJECT(window), "set_focus",
442 G_CALLBACK(focus_widget_changed_cb), window);
444 /* Initialize "Paste" sensitivity. */
445 focus_widget = gtk_window_get_focus (GTK_WINDOW (window));
446 set_copy_paste_sensitivity (window, focus_widget);
448 g_signal_connect (G_OBJECT(label), "changed",
449 G_CALLBACK(label_changed_cb), window);
451 gl_debug (DEBUG_WINDOW, "END");
455 /****************************************************************************/
456 /** Return list of glabels windows. */
457 /****************************************************************************/
459 gl_window_get_window_list (void)
461 gl_debug (DEBUG_WINDOW, "");
466 /*---------------------------------------------------------------------------*/
467 /** PRIVATE. Set window title based on name and state of label. */
468 /*---------------------------------------------------------------------------*/
470 set_window_title (glWindow *window,
475 gl_debug (DEBUG_WINDOW, "START");
477 g_return_if_fail (window && GL_IS_WINDOW (window));
478 g_return_if_fail (label && GL_IS_LABEL (label));
480 name = gl_label_get_short_name (label);
481 g_return_if_fail (name != NULL);
483 if (gl_label_is_modified (label)) {
484 title = g_strdup_printf ("%s %s - gLabels",
485 name, _("(modified)"));
487 title = g_strdup_printf ("%s - gLabels", name);
490 gtk_window_set_title (GTK_WINDOW(window), title);
495 gl_debug (DEBUG_WINDOW, "END");
499 /*-------------------------------------------------------------------------*/
500 /** PRIVATE. Window "delete-event" callback. */
501 /*-------------------------------------------------------------------------*/
503 window_delete_event_cb (glWindow *window,
507 gl_debug (DEBUG_WINDOW, "START");
509 g_return_val_if_fail (window && GL_IS_WINDOW (window), TRUE);
511 gl_file_close (window);
513 gl_debug (DEBUG_WINDOW, "END");
519 /*---------------------------------------------------------------------------*/
520 /** PRIVATE. View "selection state changed" callback. */
521 /*---------------------------------------------------------------------------*/
523 selection_changed_cb (glLabel *label,
526 gl_debug (DEBUG_WINDOW, "START");
528 g_return_if_fail (label && GL_IS_LABEL (label));
529 g_return_if_fail (window && GL_IS_WINDOW (window));
531 gl_ui_update_selection_verbs (window->ui, GL_VIEW (window->view), TRUE);
533 gl_debug (DEBUG_WINDOW, "END");
537 /*---------------------------------------------------------------------------*/
538 /** PRIVATE. View "context menu activate" callback. */
539 /*---------------------------------------------------------------------------*/
541 context_menu_activate_cb (glView *view,
543 guint32 activate_time,
546 gl_debug (DEBUG_WINDOW, "START");
548 g_return_if_fail (view && GL_IS_VIEW (view));
549 g_return_if_fail (window && GL_IS_WINDOW (window));
551 if (gl_label_is_selection_empty (view->label)) {
553 gtk_menu_popup (GTK_MENU (window->empty_selection_context_menu),
554 NULL, NULL, NULL, NULL, button, activate_time);
558 gtk_menu_popup (GTK_MENU (window->context_menu),
559 NULL, NULL, NULL, NULL, button, activate_time);
563 gl_debug (DEBUG_WINDOW, "END");
567 /*---------------------------------------------------------------------------*/
568 /** PRIVATE. View "zoom state changed" callback. */
569 /*---------------------------------------------------------------------------*/
571 zoom_changed_cb (glView *view,
577 gl_debug (DEBUG_WINDOW, "START");
579 g_return_if_fail (view && GL_IS_VIEW (view));
580 g_return_if_fail (window && GL_IS_WINDOW (window));
582 string = g_strdup_printf ("%3.0f%%", 100.0*zoom);
583 gtk_label_set_text (GTK_LABEL(window->zoom_info), string);
586 gl_ui_update_zoom_verbs (window->ui, view);
588 gl_debug (DEBUG_WINDOW, "END");
592 /*---------------------------------------------------------------------------*/
593 /** PRIVATE. View "pointer moved" callback. */
594 /*---------------------------------------------------------------------------*/
596 pointer_moved_cb (glView *view,
603 gdouble units_per_point;
604 gint units_precision;
606 gl_debug (DEBUG_WINDOW, "START");
608 g_return_if_fail (view && GL_IS_VIEW (view));
609 g_return_if_fail (window && GL_IS_WINDOW (window));
611 units = gl_prefs_model_get_units (gl_prefs);
612 units_per_point = lgl_units_get_units_per_point (units);
613 units_precision = gl_units_util_get_precision (units);
615 string = g_strdup_printf ("%.*f, %.*f",
616 units_precision, x*units_per_point,
617 units_precision, y*units_per_point);
618 gtk_label_set_text (GTK_LABEL(window->cursor_info), string);
621 gl_debug (DEBUG_WINDOW, "END");
625 /*---------------------------------------------------------------------------*/
626 /** PRIVATE. View "pointer exit" callback. */
627 /*---------------------------------------------------------------------------*/
629 pointer_exit_cb (glView *view,
632 gl_debug (DEBUG_WINDOW, "START");
634 g_return_if_fail (view && GL_IS_VIEW (view));
635 g_return_if_fail (window && GL_IS_WINDOW (window));
637 gtk_label_set_text (GTK_LABEL(window->cursor_info), "");
639 gl_debug (DEBUG_WINDOW, "END");
643 /*---------------------------------------------------------------------------*/
644 /** PRIVATE. Label "name changed" callback. */
645 /*---------------------------------------------------------------------------*/
647 name_changed_cb (glLabel *label,
650 gl_debug (DEBUG_WINDOW, "START");
652 g_return_if_fail (label && GL_IS_LABEL (label));
653 g_return_if_fail (window && GL_IS_WINDOW (window));
655 set_window_title (window, label);
657 gl_debug (DEBUG_WINDOW, "END");
661 /*---------------------------------------------------------------------------*/
662 /** PRIVATE. Label "modified state changed" callback. */
663 /*---------------------------------------------------------------------------*/
665 modified_changed_cb (glLabel *label,
668 gl_debug (DEBUG_WINDOW, "START");
670 g_return_if_fail (label && GL_IS_LABEL (label));
671 g_return_if_fail (window && GL_IS_WINDOW (window));
673 set_window_title (window, label);
675 gl_ui_update_modified_verbs (window->ui, label);
677 gl_debug (DEBUG_WINDOW, "END");
681 /*---------------------------------------------------------------------------*/
682 /** PRIVATE. Label "changed" callback. */
683 /*---------------------------------------------------------------------------*/
685 label_changed_cb (glLabel *label,
688 gl_debug (DEBUG_WINDOW, "START");
690 g_return_if_fail (label && GL_IS_LABEL (label));
691 g_return_if_fail (window && GL_IS_WINDOW (window));
693 gl_ui_update_undo_redo_verbs (window->ui, label);
695 gl_debug (DEBUG_WINDOW, "END");
700 /*---------------------------------------------------------------------------*/
701 /** PRIVATE. Clipboard "owner change" callback. */
702 /*---------------------------------------------------------------------------*/
704 clipboard_changed_cb (GtkClipboard *clipboard,
708 GtkWidget *focus_widget;
710 gl_debug (DEBUG_WINDOW, "START");
712 g_return_if_fail (window && GL_IS_WINDOW (window));
714 focus_widget = gtk_window_get_focus (GTK_WINDOW (window));
715 set_copy_paste_sensitivity (window, focus_widget);
717 gl_debug (DEBUG_WINDOW, "END");
721 /*---------------------------------------------------------------------------*/
722 /** PRIVATE. Window "set-focus" callback. */
723 /*---------------------------------------------------------------------------*/
725 focus_widget_changed_cb (GtkWindow *gtk_window,
729 gl_debug (DEBUG_WINDOW, "START");
731 g_return_if_fail (window && GL_IS_WINDOW (window));
735 gl_debug (DEBUG_WINDOW, "SET-FOCUS %x %s\n",
737 G_OBJECT_TYPE_NAME (widget));
739 set_copy_paste_sensitivity (window, widget);
742 gl_debug (DEBUG_WINDOW, "END");
746 /*---------------------------------------------------------------------------*/
747 /** PRIVATE. Set paste sensitivity. */
748 /*---------------------------------------------------------------------------*/
750 set_copy_paste_sensitivity (glWindow *window,
751 GtkWidget *focus_widget)
753 gl_debug (DEBUG_WINDOW, "START");
755 g_return_if_fail (window && GL_IS_WINDOW (window));
757 if ( focus_widget == GL_VIEW(window->view)->canvas )
759 gl_ui_update_selection_verbs (window->ui, GL_VIEW (window->view), TRUE);
761 gl_ui_update_paste_verbs (window->ui, gl_label_can_paste (window->label));
765 gl_ui_update_selection_verbs (window->ui, GL_VIEW (window->view), FALSE);
766 gl_ui_update_paste_verbs (window->ui, FALSE);
769 gl_debug (DEBUG_WINDOW, "END");
774 * Local Variables: -- emacs
776 * c-basic-offset: 8 -- emacs
777 * tab-width: 8 -- emacs
778 * indent-tabs-mode: nil -- emacs