]> git.sur5r.net Git - glabels/blob - glabels2/src/window.c
2009-09-17 Jim Evins <evins@snaught.com>
[glabels] / glabels2 / src / window.c
1 /*
2  *  window.c
3  *  Copyright (C) 2002-2009  Jim Evins <evins@snaught.com>.
4  *
5  *  This file is part of gLabels.
6  *
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.
11  *
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.
16  *
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/>.
19  */
20
21 #include <config.h>
22
23 #include "window.h"
24
25 #include <glib/gi18n.h>
26 #include <gtk/gtk.h>
27
28 #include "ui.h"
29 #include "ui-commands.h"
30 #include "util.h"
31 #include "xml-label.h"
32 #include "prefs.h"
33 #include "file.h"
34
35 #include "debug.h"
36
37
38 /*===========================================================================*/
39 /* Private macros and constants.                                             */
40 /*===========================================================================*/
41
42 #define DEFAULT_WINDOW_WIDTH  788
43 #define DEFAULT_WINDOW_HEIGHT 600
44
45 #define CURSOR_INFO_WIDTH     150
46 #define ZOOM_INFO_WIDTH        50
47
48
49 /*===========================================================================*/
50 /* Private globals                                                           */
51 /*===========================================================================*/
52
53 static GList *window_list = NULL;
54
55
56 /*===========================================================================*/
57 /* Local function prototypes                                                 */
58 /*===========================================================================*/
59
60 static void     gl_window_finalize     (GObject       *object);
61 static void     gl_window_destroy      (GtkObject     *gtk_object);
62
63 static void     set_window_title       (glWindow *window,
64                                         glLabel  *label);
65
66 static gboolean window_delete_event_cb (glWindow      *window,
67                                         GdkEvent      *event,
68                                         gpointer       user_data);
69
70 static void     selection_changed_cb   (glView        *view,
71                                         glWindow      *window);
72
73 static void   context_menu_activate_cb (glView       *view,
74                                         gint          button,
75                                         guint32       activate_time,
76                                         glWindow     *window);
77
78 static void     zoom_changed_cb        (glView        *view,
79                                         gdouble        zoom,
80                                         glWindow      *window);
81
82 static void     pointer_moved_cb       (glView        *view,
83                                         gdouble        x,
84                                         gdouble        y,
85                                         glWindow      *window);
86
87 static void     pointer_exit_cb        (glView        *view,
88                                         glWindow      *window);
89
90 static void     name_changed_cb        (glLabel       *label,
91                                         glWindow      *window);
92
93 static void     modified_changed_cb    (glLabel       *label,
94                                         glWindow      *window);
95
96
97 /****************************************************************************/
98 /* Boilerplate Object stuff.                                                */
99 /****************************************************************************/
100 G_DEFINE_TYPE (glWindow, gl_window, GTK_TYPE_WINDOW);
101
102
103 static void
104 gl_window_class_init (glWindowClass *class)
105 {
106         GObjectClass   *object_class     = G_OBJECT_CLASS (class);
107         GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (class);
108
109         gl_debug (DEBUG_WINDOW, "START");
110
111         gl_window_parent_class = g_type_class_peek_parent (class);
112
113         object_class->finalize = gl_window_finalize;
114
115         gtk_object_class->destroy = gl_window_destroy;
116
117         gl_debug (DEBUG_WINDOW, "END");
118 }
119
120
121 static void
122 gl_window_init (glWindow *window)
123 {
124         GtkWidget        *vbox1;
125         GtkUIManager     *ui;
126         GtkWidget        *status_hbox;
127
128         gl_debug (DEBUG_WINDOW, "START");
129
130         vbox1 = gtk_vbox_new (FALSE, 0);
131         gtk_container_add (GTK_CONTAINER (window), vbox1);
132
133         window->ui = ui = gl_ui_new (window);
134         gtk_box_pack_start (GTK_BOX (vbox1),
135                             gtk_ui_manager_get_widget (ui, "/MenuBar"),
136                             FALSE, FALSE, 0);
137         gtk_box_pack_start (GTK_BOX (vbox1),
138                             gtk_ui_manager_get_widget (ui, "/MainToolBar"),
139                             FALSE, FALSE, 0);
140         gtk_box_pack_start (GTK_BOX (vbox1),
141                             gtk_ui_manager_get_widget (ui, "/DrawingToolBar"),
142                             FALSE, FALSE, 0);
143
144         window->hbox = gtk_hbox_new (FALSE, 0);
145         gtk_box_pack_start (GTK_BOX (vbox1), window->hbox, TRUE, TRUE, 0);
146
147         window->sidebar = GL_UI_SIDEBAR (gl_ui_sidebar_new ());
148         gtk_box_pack_end (GTK_BOX (window->hbox), GTK_WIDGET (window->sidebar), FALSE, FALSE, 0);
149
150         window->property_bar = GL_UI_PROPERTY_BAR (gl_ui_property_bar_new ());
151         gtk_box_pack_start (GTK_BOX (vbox1), GTK_WIDGET (window->property_bar), FALSE, FALSE, 0);
152
153         status_hbox = gtk_hbox_new (FALSE, 0);
154         gtk_box_pack_start (GTK_BOX (vbox1), status_hbox, FALSE, FALSE, 0);
155
156         window->status_bar = gtk_statusbar_new ();
157         gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR (window->status_bar), FALSE);
158         gtk_box_pack_start (GTK_BOX (status_hbox),
159                             window->status_bar,
160                             TRUE, TRUE, 0);
161         window->zoom_info = gtk_label_new (NULL);
162         gtk_widget_set_size_request (window->zoom_info, ZOOM_INFO_WIDTH, -1);
163         window->zoom_info_frame = gtk_frame_new (NULL);
164         gtk_frame_set_shadow_type (GTK_FRAME(window->zoom_info_frame), GTK_SHADOW_IN);
165         gtk_container_add (GTK_CONTAINER(window->zoom_info_frame), window->zoom_info);
166         gtk_widget_show_all (window->zoom_info_frame);
167         gtk_box_pack_end (GTK_BOX (status_hbox),
168                           window->zoom_info_frame,
169                           FALSE, FALSE, 0);
170
171         window->cursor_info = gtk_label_new (NULL);
172         gtk_widget_set_size_request (window->cursor_info, CURSOR_INFO_WIDTH, -1);
173         window->cursor_info_frame = gtk_frame_new (NULL);
174         gtk_frame_set_shadow_type (GTK_FRAME(window->cursor_info_frame), GTK_SHADOW_IN);
175         gtk_container_add (GTK_CONTAINER(window->cursor_info_frame), window->cursor_info);
176         gtk_widget_show_all (window->cursor_info_frame);
177         gtk_box_pack_end (GTK_BOX (status_hbox),
178                           window->cursor_info_frame,
179                           FALSE, FALSE, 0);
180
181         gtk_window_set_default_size (GTK_WINDOW (window),
182                                      DEFAULT_WINDOW_WIDTH,
183                                      DEFAULT_WINDOW_HEIGHT);
184
185         g_signal_connect (G_OBJECT(window), "delete-event",
186                           G_CALLBACK(window_delete_event_cb), NULL);
187         
188         window->menu_tips_context_id =
189                 gtk_statusbar_get_context_id (GTK_STATUSBAR (window->status_bar), "menu_tips");
190
191         window->print_settings = NULL;
192         window->merge_dialog = NULL;
193         window->context_menu = GTK_MENU (gtk_ui_manager_get_widget (ui, "/ContextMenu"));
194         window->empty_selection_context_menu =
195                 GTK_MENU (gtk_ui_manager_get_widget (ui, "/EmptySelectionContextMenu"));
196
197         window->view = NULL;
198
199         window_list = g_list_append (window_list, window);
200
201         gl_debug (DEBUG_WINDOW, "END");
202 }
203
204
205 static void
206 gl_window_finalize (GObject *object)
207 {
208         gl_debug (DEBUG_WINDOW, "START");
209
210         g_return_if_fail (object != NULL);
211         g_return_if_fail (GL_IS_WINDOW (object));
212
213         G_OBJECT_CLASS (gl_window_parent_class)->finalize (object);
214
215         gl_debug (DEBUG_WINDOW, "END");
216 }
217
218
219 static void
220 gl_window_destroy (GtkObject *gtk_object)
221 {
222         glWindow *window;
223
224         gl_debug (DEBUG_WINDOW, "START");
225
226         g_return_if_fail (gtk_object != NULL);
227         g_return_if_fail (GL_IS_WINDOW (gtk_object));
228
229         window = GL_WINDOW (gtk_object);
230         window_list = g_list_remove (window_list, window);
231
232         if (window->ui) {
233                 gl_ui_unref(window->ui);
234                 window->ui = NULL;
235         }
236
237         if (GTK_OBJECT_CLASS (gl_window_parent_class)->destroy) {
238                 GTK_OBJECT_CLASS (gl_window_parent_class)->destroy (gtk_object);
239         }
240
241         gl_debug (DEBUG_WINDOW, "END");
242 }
243
244
245 /****************************************************************************/
246 /** Create a glabels window.                                                */
247 /****************************************************************************/
248 GtkWidget *
249 gl_window_new (void)
250 {
251         glWindow *window;
252
253         gl_debug (DEBUG_WINDOW, "START");
254
255         window = g_object_new (GL_TYPE_WINDOW,
256                                "title",    _("(none) - gLabels"),
257                                NULL);
258
259         gl_debug (DEBUG_WINDOW, "window=%p", window);
260         gl_debug (DEBUG_WINDOW, "view=%p", window->view);
261
262         gl_debug (DEBUG_WINDOW, "END");
263
264         return GTK_WIDGET(window);
265 }
266
267
268 /****************************************************************************/
269 /** Create a glabels window from a label.                                   */
270 /****************************************************************************/
271 GtkWidget*
272 gl_window_new_from_label (glLabel *label)
273 {
274         glWindow *window;
275
276         gl_debug (DEBUG_WINDOW, "START");
277
278         window = GL_WINDOW (gl_window_new ());
279
280         gl_window_set_label (window, label);
281
282         gl_debug (DEBUG_WINDOW, "END");
283
284         return GTK_WIDGET(window);
285 }
286
287
288 /****************************************************************************/
289 /** Create a glabels window from a glabels file.                            */
290 /****************************************************************************/
291 GtkWidget*
292 gl_window_new_from_file (const gchar *filename)
293 {
294         glWindow         *window;
295         glLabel          *label;
296         gchar            *abs_filename;
297         glXMLLabelStatus  status;
298
299         gl_debug (DEBUG_WINDOW, "START");
300
301         window = GL_WINDOW (gl_window_new ());
302
303         abs_filename = gl_util_make_absolute (filename);
304         label = gl_xml_label_open (abs_filename, &status);
305         g_free (abs_filename);
306
307         gl_window_set_label (window, label);
308
309         gl_debug (DEBUG_WINDOW, "END");
310
311         return GTK_WIDGET(window);
312 }
313
314
315 /****************************************************************************/
316 /** Is window empty?                                                        */
317 /****************************************************************************/
318 gboolean
319 gl_window_is_empty (glWindow    *window)
320 {
321         g_return_val_if_fail (GL_IS_WINDOW (window), FALSE);
322
323         gl_debug (DEBUG_WINDOW, "return %d", (window->view == NULL) );
324         return ( window->view == NULL );
325 }
326
327
328 /****************************************************************************/
329 /** Create view from label and place in window.                             */
330 /****************************************************************************/
331 void
332 gl_window_set_label (glWindow    *window,
333                      glLabel     *label)
334 {
335         gchar *string;
336
337         gl_debug (DEBUG_WINDOW, "START");
338
339         g_return_if_fail (GL_IS_WINDOW (window));
340         g_return_if_fail (GL_IS_LABEL (label));
341
342         gl_label_clear_modified (label);
343
344         set_window_title (window, label);
345
346         if ( window->view != NULL ) {
347                 gtk_widget_destroy (window->view);
348                 window->view = NULL;
349         }
350
351         window->view = gl_view_new (label);
352         gtk_box_pack_start (GTK_BOX (window->hbox), window->view,TRUE, TRUE, 0);
353
354         gtk_widget_show_all (window->view);
355
356         gl_view_zoom_to_fit (GL_VIEW(window->view));
357
358         if (gl_prefs->grid_visible) {
359                 gl_view_show_grid (GL_VIEW(window->view));
360         } else {
361                 gl_view_hide_grid (GL_VIEW(window->view));
362         }
363
364         if (gl_prefs->markup_visible) {
365                 gl_view_show_markup (GL_VIEW(window->view));
366         } else {
367                 gl_view_hide_markup (GL_VIEW(window->view));
368         }
369
370         gl_ui_update_all (window->ui, GL_VIEW(window->view));
371
372         gl_ui_property_bar_set_view (window->property_bar, GL_VIEW(window->view));
373         gl_ui_sidebar_set_view (window->sidebar, GL_VIEW(window->view));
374
375         string = g_strdup_printf ("%3.0f%%",
376                                   100.0*gl_view_get_zoom (GL_VIEW(window->view)));
377         gtk_label_set_text (GTK_LABEL(window->zoom_info), string);
378         g_free (string);
379
380         g_signal_connect (G_OBJECT(window->view), "selection_changed",
381                           G_CALLBACK(selection_changed_cb), window);
382
383         g_signal_connect (G_OBJECT(window->view), "context_menu_activate",
384                           G_CALLBACK(context_menu_activate_cb), window);
385
386         g_signal_connect (G_OBJECT(window->view), "zoom_changed",
387                           G_CALLBACK(zoom_changed_cb), window);
388
389         g_signal_connect (G_OBJECT(window->view), "pointer_moved",
390                           G_CALLBACK(pointer_moved_cb), window);
391
392         g_signal_connect (G_OBJECT(window->view), "pointer_exit",
393                           G_CALLBACK(pointer_exit_cb), window);
394
395         g_signal_connect (G_OBJECT(label), "name_changed",
396                           G_CALLBACK(name_changed_cb), window);
397
398         g_signal_connect (G_OBJECT(label), "modified_changed",
399                           G_CALLBACK(modified_changed_cb), window);
400
401         gl_debug (DEBUG_WINDOW, "END");
402 }
403
404
405 /****************************************************************************/
406 /** Return list of glabels windows.                                         */
407 /****************************************************************************/
408 const GList *
409 gl_window_get_window_list (void)
410 {
411         gl_debug (DEBUG_WINDOW, "");
412         return window_list;
413 }
414
415
416 /*---------------------------------------------------------------------------*/
417 /** PRIVATE.  Set window title based on name and state of label.             */
418 /*---------------------------------------------------------------------------*/
419 static void 
420 set_window_title (glWindow *window,
421                   glLabel  *label)
422 {
423         gchar *name, *title;
424
425         gl_debug (DEBUG_WINDOW, "START");
426
427         g_return_if_fail (window && GL_IS_WINDOW (window));
428         g_return_if_fail (label && GL_IS_LABEL (label));
429
430         name = gl_label_get_short_name (label);
431         g_return_if_fail (name != NULL);
432
433         if (gl_label_is_modified (label)) {
434                 title = g_strdup_printf ("%s %s - gLabels",
435                                          name, _("(modified)"));
436         } else {
437                 title = g_strdup_printf ("%s - gLabels", name);
438         }
439
440         gtk_window_set_title (GTK_WINDOW(window), title);
441
442         g_free (name);
443         g_free (title);
444
445         gl_debug (DEBUG_WINDOW, "END");
446 }
447
448
449 /*-------------------------------------------------------------------------*/
450 /** PRIVATE.  Window "delete-event" callback.                              */
451 /*-------------------------------------------------------------------------*/
452 static gboolean
453 window_delete_event_cb (glWindow      *window,
454                         GdkEvent      *event,
455                         gpointer       user_data)
456 {
457         gl_debug (DEBUG_WINDOW, "START");
458
459         g_return_val_if_fail (window && GL_IS_WINDOW (window), TRUE);
460
461         gl_file_close (window);
462
463         gl_debug (DEBUG_WINDOW, "END");
464
465         return TRUE;
466 }
467
468
469 /*---------------------------------------------------------------------------*/
470 /** PRIVATE.  View "selection state changed" callback.                       */
471 /*---------------------------------------------------------------------------*/
472 static void 
473 selection_changed_cb (glView   *view,
474                       glWindow *window)
475 {
476         gl_debug (DEBUG_WINDOW, "START");
477
478         g_return_if_fail (view && GL_IS_VIEW (view));
479         g_return_if_fail (window && GL_IS_WINDOW (window));
480
481         gl_ui_update_selection_verbs (window->ui, view);
482
483         gl_debug (DEBUG_WINDOW, "END");
484 }
485
486
487 /*---------------------------------------------------------------------------*/
488 /** PRIVATE.  View "context menu activate" callback.                         */
489 /*---------------------------------------------------------------------------*/
490 static void
491 context_menu_activate_cb (glView       *view,
492                           gint          button,
493                           guint32       activate_time,
494                           glWindow     *window)
495 {
496         gl_debug (DEBUG_WINDOW, "START");
497
498         g_return_if_fail (view && GL_IS_VIEW (view));
499         g_return_if_fail (window && GL_IS_WINDOW (window));
500
501         if (gl_view_is_selection_empty (view)) {
502
503                 gtk_menu_popup (GTK_MENU (window->empty_selection_context_menu),
504                                 NULL, NULL, NULL, NULL, button, activate_time);
505
506         } else {
507
508                 gtk_menu_popup (GTK_MENU (window->context_menu),
509                                 NULL, NULL, NULL, NULL, button, activate_time);
510
511         }
512
513         gl_debug (DEBUG_WINDOW, "END");
514 }
515
516
517 /*---------------------------------------------------------------------------*/
518 /** PRIVATE.  View "zoom state changed" callback.                            */
519 /*---------------------------------------------------------------------------*/
520 static void 
521 zoom_changed_cb (glView   *view,
522                  gdouble   zoom,
523                  glWindow *window)
524 {
525         gchar *string;
526
527         gl_debug (DEBUG_WINDOW, "START");
528
529         g_return_if_fail (view && GL_IS_VIEW (view));
530         g_return_if_fail (window && GL_IS_WINDOW (window));
531
532         string = g_strdup_printf ("%3.0f%%", 100.0*zoom);
533         gtk_label_set_text (GTK_LABEL(window->zoom_info), string);
534         g_free (string);
535
536         gl_ui_update_zoom_verbs (window->ui, view);
537
538         gl_debug (DEBUG_WINDOW, "END");
539 }
540
541
542 /*---------------------------------------------------------------------------*/
543 /** PRIVATE.  View "pointer moved" callback.                                 */
544 /*---------------------------------------------------------------------------*/
545 static void
546 pointer_moved_cb (glView   *view,
547                   gdouble   x,
548                   gdouble   y,
549                   glWindow *window)
550 {
551         gchar *string;
552         gdouble units_per_point;
553         gint    units_precision;
554
555         gl_debug (DEBUG_WINDOW, "START");
556
557         g_return_if_fail (view && GL_IS_VIEW (view));
558         g_return_if_fail (window && GL_IS_WINDOW (window));
559
560         units_per_point = gl_prefs_get_units_per_point ();
561         units_precision = gl_prefs_get_units_precision ();
562
563         string = g_strdup_printf ("%.*f, %.*f",
564                                   units_precision, x*units_per_point,
565                                   units_precision, y*units_per_point);
566         gtk_label_set_text (GTK_LABEL(window->cursor_info), string);
567         g_free (string);
568
569         gl_debug (DEBUG_WINDOW, "END");
570 }
571
572
573 /*---------------------------------------------------------------------------*/
574 /** PRIVATE.  View "pointer exit" callback.                                  */
575 /*---------------------------------------------------------------------------*/
576 static void
577 pointer_exit_cb (glView   *view,
578                  glWindow *window)
579 {
580         gl_debug (DEBUG_WINDOW, "START");
581
582         g_return_if_fail (view && GL_IS_VIEW (view));
583         g_return_if_fail (window && GL_IS_WINDOW (window));
584
585         gtk_label_set_text (GTK_LABEL(window->cursor_info), "");
586
587         gl_debug (DEBUG_WINDOW, "END");
588 }
589
590
591 /*---------------------------------------------------------------------------*/
592 /** PRIVATE.  Label "name changed" callback.                                 */
593 /*---------------------------------------------------------------------------*/
594 static void 
595 name_changed_cb (glLabel  *label,
596                  glWindow *window)
597 {
598         gl_debug (DEBUG_WINDOW, "START");
599
600         g_return_if_fail (label && GL_IS_LABEL (label));
601         g_return_if_fail (window && GL_IS_WINDOW (window));
602
603         set_window_title (window, label);
604
605         gl_debug (DEBUG_WINDOW, "END");
606 }
607
608
609 /*---------------------------------------------------------------------------*/
610 /** PRIVATE.  Label "modified state changed" callback.                       */
611 /*---------------------------------------------------------------------------*/
612 static void 
613 modified_changed_cb (glLabel  *label,
614                      glWindow *window)
615 {
616         gl_debug (DEBUG_WINDOW, "START");
617
618         g_return_if_fail (label && GL_IS_LABEL (label));
619         g_return_if_fail (window && GL_IS_WINDOW (window));
620
621         set_window_title (window, label);
622
623         gl_ui_update_modified_verbs (window->ui, label);
624
625         gl_debug (DEBUG_WINDOW, "END");
626 }
627
628
629
630 /*
631  * Local Variables:       -- emacs
632  * mode: C                -- emacs
633  * c-basic-offset: 8      -- emacs
634  * tab-width: 8           -- emacs
635  * indent-tabs-mode: nil  -- emacs
636  * End:                   -- emacs
637  */