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