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