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