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