]> git.sur5r.net Git - glabels/blob - glabels2/src/view.c
Adjust canvas scroll region if when label size is changed.
[glabels] / glabels2 / src / view.c
1 /*
2  *  (GLABELS) Label and Business Card Creation program for GNOME
3  *
4  *  view.c:  GLabels View module
5  *
6  *  Copyright (C) 2001-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 <gtk/gtk.h>
26 #include <gtk/gtkinvisible.h>
27
28 #include <string.h>
29 #include <math.h>
30
31 #include "view.h"
32 #include "view-object.h"
33 #include "view-box.h"
34 #include "view-ellipse.h"
35 #include "view-line.h"
36 #include "view-image.h"
37 #include "view-text.h"
38 #include "view-barcode.h"
39 #include "xml-label.h"
40 #include "color.h"
41 #include "stock.h"
42 #include "merge-properties-dialog.h"
43 #include "prefs.h"
44 #include "marshal.h"
45
46 #include "debug.h"
47
48 /*==========================================================================*/
49 /* Private macros and constants.                                            */
50 /*==========================================================================*/
51
52 #define BG_COLOR        GL_COLOR (192, 192, 192)
53 #define OUTLINE_COLOR   GL_COLOR (173, 216, 230)
54 #define PAPER_COLOR     GL_COLOR (255, 255, 255)
55 #define GRID_COLOR      BG_COLOR
56 #define MARKUP_COLOR    GL_COLOR (240, 100, 100)
57
58 #define SEL_LINE_COLOR  GL_COLOR_A (0, 0, 255, 128)
59 #define SEL_FILL_COLOR  GL_COLOR_A (192, 192, 255, 128)
60
61 #define ARC_FINE         2 /* Resolution in degrees of large arcs */
62 #define ARC_COURSE       5 /* Resolution in degrees of small arcs */
63
64 #define ZOOMTOFIT_PAD   16
65
66 #define POINTS_PER_MM    2.83464566929
67
68 #define DELTA 0.01
69
70 /*==========================================================================*/
71 /* Private types.                                                           */
72 /*==========================================================================*/
73
74 enum {
75         SELECTION_CHANGED,
76         ZOOM_CHANGED,
77         POINTER_MOVED,
78         POINTER_EXIT,
79         MODE_CHANGED,
80         LAST_SIGNAL
81 };
82
83
84 /*==========================================================================*/
85 /* Private globals                                                          */
86 /*==========================================================================*/
87
88 static GtkContainerClass *parent_class;
89
90 static guint signals[LAST_SIGNAL] = {0};
91
92 /* "CLIPBOARD" selection */
93 static GdkAtom clipboard_atom = GDK_NONE;
94
95 static gdouble zooms[] = {
96         8.00,
97         6.00,
98         4.00,
99         3.00,
100         2.00,
101         1.50,
102         1.00,
103         0.75,
104         0.67,
105         0.50,
106         0.33,
107         0.25,
108         0.20,
109         0.15,
110         0.10,
111 };
112 #define N_ZOOMS G_N_ELEMENTS(zooms)
113
114
115 /*==========================================================================*/
116 /* Local function prototypes                                                */
117 /*==========================================================================*/
118
119 static void       gl_view_class_init              (glViewClass *class);
120 static void       gl_view_init                    (glView *view);
121 static void       gl_view_finalize                (GObject *object);
122
123 static void       gl_view_construct               (glView *view);
124 static GtkWidget *gl_view_construct_canvas        (glView *view);
125 static void       gl_view_construct_selection     (glView *view);
126
127 static gdouble    get_home_scale                  (glView *view);
128
129 static void       draw_layers                     (glView *view);
130
131 static void       label_resized_cb                (glLabel *label,
132                                                    glView *view);
133
134 static void       draw_label_layer                (glView *view);
135
136 static void       draw_highlight_layer            (glView *view);
137
138 static void       draw_bg_fg_layers               (glView *view);
139 static void       draw_bg_fg_rect                 (glView *view);
140 static void       draw_bg_fg_rounded_rect         (glView *view);
141 static void       draw_bg_fg_round                (glView *view);
142 static void       draw_bg_fg_cd                   (glView *view);
143 static void       draw_bg_fg_cd_bc                (glView *view);
144
145 static void       draw_grid_layer                 (glView *view);
146
147 static void       draw_markup_layer               (glView *view);
148
149 static void       draw_markup_margin              (glView *view,
150                                                    glTemplateMarkupMargin *margin);
151 static void       draw_markup_margin_rect         (glView *view,
152                                                    glTemplateMarkupMargin *margin);
153 static void       draw_markup_margin_rounded_rect (glView *view,
154                                                    glTemplateMarkupMargin *margin);
155 static void       draw_markup_margin_round        (glView *view,
156                                                    glTemplateMarkupMargin *margin);
157 static void       draw_markup_margin_cd           (glView *view,
158                                                    glTemplateMarkupMargin *margin);
159 static void       draw_markup_margin_cd_bc        (glView *view,
160                                                    glTemplateMarkupMargin *margin);
161
162 static void       draw_markup_line                (glView *view,
163                                                    glTemplateMarkupLine   *line);
164
165 static void       draw_markup_circle              (glView *view,
166                                                    glTemplateMarkupCircle *circle);
167
168
169 static void       select_object_real              (glView *view,
170                                                    glViewObject *view_object);
171 static void       unselect_object_real            (glView *view,
172                                                    glViewObject *view_object);
173
174 static gboolean   object_at                       (glView *view,
175                                                    gdouble x, gdouble y);
176
177 static gboolean   is_item_member_of_group         (glView          *view,
178                                                    GnomeCanvasItem *item,
179                                                    GnomeCanvasItem *group);
180
181 static void       set_zoom_real                   (glView          *view,
182                                                    gdouble          zoom,
183                                                    gboolean         scale_to_fit_flag);
184
185 static void       size_allocate_cb                (glView          *view);
186
187 static void       screen_changed_cb               (glView          *view);
188
189 static int        canvas_event                    (GnomeCanvas *canvas,
190                                                    GdkEvent    *event,
191                                                    glView      *view);
192 static int        canvas_event_arrow_mode         (GnomeCanvas *canvas,
193                                                    GdkEvent    *event,
194                                                    glView      *view);
195
196 static void       construct_selection_menu       (glView *view);
197
198 static void       construct_empty_selection_menu (glView *view);
199
200 static void       selection_clear_cb             (GtkWidget         *widget,
201                                                   GdkEventSelection *event,
202                                                   gpointer          data);
203
204 static void       selection_get_cb               (GtkWidget         *widget,
205                                                   GtkSelectionData  *selection_data,
206                                                   guint             info,
207                                                   guint             time,
208                                                   gpointer          data);
209
210 static void       selection_received_cb          (GtkWidget         *widget,
211                                                   GtkSelectionData  *selection_data,
212                                                   guint             time,
213                                                   gpointer          data);
214 \f
215 /****************************************************************************/
216 /* Boilerplate Object stuff.                                                */
217 /****************************************************************************/
218 guint
219 gl_view_get_type (void)
220 {
221         static guint view_type = 0;
222
223         if (!view_type) {
224                 GTypeInfo view_info = {
225                         sizeof (glViewClass),
226                         NULL,
227                         NULL,
228                         (GClassInitFunc) gl_view_class_init,
229                         NULL,
230                         NULL,
231                         sizeof (glView),
232                         0,
233                         (GInstanceInitFunc) gl_view_init,
234                 };
235
236                 view_type =
237                     g_type_register_static (gtk_vbox_get_type (),
238                                             "glView", &view_info, 0);
239         }
240
241         return view_type;
242 }
243
244 static void
245 gl_view_class_init (glViewClass *class)
246 {
247         GObjectClass *object_class = (GObjectClass *) class;
248
249         gl_debug (DEBUG_VIEW, "START");
250
251         parent_class = g_type_class_peek_parent (class);
252
253         object_class->finalize = gl_view_finalize;
254
255         signals[SELECTION_CHANGED] =
256                 g_signal_new ("selection_changed",
257                               G_OBJECT_CLASS_TYPE (object_class),
258                               G_SIGNAL_RUN_LAST,
259                               G_STRUCT_OFFSET (glViewClass, selection_changed),
260                               NULL, NULL,
261                               gl_marshal_VOID__VOID,
262                               G_TYPE_NONE,
263                               0);
264
265         signals[ZOOM_CHANGED] =
266                 g_signal_new ("zoom_changed",
267                               G_OBJECT_CLASS_TYPE (object_class),
268                               G_SIGNAL_RUN_LAST,
269                               G_STRUCT_OFFSET (glViewClass, zoom_changed),
270                               NULL, NULL,
271                               gl_marshal_VOID__DOUBLE,
272                               G_TYPE_NONE,
273                               1, G_TYPE_DOUBLE);
274
275         signals[POINTER_MOVED] =
276                 g_signal_new ("pointer_moved",
277                               G_OBJECT_CLASS_TYPE (object_class),
278                               G_SIGNAL_RUN_LAST,
279                               G_STRUCT_OFFSET (glViewClass, pointer_moved),
280                               NULL, NULL,
281                               gl_marshal_VOID__DOUBLE_DOUBLE,
282                               G_TYPE_NONE,
283                               2, G_TYPE_DOUBLE, G_TYPE_DOUBLE);
284
285         signals[POINTER_EXIT] =
286                 g_signal_new ("pointer_exit",
287                               G_OBJECT_CLASS_TYPE (object_class),
288                               G_SIGNAL_RUN_LAST,
289                               G_STRUCT_OFFSET (glViewClass, pointer_exit),
290                               NULL, NULL,
291                               gl_marshal_VOID__VOID,
292                               G_TYPE_NONE,
293                               0);
294
295         signals[MODE_CHANGED] =
296                 g_signal_new ("mode_changed",
297                               G_OBJECT_CLASS_TYPE (object_class),
298                               G_SIGNAL_RUN_LAST,
299                               G_STRUCT_OFFSET (glViewClass, mode_changed),
300                               NULL, NULL,
301                               gl_marshal_VOID__VOID,
302                               G_TYPE_NONE,
303                               0);
304
305         gl_debug (DEBUG_VIEW, "END");
306 }
307
308 static void
309 gl_view_init (glView *view)
310 {
311         gl_debug (DEBUG_VIEW, "START");
312
313         view->label = NULL;
314
315         view->grid_spacing = 9;
316
317         view->default_font_family = NULL;
318
319         gl_debug (DEBUG_VIEW, "END");
320 }
321
322 static void
323 gl_view_finalize (GObject *object)
324 {
325         glView *view;
326
327         gl_debug (DEBUG_VIEW, "START");
328
329         g_return_if_fail (object != NULL);
330         g_return_if_fail (GL_IS_VIEW (object));
331
332         view = GL_VIEW (object);
333
334         G_OBJECT_CLASS (parent_class)->finalize (object);
335
336         gl_debug (DEBUG_VIEW, "END");
337 }
338
339 /****************************************************************************/
340 /* NEW view object.                                                         */
341 /****************************************************************************/
342 GtkWidget *
343 gl_view_new (glLabel *label)
344 {
345         glView *view;
346
347         gl_debug (DEBUG_VIEW, "START");
348
349         g_return_val_if_fail (label && GL_IS_LABEL (label), NULL);
350
351         view = g_object_new (gl_view_get_type (), NULL);
352         view->label = label;
353
354         gl_view_construct (view);
355
356         gl_debug (DEBUG_VIEW, "END");
357
358         return GTK_WIDGET (view);
359 }
360
361 /*---------------------------------------------------------------------------*/
362 /* PRIVATE.  Construct composite widget.                                     */
363 /*---------------------------------------------------------------------------*/
364 static void
365 gl_view_construct (glView *view)
366 {
367         GtkWidget *wvbox, *wscroll;
368
369         gl_debug (DEBUG_VIEW, "START");
370
371         g_return_if_fail (GL_IS_VIEW (view));
372
373         wvbox = GTK_WIDGET (view);
374
375         view->state = GL_VIEW_STATE_ARROW;
376         view->object_list = NULL;
377
378         gl_view_construct_canvas (view);
379         wscroll = gtk_scrolled_window_new (NULL, NULL);
380         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (wscroll),
381                                         GTK_POLICY_AUTOMATIC,
382                                         GTK_POLICY_AUTOMATIC);
383         gtk_box_pack_start (GTK_BOX (wvbox), wscroll, TRUE, TRUE, 0);
384         gtk_container_add (GTK_CONTAINER (wscroll), view->canvas);
385
386         gl_view_construct_selection (view);
387
388         construct_selection_menu (view);
389         construct_empty_selection_menu (view);
390
391         gl_view_set_default_font_family      (view, gl_prefs->default_font_family);
392         gl_view_set_default_font_size        (view, gl_prefs->default_font_size);
393         gl_view_set_default_font_weight      (view, gl_prefs->default_font_weight);
394         gl_view_set_default_font_italic_flag (view, gl_prefs->default_font_italic_flag);
395         gl_view_set_default_text_color       (view, gl_prefs->default_text_color);
396         gl_view_set_default_text_alignment   (view, gl_prefs->default_text_alignment);
397         gl_view_set_default_line_width       (view, gl_prefs->default_line_width);
398         gl_view_set_default_line_color       (view, gl_prefs->default_line_color);
399         gl_view_set_default_fill_color       (view, gl_prefs->default_fill_color);
400
401         gl_debug (DEBUG_VIEW, "END");
402 }
403
404 /*---------------------------------------------------------------------------*/
405 /* PRIVATE.  Create canvas w/ a background in the shape of the label/card.   */
406 /*---------------------------------------------------------------------------*/
407 static GtkWidget *
408 gl_view_construct_canvas (glView *view)
409 {
410         glLabel   *label;
411         gdouble    label_width, label_height;
412         GdkColor  *bg_color;
413
414         gl_debug (DEBUG_VIEW, "START");
415
416         g_return_val_if_fail (view && GL_IS_VIEW (view), NULL);
417         g_return_val_if_fail (view->label && GL_IS_LABEL (view->label), NULL);
418
419         label = view->label;
420
421         gtk_widget_push_colormap (gdk_rgb_get_colormap ());
422         view->canvas = gnome_canvas_new_aa ();
423         gtk_widget_pop_colormap ();
424
425         bg_color = gl_color_to_gdk_color (BG_COLOR);
426         gtk_widget_modify_bg (GTK_WIDGET(view->canvas), GTK_STATE_NORMAL, bg_color);
427         g_free (bg_color);
428
429         gl_label_get_size (label, &label_width, &label_height);
430         gl_debug (DEBUG_VIEW, "Label size: w=%lf, h=%lf",
431                   label_width, label_height);
432
433         view->zoom = 1.0;
434         view->home_scale = get_home_scale (view);
435         gnome_canvas_set_pixels_per_unit (GNOME_CANVAS (view->canvas), view->home_scale);
436
437         gnome_canvas_set_scroll_region (GNOME_CANVAS (view->canvas),
438                                         0.0, 0.0, label_width, label_height);
439
440         draw_layers (view);
441
442         g_signal_connect (G_OBJECT (view->canvas), "event",
443                           G_CALLBACK (canvas_event), view);
444
445         g_signal_connect_swapped (G_OBJECT (view->canvas), "size-allocate",
446                                   G_CALLBACK (size_allocate_cb), view);
447
448         g_signal_connect_swapped (G_OBJECT (view->canvas), "screen-changed",
449                                   G_CALLBACK (screen_changed_cb), view);
450
451         gl_debug (DEBUG_VIEW, "END");
452
453         return view->canvas;
454 }
455
456 /*---------------------------------------------------------------------------*/
457 /* PRIAVTE.  Calculate 1:1 scale for screen.                                 */
458 /*---------------------------------------------------------------------------*/
459 static gdouble
460 get_home_scale (glView *view)
461 {
462         GdkScreen *screen;
463         gdouble    screen_width_pixels, screen_width_mm;
464         gdouble    screen_height_pixels, screen_height_mm;
465         gdouble    x_pixels_per_mm, y_pixels_per_mm;
466         gdouble    scale;
467
468         if (!gtk_widget_has_screen) return 1.0;
469
470         screen = gtk_widget_get_screen (GTK_WIDGET (view->canvas));
471
472         gl_debug (DEBUG_VIEW, "Screen = %p", screen);
473
474         screen_width_pixels  = gdk_screen_get_width (screen);
475         screen_width_mm      = gdk_screen_get_width_mm (screen);
476         screen_height_pixels = gdk_screen_get_height (screen);
477         screen_height_mm     = gdk_screen_get_height_mm (screen);
478
479         x_pixels_per_mm      = screen_width_pixels / screen_width_mm;
480         y_pixels_per_mm      = screen_height_pixels / screen_height_mm;
481
482         gl_debug (DEBUG_VIEW, "Horizontal dot pitch: %g pixels/mm (%g dpi)",
483                   x_pixels_per_mm, x_pixels_per_mm * 25.4);
484         gl_debug (DEBUG_VIEW, "Vertical dot pitch: %g pixels/mm (%g dpi)",
485                   y_pixels_per_mm, y_pixels_per_mm * 25.4);
486
487         scale = (x_pixels_per_mm + y_pixels_per_mm) / 2.0;
488
489         gl_debug (DEBUG_VIEW, "Average dot pitch: %g pixels/mm (%g dpi)",
490                   scale, scale * 25.4);
491
492         scale /= POINTS_PER_MM;
493
494         gl_debug (DEBUG_VIEW, "Scale = %g pixels/point", scale);
495
496         /* Make sure scale is somewhat sane. */
497         if ( (scale < 0.25) || (scale > 4.0) ) return 1.0;
498
499         return scale;
500 }
501
502 /*---------------------------------------------------------------------------*/
503 /* PRIVATE.  Create clipboard selection targets.                             */
504 /*---------------------------------------------------------------------------*/
505 static void
506 gl_view_construct_selection (glView *view)
507 {
508         gl_debug (DEBUG_VIEW, "START");
509
510         g_return_if_fail (GL_IS_VIEW (view));
511
512         view->have_selection = FALSE;
513         view->selection_data = NULL;
514         view->invisible = gtk_invisible_new ();
515
516         view->selected_object_list = NULL;
517
518         if (!clipboard_atom) {
519                 clipboard_atom = gdk_atom_intern ("GLABELS_CLIPBOARD", FALSE);
520         }
521
522         gtk_selection_add_target (view->invisible,
523                                   clipboard_atom, GDK_SELECTION_TYPE_STRING, 1);
524
525         g_signal_connect (G_OBJECT (view->invisible),
526                           "selection_clear_event",
527                           G_CALLBACK (selection_clear_cb), view);
528
529         g_signal_connect (G_OBJECT (view->invisible), "selection_get",
530                           G_CALLBACK (selection_get_cb), view);
531
532         g_signal_connect (G_OBJECT (view->invisible),
533                           "selection_received",
534                           G_CALLBACK (selection_received_cb), view);
535
536         gl_debug (DEBUG_VIEW, "END");
537 }
538
539 /*---------------------------------------------------------------------------*/
540 /* PRIVATE.  Create, draw and order layers.                                  */
541 /*---------------------------------------------------------------------------*/
542 static void
543 draw_layers (glView *view)
544 {
545         g_return_if_fail (view && GL_IS_VIEW (view));
546         g_return_if_fail (view->label && GL_IS_LABEL (view->label));
547
548         draw_bg_fg_layers (view);
549         draw_grid_layer (view);
550         draw_markup_layer (view);
551         draw_highlight_layer (view); /* Must be done before label layer */
552         draw_label_layer (view);
553
554         gnome_canvas_item_raise_to_top (GNOME_CANVAS_ITEM(view->fg_group));
555         gnome_canvas_item_raise_to_top (GNOME_CANVAS_ITEM(view->highlight_group));
556
557         g_signal_connect (G_OBJECT (view->label), "size_changed",
558                           G_CALLBACK (label_resized_cb), view);
559 }
560
561 /*---------------------------------------------------------------------------*/
562 /* PRIVATE.  Handle label resize event.   .                                  */
563 /*---------------------------------------------------------------------------*/
564 static void
565 label_resized_cb (glLabel *label,
566                   glView *view)
567 {
568         gdouble label_width, label_height;
569
570         g_return_if_fail (label && GL_IS_LABEL (label));
571         g_return_if_fail (view && GL_IS_VIEW (view));
572
573         gl_label_get_size (label, &label_width, &label_height);
574         gnome_canvas_set_scroll_region (GNOME_CANVAS (view->canvas),
575                                         0.0, 0.0, label_width, label_height);
576
577         gtk_object_destroy (GTK_OBJECT (view->bg_group));
578         gtk_object_destroy (GTK_OBJECT (view->grid_group));
579         gtk_object_destroy (GTK_OBJECT (view->markup_group));
580         gtk_object_destroy (GTK_OBJECT (view->fg_group));
581
582         draw_bg_fg_layers (view);
583         draw_grid_layer (view);
584         draw_markup_layer (view);
585
586         gnome_canvas_item_raise_to_top (GNOME_CANVAS_ITEM(view->label_group));
587         gnome_canvas_item_raise_to_top (GNOME_CANVAS_ITEM(view->fg_group));
588         gnome_canvas_item_raise_to_top (GNOME_CANVAS_ITEM(view->highlight_group));
589 }
590
591 /*---------------------------------------------------------------------------*/
592 /* PRIVATE.  Draw label layer.                                               */
593 /*---------------------------------------------------------------------------*/
594 static void
595 draw_label_layer (glView *view)
596 {
597         GnomeCanvasGroup *group;
598         glLabel          *label;
599         GList            *p_obj;
600         glLabelObject    *object;
601         glViewObject     *view_object;
602
603         g_return_if_fail (view && GL_IS_VIEW (view));
604         g_return_if_fail (view->label && GL_IS_LABEL (view->label));
605
606         group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
607         view->label_group = GNOME_CANVAS_GROUP(
608                 gnome_canvas_item_new (group,
609                                        gnome_canvas_group_get_type (),
610                                        "x", 0.0,
611                                        "y", 0.0,
612                                        NULL));
613
614         label = view->label;
615
616         for (p_obj = label->objects; p_obj != NULL; p_obj = p_obj->next) {
617                 object = (glLabelObject *) p_obj->data;
618
619                 if (GL_IS_LABEL_BOX (object)) {
620                         view_object = gl_view_box_new (GL_LABEL_BOX(object),
621                                                        view);
622                 } else if (GL_IS_LABEL_ELLIPSE (object)) {
623                         view_object = gl_view_ellipse_new (GL_LABEL_ELLIPSE(object),
624                                                            view);
625                 } else if (GL_IS_LABEL_LINE (object)) {
626                         view_object = gl_view_line_new (GL_LABEL_LINE(object),
627                                                         view);
628                 } else if (GL_IS_LABEL_IMAGE (object)) {
629                         view_object = gl_view_image_new (GL_LABEL_IMAGE(object),
630                                                          view);
631                 } else if (GL_IS_LABEL_TEXT (object)) {
632                         view_object = gl_view_text_new (GL_LABEL_TEXT(object),
633                                                         view);
634                 } else if (GL_IS_LABEL_BARCODE (object)) {
635                         view_object = gl_view_barcode_new (GL_LABEL_BARCODE(object),
636                                                            view);
637                 } else {
638                         /* Should not happen! */
639                         view_object = NULL;
640                         g_warning ("Invalid label object type.");
641                 }
642         }
643 }
644
645 /*---------------------------------------------------------------------------*/
646 /* PRIVATE.  Create highlight layer.                                         */
647 /*---------------------------------------------------------------------------*/
648 static void
649 draw_highlight_layer (glView *view)
650 {
651         GnomeCanvasGroup *group;
652
653         g_return_if_fail (view && GL_IS_VIEW (view));
654
655         group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
656         view->highlight_group = GNOME_CANVAS_GROUP(
657                 gnome_canvas_item_new (group,
658                                        gnome_canvas_group_get_type (),
659                                        "x", 0.0,
660                                        "y", 0.0,
661                                        NULL));
662 }
663
664 /*---------------------------------------------------------------------------*/
665 /* PRIVATE.  Draw background and foreground outlines.                        */
666 /*---------------------------------------------------------------------------*/
667 static void
668 draw_bg_fg_layers (glView *view)
669 {
670         glLabel          *label;
671         glTemplate       *template;
672         GnomeCanvasGroup *group;
673
674         g_return_if_fail (view && GL_IS_VIEW (view));
675         g_return_if_fail (view->label && GL_IS_LABEL (view->label));
676
677         group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
678         view->bg_group = GNOME_CANVAS_GROUP(
679                 gnome_canvas_item_new (group,
680                                        gnome_canvas_group_get_type (),
681                                        "x", 0.0,
682                                        "y", 0.0,
683                                        NULL));
684         view->fg_group = GNOME_CANVAS_GROUP(
685                 gnome_canvas_item_new (group,
686                                        gnome_canvas_group_get_type (),
687                                        "x", 0.0,
688                                        "y", 0.0,
689                                        NULL));
690
691         label    = view->label;
692         template = gl_label_get_template (label);
693
694         switch (template->label.style) {
695
696         case GL_TEMPLATE_STYLE_RECT:
697                 if (template->label.rect.r == 0.0) {
698                         /* Square corners. */
699                         draw_bg_fg_rect (view);
700                 } else {
701                         /* Rounded corners. */
702                         draw_bg_fg_rounded_rect (view);
703                 }
704                 break;
705
706         case GL_TEMPLATE_STYLE_ROUND:
707                 draw_bg_fg_round (view);
708                 break;
709
710         case GL_TEMPLATE_STYLE_CD:
711                 if ((template->label.cd.w == 0.0) && (template->label.cd.h == 0.0) ) {
712                         draw_bg_fg_cd (view);
713                 } else {
714                         draw_bg_fg_cd_bc (view);
715                 }
716                 break;
717
718         default:
719                 g_warning ("Unknown template label style");
720                 break;
721         }
722 }
723
724 /*---------------------------------------------------------------------------*/
725 /* PRIVATE.  Draw simple recangular background.                              */
726 /*---------------------------------------------------------------------------*/
727 static void
728 draw_bg_fg_rect (glView *view)
729 {
730         glLabel          *label;
731         glTemplate       *template;
732         gdouble           w, h;
733         GnomeCanvasItem  *item;
734
735         gl_debug (DEBUG_VIEW, "START");
736
737         g_return_if_fail (view && GL_IS_VIEW (view));
738         g_return_if_fail (view->label && GL_IS_LABEL (view->label));
739
740         label = view->label;
741
742         gl_label_get_size (label, &w, &h);
743         template = gl_label_get_template (label);
744
745         /* Background */
746         item = gnome_canvas_item_new (view->bg_group,
747                                       gnome_canvas_rect_get_type (),
748                                       "x1", 0.0,
749                                       "y1", 0.0,
750                                       "x2", w,
751                                       "y2", h,
752                                       "fill_color_rgba", PAPER_COLOR,
753                                       NULL);
754
755         /* Foreground */
756         item = gnome_canvas_item_new (view->fg_group,
757                                       gnome_canvas_rect_get_type (),
758                                       "x1", 0.0,
759                                       "y1", 0.0,
760                                       "x2", w,
761                                       "y2", h,
762                                       "width_pixels", 2,
763                                       "outline_color_rgba", OUTLINE_COLOR,
764                                       NULL);
765
766         gl_debug (DEBUG_VIEW, "END");
767 }
768
769 /*---------------------------------------------------------------------------*/
770 /* PRIVATE.  Draw rounded recangular background.                             */
771 /*---------------------------------------------------------------------------*/
772 static void
773 draw_bg_fg_rounded_rect (glView *view)
774 {
775         glLabel           *label;
776         GnomeCanvasPoints *points;
777         gint               i_coords, i_theta;
778         glTemplate        *template;
779         gdouble            r, w, h;
780         GnomeCanvasItem   *item;
781
782         gl_debug (DEBUG_VIEW, "START");
783
784         g_return_if_fail (view && GL_IS_VIEW (view));
785         g_return_if_fail (view->label && GL_IS_LABEL (view->label));
786
787         label = view->label;
788
789         gl_label_get_size (label, &w, &h);
790         template = gl_label_get_template (label);
791         r = template->label.rect.r;
792
793         points = gnome_canvas_points_new (4 * (1 + 90 / ARC_COURSE));
794         i_coords = 0;
795         for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
796                 points->coords[i_coords++] =
797                     r - r * sin (i_theta * G_PI / 180.0);
798                 points->coords[i_coords++] =
799                     r - r * cos (i_theta * G_PI / 180.0);
800         }
801         for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
802                 points->coords[i_coords++] =
803                     r - r * cos (i_theta * G_PI / 180.0);
804                 points->coords[i_coords++] =
805                     (h - r) + r * sin (i_theta * G_PI / 180.0);
806         }
807         for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
808                 points->coords[i_coords++] =
809                     (w - r) + r * sin (i_theta * G_PI / 180.0);
810                 points->coords[i_coords++] =
811                     (h - r) + r * cos (i_theta * G_PI / 180.0);
812         }
813         for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
814                 points->coords[i_coords++] =
815                     (w - r) + r * cos (i_theta * G_PI / 180.0);
816                 points->coords[i_coords++] =
817                     r - r * sin (i_theta * G_PI / 180.0);
818         }
819
820         /* Background */
821         item = gnome_canvas_item_new (view->bg_group,
822                                       gnome_canvas_polygon_get_type (),
823                                       "points", points,
824                                       "fill_color_rgba", PAPER_COLOR,
825                                       NULL);
826
827         /* Foreground */
828         item = gnome_canvas_item_new (view->fg_group,
829                                       gnome_canvas_polygon_get_type (),
830                                       "points", points,
831                                       "width_pixels", 2,
832                                       "outline_color_rgba", OUTLINE_COLOR,
833                                       NULL);
834
835         gnome_canvas_points_free (points);
836
837         gl_debug (DEBUG_VIEW, "END");
838 }
839
840 /*---------------------------------------------------------------------------*/
841 /* PRIVATE.  Draw round background.                                          */
842 /*---------------------------------------------------------------------------*/
843 static void
844 draw_bg_fg_round (glView *view)
845 {
846         glLabel          *label;
847         glTemplate       *template;
848         gdouble           r;
849         GnomeCanvasItem  *item;
850
851         gl_debug (DEBUG_VIEW, "START");
852
853         g_return_if_fail (view && GL_IS_VIEW (view));
854         g_return_if_fail (view->label && GL_IS_LABEL(view->label));
855
856         label    = view->label;
857         template = gl_label_get_template (label);
858
859         r = template->label.round.r;
860
861         /* Background */
862         item = gnome_canvas_item_new (view->bg_group,
863                                       gnome_canvas_ellipse_get_type (),
864                                       "x1", 0.0,
865                                       "y1", 0.0,
866                                       "x2", 2.0*r,
867                                       "y2", 2.0*r,
868                                       "fill_color_rgba", PAPER_COLOR,
869                                       NULL);
870
871         /* Foreground */
872         item = gnome_canvas_item_new (view->fg_group,
873                                       gnome_canvas_ellipse_get_type (),
874                                       "x1", 0.0,
875                                       "y1", 0.0,
876                                       "x2", 2.0*r,
877                                       "y2", 2.0*r,
878                                       "width_pixels", 2,
879                                       "outline_color_rgba", OUTLINE_COLOR,
880                                       NULL);
881
882         gl_debug (DEBUG_VIEW, "END");
883 }
884
885 /*---------------------------------------------------------------------------*/
886 /* PRIVATE.  Draw CD style background, circular w/ concentric hole.          */
887 /*---------------------------------------------------------------------------*/
888 static void
889 draw_bg_fg_cd (glView *view)
890 {
891         glLabel          *label;
892         glTemplate       *template;
893         gdouble           r1, r2;
894         GnomeCanvasItem  *item;
895
896         gl_debug (DEBUG_VIEW, "START");
897
898         g_return_if_fail (view && GL_IS_VIEW (view));
899         g_return_if_fail (view->label && GL_IS_LABEL (view->label));
900
901         label    = view->label;
902         template = gl_label_get_template (label);
903
904         r1 = template->label.cd.r1;
905         r2 = template->label.cd.r2;
906
907         /* Background */
908         /* outer circle */
909         item = gnome_canvas_item_new (view->bg_group,
910                                       gnome_canvas_ellipse_get_type (),
911                                       "x1", 0.0,
912                                       "y1", 0.0,
913                                       "x2", 2.0*r1,
914                                       "y2", 2.0*r1,
915                                       "fill_color_rgba", PAPER_COLOR,
916                                       NULL);
917         /* hole */
918         item = gnome_canvas_item_new (view->bg_group,
919                                       gnome_canvas_ellipse_get_type (),
920                                       "x1", r1 - r2,
921                                       "y1", r1 - r2,
922                                       "x2", r1 + r2,
923                                       "y2", r1 + r2,
924                                       "fill_color_rgba", GRID_COLOR,
925                                       NULL);
926
927         /* Foreground */
928         /* outer circle */
929         item = gnome_canvas_item_new (view->fg_group,
930                                       gnome_canvas_ellipse_get_type (),
931                                       "x1", 0.0,
932                                       "y1", 0.0,
933                                       "x2", 2.0*r1,
934                                       "y2", 2.0*r1,
935                                       "width_pixels", 2,
936                                       "outline_color_rgba", OUTLINE_COLOR,
937                                       NULL);
938         /* hole */
939         item = gnome_canvas_item_new (view->fg_group,
940                                       gnome_canvas_ellipse_get_type (),
941                                       "x1", r1 - r2,
942                                       "y1", r1 - r2,
943                                       "x2", r1 + r2,
944                                       "y2", r1 + r2,
945                                       "width_pixels", 2,
946                                       "outline_color_rgba", OUTLINE_COLOR,
947                                       NULL);
948
949         gl_debug (DEBUG_VIEW, "END");
950 }
951
952 /*---------------------------------------------------------------------------*/
953 /* PRIVATE.  Draw Business Card CD style background, CD w/ chopped ends.     */
954 /*---------------------------------------------------------------------------*/
955 static void
956 draw_bg_fg_cd_bc (glView *view)
957 {
958         glLabel           *label;
959         glTemplate        *template;
960         GnomeCanvasPoints *points;
961         gint               i_coords, i_theta;
962         gdouble            theta1, theta2;
963         gdouble            x0, y0, w, h, r1, r2;
964         GnomeCanvasItem   *item;
965
966         gl_debug (DEBUG_VIEW, "START");
967
968         g_return_if_fail (view && GL_IS_VIEW (view));
969         g_return_if_fail (view->label && GL_IS_LABEL (view->label));
970
971         label    = view->label;
972
973         template = gl_label_get_template (label);
974         gl_label_get_size (label, &w, &h);
975         x0 = w/2.0;
976         y0 = h/2.0;
977
978         r1 = template->label.cd.r1;
979         r2 = template->label.cd.r2;
980
981         theta1 = (180.0/G_PI) * acos (w / (2.0*r1));
982         theta2 = (180.0/G_PI) * asin (h / (2.0*r1));
983
984         points = gnome_canvas_points_new (360/ARC_FINE + 1);
985         i_coords = 0;
986
987         points->coords[i_coords++] = x0 + r1 * cos (theta1 * G_PI / 180.0);
988         points->coords[i_coords++] = y0 + r1 * sin (theta1 * G_PI / 180.0);
989
990         for ( i_theta = theta1 + ARC_FINE; i_theta < theta2; i_theta +=ARC_FINE ) {
991                 points->coords[i_coords++] = x0 + r1 * cos (i_theta * G_PI / 180.0);
992                 points->coords[i_coords++] = y0 + r1 * sin (i_theta * G_PI / 180.0);
993         }
994
995         points->coords[i_coords++] = x0 + r1 * cos (theta2 * G_PI / 180.0);
996         points->coords[i_coords++] = y0 + r1 * sin (theta2 * G_PI / 180.0);
997
998
999         if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
1000                 points->coords[i_coords++] = x0 + r1 * cos ((180-theta2) * G_PI / 180.0);
1001                 points->coords[i_coords++] = y0 + r1 * sin ((180-theta2) * G_PI / 180.0);
1002         }
1003
1004         for ( i_theta = 180-theta2+ARC_FINE; i_theta < (180-theta1); i_theta +=ARC_FINE ) {
1005                 points->coords[i_coords++] = x0 + r1 * cos (i_theta * G_PI / 180.0);
1006                 points->coords[i_coords++] = y0 + r1 * sin (i_theta * G_PI / 180.0);
1007         }
1008
1009         points->coords[i_coords++] = x0 + r1 * cos ((180-theta1) * G_PI / 180.0);
1010         points->coords[i_coords++] = y0 + r1 * sin ((180-theta1) * G_PI / 180.0);
1011
1012         if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
1013                 points->coords[i_coords++] = x0 + r1 * cos ((180+theta1) * G_PI / 180.0);
1014                 points->coords[i_coords++] = y0 + r1 * sin ((180+theta1) * G_PI / 180.0);
1015         }
1016
1017         for ( i_theta = 180+theta1+ARC_FINE; i_theta < (180+theta2); i_theta +=ARC_FINE ) {
1018                 points->coords[i_coords++] = x0 + r1 * cos (i_theta * G_PI / 180.0);
1019                 points->coords[i_coords++] = y0 + r1 * sin (i_theta * G_PI / 180.0);
1020         }
1021
1022         points->coords[i_coords++] = x0 + r1 * cos ((180+theta2) * G_PI / 180.0);
1023         points->coords[i_coords++] = y0 + r1 * sin ((180+theta2) * G_PI / 180.0);
1024
1025         if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
1026                 points->coords[i_coords++] = x0 + r1 * cos ((360-theta2) * G_PI / 180.0);
1027                 points->coords[i_coords++] = y0 + r1 * sin ((360-theta2) * G_PI / 180.0);
1028         }
1029
1030         for ( i_theta = 360-theta2+ARC_FINE; i_theta < (360-theta1); i_theta +=ARC_FINE ) {
1031                 points->coords[i_coords++] = x0 + r1 * cos (i_theta * G_PI / 180.0);
1032                 points->coords[i_coords++] = y0 + r1 * sin (i_theta * G_PI / 180.0);
1033         }
1034
1035         if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
1036                 points->coords[i_coords++] = x0 + r1 * cos ((360-theta1) * G_PI / 180.0);
1037                 points->coords[i_coords++] = y0 + r1 * sin ((360-theta1) * G_PI / 180.0);
1038         }
1039
1040         points->num_points = i_coords / 2;
1041
1042         /* Background */
1043         /* outer circle */
1044         item = gnome_canvas_item_new (view->bg_group,
1045                                       gnome_canvas_polygon_get_type (),
1046                                       "points", points,
1047                                       "fill_color_rgba", PAPER_COLOR,
1048                                       NULL);
1049         /* hole */
1050         item = gnome_canvas_item_new (view->bg_group,
1051                                       gnome_canvas_ellipse_get_type (),
1052                                       "x1", x0 - r2,
1053                                       "y1", y0 - r2,
1054                                       "x2", x0 + r2,
1055                                       "y2", y0 + r2,
1056                                       "fill_color_rgba", GRID_COLOR,
1057                                       NULL);
1058
1059         /* Foreground */
1060         /* outer circle */
1061         item = gnome_canvas_item_new (view->fg_group,
1062                                       gnome_canvas_polygon_get_type (),
1063                                       "points", points,
1064                                       "width_pixels", 2,
1065                                       "outline_color_rgba", OUTLINE_COLOR,
1066                                       NULL);
1067         /* hole */
1068         item = gnome_canvas_item_new (view->fg_group,
1069                                       gnome_canvas_ellipse_get_type (),
1070                                       "x1", x0 - r2,
1071                                       "y1", y0 - r2,
1072                                       "x2", x0 + r2,
1073                                       "y2", y0 + r2,
1074                                       "width_pixels", 2,
1075                                       "outline_color_rgba", OUTLINE_COLOR,
1076                                       NULL);
1077
1078         gnome_canvas_points_free (points);
1079
1080         gl_debug (DEBUG_VIEW, "END");
1081 }
1082
1083 /*---------------------------------------------------------------------------*/
1084 /* PRIVATE.  Draw grid lines.                                                */
1085 /*---------------------------------------------------------------------------*/
1086 static void
1087 draw_grid_layer (glView *view)
1088 {
1089         gdouble            w, h, x, y;
1090         GnomeCanvasPoints *points;
1091         GnomeCanvasItem  *item;
1092         GnomeCanvasGroup *group;
1093
1094         gl_debug (DEBUG_VIEW, "START");
1095
1096         g_return_if_fail (view && GL_IS_VIEW (view));
1097         g_return_if_fail (view->label && GL_IS_LABEL(view->label));
1098
1099         gl_label_get_size (view->label, &w, &h);
1100
1101         group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
1102         view->grid_group = GNOME_CANVAS_GROUP(
1103                 gnome_canvas_item_new (group,
1104                                        gnome_canvas_group_get_type (),
1105                                        "x", 0.0,
1106                                        "y", 0.0,
1107                                        NULL));
1108         points = gnome_canvas_points_new (2);
1109
1110         points->coords[1] = 0.0;
1111         points->coords[3] = h;
1112         for ( x=0.0; x < w; x += view->grid_spacing ) {
1113                 points->coords[0] = points->coords[2] = x;
1114                 item = gnome_canvas_item_new (view->grid_group,
1115                                               gnome_canvas_line_get_type (),
1116                                               "points", points,
1117                                               "width_pixels", 1,
1118                                               "fill_color_rgba", GRID_COLOR,
1119                                               NULL);
1120         }
1121         points->coords[0] = points->coords[2] = w;
1122         item = gnome_canvas_item_new (view->grid_group,
1123                                       gnome_canvas_line_get_type (),
1124                                       "points", points,
1125                                       "width_pixels", 1,
1126                                       "fill_color_rgba", GRID_COLOR,
1127                                       NULL);
1128
1129         points->coords[0] = 0.0;
1130         points->coords[2] = w;
1131         for ( y=0.0; y < h; y += view->grid_spacing ) {
1132                 points->coords[1] = points->coords[3] = y;
1133                 item = gnome_canvas_item_new (view->grid_group,
1134                                               gnome_canvas_line_get_type (),
1135                                               "points", points,
1136                                               "width_pixels", 1,
1137                                               "fill_color_rgba", GRID_COLOR,
1138                                               NULL);
1139         }
1140         points->coords[1] = points->coords[3] = h;
1141         item = gnome_canvas_item_new (view->grid_group,
1142                                       gnome_canvas_line_get_type (),
1143                                       "points", points,
1144                                       "width_pixels", 1,
1145                                       "fill_color_rgba", GRID_COLOR,
1146                                       NULL);
1147
1148         gnome_canvas_points_free (points);
1149
1150         gl_debug (DEBUG_VIEW, "END");
1151 }
1152
1153 /*---------------------------------------------------------------------------*/
1154 /* PRIVATE.  Draw markup lines.                                              */
1155 /*---------------------------------------------------------------------------*/
1156 static void
1157 draw_markup_layer (glView *view)
1158 {
1159         GnomeCanvasGroup *group;
1160         glLabel          *label;
1161         glTemplate       *template;
1162         GList            *p;
1163         glTemplateMarkup *markup;
1164
1165         g_return_if_fail (view && GL_IS_VIEW (view));
1166         g_return_if_fail (view->label && GL_IS_LABEL (view->label));
1167
1168         group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
1169         view->markup_group = GNOME_CANVAS_GROUP(
1170                 gnome_canvas_item_new (group,
1171                                        gnome_canvas_group_get_type (),
1172                                        "x", 0.0,
1173                                        "y", 0.0,
1174                                        NULL));
1175
1176         label    = view->label;
1177         template = gl_label_get_template (label);
1178
1179         for ( p=template->label.any.markups; p != NULL; p=p->next ) {
1180                 markup = (glTemplateMarkup *)p->data;
1181
1182                 switch (markup->type) {
1183                 case GL_TEMPLATE_MARKUP_MARGIN:
1184                         draw_markup_margin (view,
1185                                             (glTemplateMarkupMargin *)markup);
1186                         break;
1187                 case GL_TEMPLATE_MARKUP_LINE:
1188                         draw_markup_line (view,
1189                                           (glTemplateMarkupLine *)markup);
1190                         break;
1191                 case GL_TEMPLATE_MARKUP_CIRCLE:
1192                         draw_markup_circle (view,
1193                                             (glTemplateMarkupCircle *)markup);
1194                         break;
1195                 default:
1196                         g_warning ("Unknown template markup type");
1197                         break;
1198                 }
1199         }
1200 }
1201
1202 /*---------------------------------------------------------------------------*/
1203 /* PRIVATE.  Draw margin markup.                                             */
1204 /*---------------------------------------------------------------------------*/
1205 static void
1206 draw_markup_margin (glView                 *view,
1207                     glTemplateMarkupMargin *margin)
1208 {
1209         glLabel    *label;
1210         glTemplate *template;
1211
1212         g_return_if_fail (view && GL_IS_VIEW (view));
1213         g_return_if_fail (view->label && GL_IS_LABEL (view->label));
1214
1215         label    = view->label;
1216         template = gl_label_get_template (label);
1217
1218         switch (template->label.style) {
1219
1220         case GL_TEMPLATE_STYLE_RECT:
1221                 if (template->label.rect.r == 0.0) {
1222                         /* Square corners. */
1223                         draw_markup_margin_rect (view, margin);
1224                 } else {
1225                         if ( margin->size < template->label.rect.r) {
1226                                 /* Rounded corners. */
1227                                 draw_markup_margin_rounded_rect (view, margin);
1228                         } else {
1229                                 /* Square corners. */
1230                                 draw_markup_margin_rect (view, margin);
1231                         }
1232                 }
1233                 break;
1234
1235         case GL_TEMPLATE_STYLE_ROUND:
1236                 draw_markup_margin_round (view, margin);
1237                 break;
1238
1239         case GL_TEMPLATE_STYLE_CD:
1240                 if ((template->label.cd.w == 0.0) && (template->label.cd.h == 0.0) ) {
1241                         draw_markup_margin_cd (view, margin);
1242                 } else {
1243                         draw_markup_margin_cd_bc (view, margin);
1244                 }
1245                 break;
1246
1247         default:
1248                 g_warning ("Unknown template label style");
1249                 break;
1250         }
1251 }
1252
1253 /*---------------------------------------------------------------------------*/
1254 /* PRIVATE.  Draw simple recangular margin.                                  */
1255 /*---------------------------------------------------------------------------*/
1256 static void
1257 draw_markup_margin_rect (glView                 *view,
1258                          glTemplateMarkupMargin *margin)
1259 {
1260         glLabel          *label;
1261         glTemplate       *template;
1262         gdouble           w, h, m;
1263         GnomeCanvasItem  *item;
1264
1265         gl_debug (DEBUG_VIEW, "START");
1266
1267         g_return_if_fail (view && GL_IS_VIEW (view));
1268         g_return_if_fail (view->label && GL_IS_LABEL (view->label));
1269
1270         label = view->label;
1271
1272         gl_label_get_size (label, &w, &h);
1273         template = gl_label_get_template (label);
1274         m = margin->size;
1275
1276         /* Bounding box @ margin */
1277         gnome_canvas_item_new (view->markup_group,
1278                                gnome_canvas_rect_get_type (),
1279                                "x1", m,
1280                                "y1", m,
1281                                "x2", w - m,
1282                                "y2", h - m,
1283                                "width_pixels", 1,
1284                                "outline_color_rgba", MARKUP_COLOR,
1285                                NULL);
1286
1287         gl_debug (DEBUG_VIEW, "END");
1288 }
1289
1290 /*---------------------------------------------------------------------------*/
1291 /* PRIVATE.  Draw rounded recangular markup.                                 */
1292 /*---------------------------------------------------------------------------*/
1293 static void
1294 draw_markup_margin_rounded_rect (glView                 *view,
1295                                  glTemplateMarkupMargin *margin)
1296 {
1297         glLabel           *label;
1298         GnomeCanvasPoints *points;
1299         gint               i_coords, i_theta;
1300         glTemplate        *template;
1301         gdouble            r, w, h, m;
1302         GnomeCanvasItem   *item;
1303
1304         gl_debug (DEBUG_VIEW, "START");
1305
1306         g_return_if_fail (view && GL_IS_VIEW (view));
1307         g_return_if_fail (view->label && GL_IS_LABEL (view->label));
1308
1309         label = view->label;
1310
1311         gl_label_get_size (label, &w, &h);
1312         template = gl_label_get_template (label);
1313         r = template->label.rect.r;
1314         m = margin->size;
1315
1316         r = r - m;
1317         w = w - 2 * m;
1318         h = h - 2 * m;
1319
1320         /* rectangle with rounded corners */
1321         points = gnome_canvas_points_new (4 * (1 + 90 / ARC_COURSE));
1322         i_coords = 0;
1323         for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
1324                 points->coords[i_coords++] =
1325                         m + r - r * sin (i_theta * G_PI / 180.0);
1326                 points->coords[i_coords++] =
1327                         m + r - r * cos (i_theta * G_PI / 180.0);
1328         }
1329         for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
1330                 points->coords[i_coords++] =
1331                         m + r - r * cos (i_theta * G_PI / 180.0);
1332                 points->coords[i_coords++] =
1333                         m + (h - r) + r * sin (i_theta * G_PI / 180.0);
1334         }
1335         for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
1336                 points->coords[i_coords++] =
1337                         m + (w - r) + r * sin (i_theta * G_PI / 180.0);
1338                 points->coords[i_coords++] =
1339                         m + (h - r) + r * cos (i_theta * G_PI / 180.0);
1340         }
1341         for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
1342                 points->coords[i_coords++] =
1343                         m + (w - r) + r * cos (i_theta * G_PI / 180.0);
1344                 points->coords[i_coords++] =
1345                         m + r - r * sin (i_theta * G_PI / 180.0);
1346         }
1347         item = gnome_canvas_item_new (view->markup_group,
1348                                       gnome_canvas_polygon_get_type (),
1349                                       "points", points,
1350                                       "width_pixels", 1,
1351                                       "outline_color_rgba", MARKUP_COLOR,
1352                                       NULL);
1353         gnome_canvas_points_free (points);
1354
1355         gl_debug (DEBUG_VIEW, "END");
1356 }
1357
1358 /*---------------------------------------------------------------------------*/
1359 /* PRIVATE.  Draw round margin.                                              */
1360 /*---------------------------------------------------------------------------*/
1361 static void
1362 draw_markup_margin_round (glView                 *view,
1363                           glTemplateMarkupMargin *margin)
1364 {
1365         glLabel          *label;
1366         glTemplate       *template;
1367         gdouble           r, m;
1368         GnomeCanvasItem  *item;
1369
1370         gl_debug (DEBUG_VIEW, "START");
1371
1372         g_return_if_fail (view && GL_IS_VIEW (view));
1373         g_return_if_fail (view->label && GL_IS_LABEL (view->label));
1374
1375         label    = view->label;
1376         template = gl_label_get_template (label);
1377
1378         r = template->label.round.r;
1379         m = margin->size;
1380
1381         /* Margin outline */
1382         item = gnome_canvas_item_new (view->markup_group,
1383                                       gnome_canvas_ellipse_get_type (),
1384                                       "x1", m,
1385                                       "y1", m,
1386                                       "x2", 2.0*r - m,
1387                                       "y2", 2.0*r - m,
1388                                       "width_pixels", 1,
1389                                       "outline_color_rgba", MARKUP_COLOR,
1390                                       NULL);
1391
1392         gl_debug (DEBUG_VIEW, "END");
1393 }
1394
1395 /*---------------------------------------------------------------------------*/
1396 /* PRIVATE.  Draw CD margins.                                                */
1397 /*---------------------------------------------------------------------------*/
1398 static void
1399 draw_markup_margin_cd (glView                 *view,
1400                        glTemplateMarkupMargin *margin)
1401 {
1402         glLabel          *label;
1403         glTemplate       *template;
1404         gdouble           m, r1, r2;
1405         GnomeCanvasItem  *item;
1406
1407         gl_debug (DEBUG_VIEW, "START");
1408
1409         g_return_if_fail (view && GL_IS_VIEW (view));
1410         g_return_if_fail (view->label && GL_IS_LABEL (view->label));
1411
1412         label    = view->label;
1413         template = gl_label_get_template (label);
1414
1415         r1 = template->label.cd.r1;
1416         r2 = template->label.cd.r2;
1417         m  = margin->size;
1418
1419         /* outer margin */
1420         item = gnome_canvas_item_new (view->markup_group,
1421                                       gnome_canvas_ellipse_get_type (),
1422                                       "x1", m,
1423                                       "y1", m,
1424                                       "x2", 2.0*r1 - m,
1425                                       "y2", 2.0*r1 - m,
1426                                       "width_pixels", 1,
1427                                       "outline_color_rgba", MARKUP_COLOR,
1428                                       NULL);
1429         /* inner margin */
1430         item = gnome_canvas_item_new (view->markup_group,
1431                                       gnome_canvas_ellipse_get_type (),
1432                                       "x1", r1 - r2 - m,
1433                                       "y1", r1 - r2 - m,
1434                                       "x2", r1 + r2 + m,
1435                                       "y2", r1 + r2 + m,
1436                                       "width_pixels", 1,
1437                                       "outline_color_rgba", MARKUP_COLOR,
1438                                       NULL);
1439
1440         gl_debug (DEBUG_VIEW, "END");
1441 }
1442
1443 /*---------------------------------------------------------------------------*/
1444 /* PRIVATE.  Draw Business Card CD margins.                                  */
1445 /*---------------------------------------------------------------------------*/
1446 static void
1447 draw_markup_margin_cd_bc (glView                 *view,
1448                           glTemplateMarkupMargin *margin)
1449 {
1450         glLabel           *label;
1451         glTemplate        *template;
1452         gdouble            m, r1, r2;
1453         GnomeCanvasPoints *points;
1454         gint               i_coords, i_theta;
1455         gdouble            theta1, theta2;
1456         gdouble            x0, y0, w, h, r;
1457         GnomeCanvasItem   *item;
1458
1459         gl_debug (DEBUG_VIEW, "START");
1460
1461         g_return_if_fail (view && GL_IS_VIEW (view));
1462         g_return_if_fail (view->label && GL_IS_LABEL (view->label));
1463
1464         label    = view->label;
1465         template = gl_label_get_template (label);
1466         gl_label_get_size (label, &w, &h);
1467         x0 = w/2.0;
1468         y0 = h/2.0;
1469
1470         r1 = template->label.cd.r1;
1471         r2 = template->label.cd.r2;
1472         m  = margin->size;
1473
1474         /* outer margin */
1475         r = r1 - m;
1476         theta1 = (180.0/G_PI) * acos (w / (2.0*r1));
1477         theta2 = (180.0/G_PI) * asin (h / (2.0*r1));
1478
1479         points = gnome_canvas_points_new (360/ARC_FINE + 1);
1480         i_coords = 0;
1481
1482         points->coords[i_coords++] = x0 + r * cos (theta1 * G_PI / 180.0);
1483         points->coords[i_coords++] = y0 + r * sin (theta1 * G_PI / 180.0);
1484
1485         for ( i_theta = theta1 + ARC_FINE; i_theta < theta2; i_theta +=ARC_FINE ) {
1486                 points->coords[i_coords++] = x0 + r * cos (i_theta * G_PI / 180.0);
1487                 points->coords[i_coords++] = y0 + r * sin (i_theta * G_PI / 180.0);
1488         }
1489
1490         points->coords[i_coords++] = x0 + r * cos (theta2 * G_PI / 180.0);
1491         points->coords[i_coords++] = y0 + r * sin (theta2 * G_PI / 180.0);
1492
1493
1494         if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
1495                 points->coords[i_coords++] = x0 + r * cos ((180-theta2) * G_PI / 180.0);
1496                 points->coords[i_coords++] = y0 + r * sin ((180-theta2) * G_PI / 180.0);
1497         }
1498
1499         for ( i_theta = 180-theta2+ARC_FINE; i_theta < (180-theta1); i_theta +=ARC_FINE ) {
1500                 points->coords[i_coords++] = x0 + r * cos (i_theta * G_PI / 180.0);
1501                 points->coords[i_coords++] = y0 + r * sin (i_theta * G_PI / 180.0);
1502         }
1503
1504         points->coords[i_coords++] = x0 + r * cos ((180-theta1) * G_PI / 180.0);
1505         points->coords[i_coords++] = y0 + r * sin ((180-theta1) * G_PI / 180.0);
1506
1507         if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
1508                 points->coords[i_coords++] = x0 + r * cos ((180+theta1) * G_PI / 180.0);
1509                 points->coords[i_coords++] = y0 + r * sin ((180+theta1) * G_PI / 180.0);
1510         }
1511
1512         for ( i_theta = 180+theta1+ARC_FINE; i_theta < (180+theta2); i_theta +=ARC_FINE ) {
1513                 points->coords[i_coords++] = x0 + r * cos (i_theta * G_PI / 180.0);
1514                 points->coords[i_coords++] = y0 + r * sin (i_theta * G_PI / 180.0);
1515         }
1516
1517         points->coords[i_coords++] = x0 + r * cos ((180+theta2) * G_PI / 180.0);
1518         points->coords[i_coords++] = y0 + r * sin ((180+theta2) * G_PI / 180.0);
1519
1520         if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
1521                 points->coords[i_coords++] = x0 + r * cos ((360-theta2) * G_PI / 180.0);
1522                 points->coords[i_coords++] = y0 + r * sin ((360-theta2) * G_PI / 180.0);
1523         }
1524
1525         for ( i_theta = 360-theta2+ARC_FINE; i_theta < (360-theta1); i_theta +=ARC_FINE ) {
1526                 points->coords[i_coords++] = x0 + r * cos (i_theta * G_PI / 180.0);
1527                 points->coords[i_coords++] = y0 + r * sin (i_theta * G_PI / 180.0);
1528         }
1529
1530         if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
1531                 points->coords[i_coords++] = x0 + r * cos ((360-theta1) * G_PI / 180.0);
1532                 points->coords[i_coords++] = y0 + r * sin ((360-theta1) * G_PI / 180.0);
1533         }
1534
1535         points->num_points = i_coords / 2;
1536
1537         item = gnome_canvas_item_new (view->markup_group,
1538                                       gnome_canvas_polygon_get_type (),
1539                                       "points", points,
1540                                       "width_pixels", 1,
1541                                       "outline_color_rgba", MARKUP_COLOR,
1542                                       NULL);
1543
1544         gnome_canvas_points_free (points);
1545
1546         /* inner margin */
1547         item = gnome_canvas_item_new (view->markup_group,
1548                                       gnome_canvas_ellipse_get_type (),
1549                                       "x1", x0 - r2 - m,
1550                                       "y1", y0 - r2 - m,
1551                                       "x2", x0 + r2 + m,
1552                                       "y2", y0 + r2 + m,
1553                                       "width_pixels", 1,
1554                                       "outline_color_rgba", MARKUP_COLOR,
1555                                       NULL);
1556
1557         gl_debug (DEBUG_VIEW, "END");
1558 }
1559
1560 /*---------------------------------------------------------------------------*/
1561 /* PRIVATE.  Draw line markup.                                               */
1562 /*---------------------------------------------------------------------------*/
1563 static void
1564 draw_markup_line (glView               *view,
1565                   glTemplateMarkupLine *line)
1566 {
1567         GnomeCanvasPoints *points;
1568
1569         gl_debug (DEBUG_VIEW, "START");
1570
1571         g_return_if_fail (view && GL_IS_VIEW (view));
1572
1573         points = gnome_canvas_points_new (2);
1574         points->coords[0] = line->x1;
1575         points->coords[1] = line->y1;
1576         points->coords[2] = line->x2;
1577         points->coords[3] = line->y2;
1578
1579         /* Bounding box @ margin */
1580         gnome_canvas_item_new (view->markup_group,
1581                                gnome_canvas_line_get_type (),
1582                                "points", points,
1583                                "width_pixels", 1,
1584                                "fill_color_rgba", MARKUP_COLOR,
1585                                NULL);
1586
1587         gnome_canvas_points_free (points);
1588
1589         gl_debug (DEBUG_VIEW, "END");
1590 }
1591
1592 /*---------------------------------------------------------------------------*/
1593 /* PRIVATE.  Draw circle markup.                                             */
1594 /*---------------------------------------------------------------------------*/
1595 static void
1596 draw_markup_circle (glView                 *view,
1597                     glTemplateMarkupCircle *circle)
1598 {
1599         gl_debug (DEBUG_VIEW, "START");
1600
1601         g_return_if_fail (view && GL_IS_VIEW (view));
1602
1603         /* Circle outline */
1604         gnome_canvas_item_new (view->markup_group,
1605                                gnome_canvas_ellipse_get_type (),
1606                                "x1", circle->x0 - circle->r,
1607                                "y1", circle->y0 - circle->r,
1608                                "x2", circle->x0 + circle->r,
1609                                "y2", circle->y0 + circle->r,
1610                                "width_pixels", 1,
1611                                "outline_color_rgba", MARKUP_COLOR,
1612                                NULL);
1613
1614         gl_debug (DEBUG_VIEW, "END");
1615 }
1616
1617 /*****************************************************************************/
1618 /* Show grid.                                                                */
1619 /*****************************************************************************/
1620 void       gl_view_show_grid               (glView            *view)
1621 {
1622         g_return_if_fail (view && GL_IS_VIEW (view));
1623
1624         gnome_canvas_item_show (GNOME_CANVAS_ITEM(view->grid_group));
1625 }
1626
1627 /*****************************************************************************/
1628 /* Hide grid.                                                                */
1629 /*****************************************************************************/
1630 void       gl_view_hide_grid               (glView            *view)
1631 {
1632         g_return_if_fail (view && GL_IS_VIEW (view));
1633
1634         gnome_canvas_item_hide (GNOME_CANVAS_ITEM(view->grid_group));
1635 }
1636
1637 /*****************************************************************************/
1638 /* Set grid spacing.                                                         */
1639 /*****************************************************************************/
1640 void       gl_view_set_grid_spacing        (glView            *view,
1641                                             gdouble            spacing)
1642 {
1643         g_return_if_fail (view && GL_IS_VIEW (view));
1644
1645         view->grid_spacing = spacing;
1646
1647         gtk_object_destroy (GTK_OBJECT(view->grid_group));
1648         draw_grid_layer (view);
1649 }
1650
1651 /*****************************************************************************/
1652 /* Show markup.                                                              */
1653 /*****************************************************************************/
1654 void       gl_view_show_markup             (glView            *view)
1655 {
1656         g_return_if_fail (view && GL_IS_VIEW (view));
1657
1658         gnome_canvas_item_show (GNOME_CANVAS_ITEM(view->markup_group));
1659 }
1660
1661 /*****************************************************************************/
1662 /* Hide markup.                                                              */
1663 /*****************************************************************************/
1664 void       gl_view_hide_markup             (glView            *view)
1665 {
1666         g_return_if_fail (view && GL_IS_VIEW (view));
1667
1668         gnome_canvas_item_hide (GNOME_CANVAS_ITEM(view->markup_group));
1669 }
1670
1671 /*****************************************************************************/
1672 /* Set arrow mode.                                                           */
1673 /*****************************************************************************/
1674 void
1675 gl_view_arrow_mode (glView *view)
1676 {
1677         static GdkCursor *cursor = NULL;
1678
1679         gl_debug (DEBUG_VIEW, "START");
1680
1681         g_return_if_fail (view && GL_IS_VIEW (view));
1682
1683         if (!cursor) {
1684                 cursor = gdk_cursor_new (GDK_LEFT_PTR);
1685         }
1686
1687         gdk_window_set_cursor (view->canvas->window, cursor);
1688
1689         view->state = GL_VIEW_STATE_ARROW;
1690
1691         gl_debug (DEBUG_VIEW, "END");
1692 }
1693
1694 /*****************************************************************************/
1695 /* Set create text object mode.                                              */
1696 /*****************************************************************************/
1697 void
1698 gl_view_object_create_mode (glView            *view,
1699                             glLabelObjectType type)
1700 {
1701         GdkCursor *cursor;
1702
1703         gl_debug (DEBUG_VIEW, "START");
1704
1705         g_return_if_fail (view && GL_IS_VIEW (view));
1706
1707         switch (type) {
1708         case GL_LABEL_OBJECT_BOX:
1709                 cursor = gl_view_box_get_create_cursor ();
1710                 break;
1711         case GL_LABEL_OBJECT_ELLIPSE:
1712                 cursor = gl_view_ellipse_get_create_cursor ();
1713                 break;
1714         case GL_LABEL_OBJECT_LINE:
1715                 cursor = gl_view_line_get_create_cursor ();
1716                 break;
1717         case GL_LABEL_OBJECT_IMAGE:
1718                 cursor = gl_view_image_get_create_cursor ();
1719                 break;
1720         case GL_LABEL_OBJECT_TEXT:
1721                 cursor = gl_view_text_get_create_cursor ();
1722                 break;
1723         case GL_LABEL_OBJECT_BARCODE:
1724                 cursor = gl_view_barcode_get_create_cursor ();
1725                 break;
1726         default:
1727                 g_warning ("Invalid label object type.");/*Should not happen!*/
1728                 break;
1729         }
1730
1731         gdk_window_set_cursor (view->canvas->window, cursor);
1732
1733         view->state = GL_VIEW_STATE_OBJECT_CREATE;
1734         view->create_type = type;
1735
1736         gl_debug (DEBUG_VIEW, "END");
1737 }
1738
1739 /*****************************************************************************/
1740 /* Select given object (adding to current selection).                        */
1741 /*****************************************************************************/
1742 void
1743 gl_view_select_object (glView       *view,
1744                        glViewObject *view_object)
1745 {
1746         gl_debug (DEBUG_VIEW, "START");
1747
1748         g_return_if_fail (view && GL_IS_VIEW (view));
1749
1750         select_object_real (view, view_object);
1751
1752         g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1753
1754         gl_debug (DEBUG_VIEW, "END");
1755 }
1756
1757 /*****************************************************************************/
1758 /* Unselect given object (removing from current selection).                  */
1759 /*****************************************************************************/
1760 void
1761 gl_view_unselect_object (glView       *view,
1762                          glViewObject *view_object)
1763 {
1764         gl_debug (DEBUG_VIEW, "START");
1765
1766         g_return_if_fail (view && GL_IS_VIEW (view));
1767
1768         unselect_object_real (view, view_object);
1769
1770         g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1771
1772         gl_debug (DEBUG_VIEW, "END");
1773 }
1774
1775 /*****************************************************************************/
1776 /* Select all items.                                                         */
1777 /*****************************************************************************/
1778 void
1779 gl_view_select_all (glView *view)
1780 {
1781         GList *p, *p_next;
1782
1783         gl_debug (DEBUG_VIEW, "START");
1784
1785         g_return_if_fail (view && GL_IS_VIEW (view));
1786
1787         /* 1st unselect anything already selected. */
1788         for (p = view->selected_object_list; p != NULL; p = p_next) {
1789                 p_next = p->next;
1790                 unselect_object_real (view, GL_VIEW_OBJECT (p->data));
1791         }
1792
1793         /* Finally select all objects. */
1794         for (p = view->object_list; p != NULL; p = p->next) {
1795                 select_object_real (view, GL_VIEW_OBJECT (p->data));
1796         }
1797
1798         g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1799
1800         gl_debug (DEBUG_VIEW, "END");
1801 }
1802
1803 /*****************************************************************************/
1804 /* Remove all selections                                                     */
1805 /*****************************************************************************/
1806 void
1807 gl_view_unselect_all (glView *view)
1808 {
1809         GList *p, *p_next;
1810
1811         gl_debug (DEBUG_VIEW, "START");
1812
1813         g_return_if_fail (view && GL_IS_VIEW (view));
1814
1815         for (p = view->selected_object_list; p != NULL; p = p_next) {
1816                 p_next = p->next;
1817                 unselect_object_real (view, GL_VIEW_OBJECT (p->data));
1818         }
1819
1820         g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1821
1822         gl_debug (DEBUG_VIEW, "END");
1823 }
1824
1825 /*****************************************************************************/
1826 /* Select all objects within given rectangular region (adding to selection). */
1827 /*****************************************************************************/
1828 void
1829 gl_view_select_region (glView  *view,
1830                        gdouble  x1,
1831                        gdouble  y1,
1832                        gdouble  x2,
1833                        gdouble  y2)
1834 {
1835         GList *p;
1836         glViewObject *view_object;
1837         glLabelObject *object;
1838         gdouble i_x1, i_y1, i_x2, i_y2;
1839
1840         gl_debug (DEBUG_VIEW, "START");
1841
1842         g_return_if_fail (view && GL_IS_VIEW (view));
1843         g_return_if_fail ((x1 <= x2) && (y1 <= y2));
1844
1845         for (p = view->object_list; p != NULL; p = p->next) {
1846                 view_object = GL_VIEW_OBJECT(p->data);
1847                 if (!gl_view_is_object_selected (view, view_object)) {
1848
1849                         object = gl_view_object_get_object (view_object);
1850
1851                         gl_label_object_get_extent (object, &i_x1, &i_y1, &i_x2, &i_y2);
1852                         if ((i_x1 >= x1) && (i_x2 <= x2) && (i_y1 >= y1)
1853                             && (i_y2 <= y2)) {
1854                                 select_object_real (view, view_object);
1855                         }
1856
1857                 }
1858         }
1859
1860         g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1861
1862         gl_debug (DEBUG_VIEW, "END");
1863 }
1864
1865 /*---------------------------------------------------------------------------*/
1866 /* PRIVATE. Select an object.                                                */
1867 /*---------------------------------------------------------------------------*/
1868 static void
1869 select_object_real (glView       *view,
1870                     glViewObject *view_object)
1871 {
1872         gl_debug (DEBUG_VIEW, "START");
1873
1874         g_return_if_fail (view && GL_IS_VIEW (view));
1875         g_return_if_fail (GL_IS_VIEW_OBJECT (view_object));
1876
1877         if (!gl_view_is_object_selected (view, view_object)) {
1878                 view->selected_object_list =
1879                     g_list_prepend (view->selected_object_list, view_object);
1880         }
1881         gl_view_object_show_highlight (view_object);
1882         gtk_widget_grab_focus (GTK_WIDGET (view->canvas));
1883
1884         gl_debug (DEBUG_VIEW, "END");
1885 }
1886
1887 /*---------------------------------------------------------------------------*/
1888 /* PRIVATE.  Un-select object.                                               */
1889 /*---------------------------------------------------------------------------*/
1890 static void
1891 unselect_object_real (glView       *view,
1892                       glViewObject *view_object)
1893 {
1894         gl_debug (DEBUG_VIEW, "START");
1895
1896         g_return_if_fail (view && GL_IS_VIEW (view));
1897         g_return_if_fail (GL_IS_VIEW_OBJECT (view_object));
1898
1899         gl_view_object_hide_highlight (view_object);
1900
1901         view->selected_object_list =
1902             g_list_remove (view->selected_object_list, view_object);
1903
1904         gl_debug (DEBUG_VIEW, "END");
1905 }
1906
1907 /*---------------------------------------------------------------------------*/
1908 /* PRIVATE. Return object at (x,y).                                          */
1909 /*---------------------------------------------------------------------------*/
1910 static gboolean
1911 object_at (glView  *view,
1912            gdouble  x,
1913            gdouble  y)
1914 {
1915         GnomeCanvasItem *item, *p_item;
1916         GList *p;
1917
1918         gl_debug (DEBUG_VIEW, "");
1919
1920         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
1921
1922         item = gnome_canvas_get_item_at (GNOME_CANVAS (view->canvas), x, y);
1923
1924         /* No item is at x, y */
1925         if (item == NULL)
1926                 return FALSE;
1927
1928         /* ignore items not in label or highlight layers, e.g. background items */
1929         if (!is_item_member_of_group(view, item, GNOME_CANVAS_ITEM(view->label_group)) &&
1930             !is_item_member_of_group(view, item, GNOME_CANVAS_ITEM(view->highlight_group)))
1931                 return FALSE;
1932
1933         return TRUE;
1934 }
1935
1936 /*---------------------------------------------------------------------------*/
1937 /* PRIVATE.  Is the item a child (or grandchild, etc.) of group.             */
1938 /*---------------------------------------------------------------------------*/
1939 static gboolean
1940 is_item_member_of_group (glView          *view,
1941                          GnomeCanvasItem *item,
1942                          GnomeCanvasItem *group)
1943 {
1944         GnomeCanvasItem *parent;
1945         GnomeCanvasItem *root_group;
1946
1947         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
1948
1949         root_group = GNOME_CANVAS_ITEM(gnome_canvas_root (GNOME_CANVAS (view->canvas)));
1950
1951         for ( parent=item->parent; parent && (parent!=root_group); parent=parent->parent) {
1952                 if (parent == group) return TRUE;
1953         }
1954         return FALSE;
1955 }
1956
1957 /*****************************************************************************/
1958 /* Is the object in our current selection?                                   */
1959 /*****************************************************************************/
1960 gboolean
1961 gl_view_is_object_selected (glView       *view,
1962                     glViewObject *view_object)
1963 {
1964         gl_debug (DEBUG_VIEW, "");
1965
1966         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
1967         g_return_val_if_fail (GL_IS_VIEW_OBJECT (view_object), FALSE);
1968
1969         if (g_list_find (view->selected_object_list, view_object) == NULL) {
1970                 return FALSE;
1971         }
1972         return TRUE;
1973 }
1974
1975 /*****************************************************************************/
1976 /* Is our current selection empty?                                           */
1977 /*****************************************************************************/
1978 gboolean
1979 gl_view_is_selection_empty (glView *view)
1980 {
1981         gl_debug (DEBUG_VIEW, "");
1982
1983         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
1984
1985         if (view->selected_object_list == NULL) {
1986                 return TRUE;
1987         } else {
1988                 return FALSE;
1989         }
1990 }
1991
1992 /*****************************************************************************/
1993 /* Is our current selection atomic?  I.e. only one item selected.            */
1994 /*****************************************************************************/
1995 gboolean
1996 gl_view_is_selection_atomic (glView *view)
1997 {
1998         gl_debug (DEBUG_VIEW, "");
1999
2000         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
2001
2002         if (view->selected_object_list == NULL)
2003                 return FALSE;
2004         if (view->selected_object_list->next == NULL)
2005                 return TRUE;
2006         return FALSE;
2007 }
2008
2009 /*****************************************************************************/
2010 /* Delete selected objects. (Bypass clipboard)                               */
2011 /*****************************************************************************/
2012 void
2013 gl_view_delete_selection (glView *view)
2014 {
2015         GList *object_list, *p, *p_next;
2016
2017         gl_debug (DEBUG_VIEW, "START");
2018
2019         g_return_if_fail (view && GL_IS_VIEW (view));
2020
2021         object_list = view->selected_object_list;
2022         view->selected_object_list = NULL;
2023         g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
2024
2025         for (p = object_list; p != NULL; p = p_next) {
2026                 p_next = p->next;
2027                 g_object_unref (G_OBJECT (p->data));
2028                 object_list = g_list_delete_link (object_list, p);
2029         }
2030
2031         gl_debug (DEBUG_VIEW, "END");
2032 }
2033
2034 /*****************************************************************************/
2035 /* Get object property editor of first selected object.                      */
2036 /*****************************************************************************/
2037 GtkWidget *
2038 gl_view_get_editor (glView *view)
2039 {
2040         glViewObject *view_object;
2041         GtkWidget    *editor = NULL;
2042
2043         gl_debug (DEBUG_VIEW, "START");
2044
2045         g_return_if_fail (view && GL_IS_VIEW (view));
2046
2047         if (!gl_view_is_selection_empty (view)) {
2048
2049                 view_object = GL_VIEW_OBJECT(view->selected_object_list->data);
2050                 editor = gl_view_object_get_editor (view_object);
2051
2052         }
2053
2054         gl_debug (DEBUG_VIEW, "END");
2055
2056         return editor;
2057 }
2058
2059 /*****************************************************************************/
2060 /* Raise selected items to top.                                              */
2061 /*****************************************************************************/
2062 void
2063 gl_view_raise_selection (glView *view)
2064 {
2065         GList         *p;
2066         glViewObject  *view_object;
2067         glLabelObject *object;
2068
2069         gl_debug (DEBUG_VIEW, "START");
2070
2071         g_return_if_fail (view && GL_IS_VIEW (view));
2072
2073         for (p = view->selected_object_list; p != NULL; p = p->next) {
2074                 view_object = GL_VIEW_OBJECT (p->data);
2075                 object = gl_view_object_get_object (view_object);
2076                 gl_label_object_raise_to_top (object);
2077         }
2078
2079         gl_debug (DEBUG_VIEW, "END");
2080 }
2081
2082 /*****************************************************************************/
2083 /* Lower selected items to bottom.                                           */
2084 /*****************************************************************************/
2085 void
2086 gl_view_lower_selection (glView *view)
2087 {
2088         GList         *p;
2089         glViewObject  *view_object;
2090         glLabelObject *object;
2091
2092         gl_debug (DEBUG_VIEW, "START");
2093
2094         g_return_if_fail (view && GL_IS_VIEW (view));
2095
2096         for (p = view->selected_object_list; p != NULL; p = p->next) {
2097                 view_object = GL_VIEW_OBJECT (p->data);
2098                 object = gl_view_object_get_object (view_object);
2099                 gl_label_object_lower_to_bottom (object);
2100         }
2101
2102         gl_debug (DEBUG_VIEW, "END");
2103 }
2104
2105 /*****************************************************************************/
2106 /* Rotate selected objects by given angle.                                   */
2107 /*****************************************************************************/
2108 void
2109 gl_view_rotate_selection (glView *view,
2110                           gdouble theta_degs)
2111 {
2112         GList         *p;
2113         glViewObject  *view_object;
2114         glLabelObject *object;
2115
2116         gl_debug (DEBUG_VIEW, "START");
2117
2118         g_return_if_fail (view && GL_IS_VIEW (view));
2119
2120         for (p = view->selected_object_list; p != NULL; p = p->next) {
2121                 view_object = GL_VIEW_OBJECT (p->data);
2122                 object = gl_view_object_get_object (view_object);
2123                 gl_label_object_rotate (object, theta_degs);
2124         }
2125
2126         gl_debug (DEBUG_VIEW, "END");
2127 }
2128
2129 /*****************************************************************************/
2130 /* Rotate selected objects 90 degrees left.                                  */
2131 /*****************************************************************************/
2132 void
2133 gl_view_rotate_selection_left (glView *view)
2134 {
2135         GList         *p;
2136         glViewObject  *view_object;
2137         glLabelObject *object;
2138
2139         gl_debug (DEBUG_VIEW, "START");
2140
2141         g_return_if_fail (view && GL_IS_VIEW (view));
2142
2143         for (p = view->selected_object_list; p != NULL; p = p->next) {
2144                 view_object = GL_VIEW_OBJECT (p->data);
2145                 object = gl_view_object_get_object (view_object);
2146                 gl_label_object_rotate (object, -90.0);
2147         }
2148
2149         gl_debug (DEBUG_VIEW, "END");
2150 }
2151
2152 /*****************************************************************************/
2153 /* Rotate selected objects 90 degrees right.                                 */
2154 /*****************************************************************************/
2155 void
2156 gl_view_rotate_selection_right (glView *view)
2157 {
2158         GList         *p;
2159         glViewObject  *view_object;
2160         glLabelObject *object;
2161
2162         gl_debug (DEBUG_VIEW, "START");
2163
2164         g_return_if_fail (view && GL_IS_VIEW (view));
2165
2166         for (p = view->selected_object_list; p != NULL; p = p->next) {
2167                 view_object = GL_VIEW_OBJECT (p->data);
2168                 object = gl_view_object_get_object (view_object);
2169                 gl_label_object_rotate (object, 90.0);
2170         }
2171
2172         gl_debug (DEBUG_VIEW, "END");
2173 }
2174
2175 /*****************************************************************************/
2176 /* Flip selected objects horizontally.                                       */
2177 /*****************************************************************************/
2178 void
2179 gl_view_flip_selection_horiz (glView *view)
2180 {
2181         GList         *p;
2182         glViewObject  *view_object;
2183         glLabelObject *object;
2184
2185         gl_debug (DEBUG_VIEW, "START");
2186
2187         g_return_if_fail (view && GL_IS_VIEW (view));
2188
2189         for (p = view->selected_object_list; p != NULL; p = p->next) {
2190                 view_object = GL_VIEW_OBJECT (p->data);
2191                 object = gl_view_object_get_object (view_object);
2192                 gl_label_object_flip_horiz (object);
2193         }
2194
2195         gl_debug (DEBUG_VIEW, "END");
2196 }
2197
2198 /*****************************************************************************/
2199 /* Flip selected objects vertically.                                         */
2200 /*****************************************************************************/
2201 void
2202 gl_view_flip_selection_vert (glView *view)
2203 {
2204         GList         *p;
2205         glViewObject  *view_object;
2206         glLabelObject *object;
2207
2208         gl_debug (DEBUG_VIEW, "START");
2209
2210         g_return_if_fail (view && GL_IS_VIEW (view));
2211
2212         for (p = view->selected_object_list; p != NULL; p = p->next) {
2213                 view_object = GL_VIEW_OBJECT (p->data);
2214                 object = gl_view_object_get_object (view_object);
2215                 gl_label_object_flip_vert (object);
2216         }
2217
2218         gl_debug (DEBUG_VIEW, "END");
2219 }
2220
2221 /*****************************************************************************/
2222 /* Align selected objects to left most edge.                                 */
2223 /*****************************************************************************/
2224 void
2225 gl_view_align_selection_left (glView *view)
2226 {
2227         GList         *p;
2228         glViewObject  *view_object;
2229         glLabelObject *object;
2230         gdouble        dx, x1min, x1, y1, x2, y2;
2231
2232         gl_debug (DEBUG_VIEW, "START");
2233
2234         g_return_if_fail (view && GL_IS_VIEW (view));
2235
2236         g_return_if_fail (!gl_view_is_selection_empty (view) &&
2237                           !gl_view_is_selection_atomic (view));
2238
2239         /* find left most edge */
2240         p = view->selected_object_list;
2241         view_object = GL_VIEW_OBJECT (p->data);
2242         object = gl_view_object_get_object (view_object);
2243         gl_label_object_get_extent (object, &x1min, &y1, &x2, &y2);
2244         for (p = p->next; p != NULL; p = p->next) {
2245                 view_object = GL_VIEW_OBJECT (p->data);
2246                 object = gl_view_object_get_object (view_object);
2247                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2248                 if ( x1 < x1min ) x1min = x1;
2249         }
2250
2251         /* now adjust the object positions to line up the left edges */
2252         for (p = view->selected_object_list; p != NULL; p = p->next) {
2253                 view_object = GL_VIEW_OBJECT (p->data);
2254                 object = gl_view_object_get_object (view_object);
2255                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2256                 dx = x1min - x1;
2257                 gl_label_object_set_position_relative (object, dx, 0.0);
2258         }
2259
2260         gl_debug (DEBUG_VIEW, "END");
2261 }
2262
2263
2264 /*****************************************************************************/
2265 /* Align selected objects to right most edge.                                */
2266 /*****************************************************************************/
2267 void
2268 gl_view_align_selection_right (glView *view)
2269 {
2270         GList         *p;
2271         glViewObject  *view_object;
2272         glLabelObject *object;
2273         gdouble        dx, x2max, x1, y1, x2, y2;
2274
2275         gl_debug (DEBUG_VIEW, "START");
2276
2277         g_return_if_fail (view && GL_IS_VIEW (view));
2278
2279         g_return_if_fail (!gl_view_is_selection_empty (view) &&
2280                           !gl_view_is_selection_atomic (view));
2281
2282         /* find right most edge */
2283         p = view->selected_object_list;
2284         view_object = GL_VIEW_OBJECT (p->data);
2285         object = gl_view_object_get_object (view_object);
2286         gl_label_object_get_extent (object, &x1, &y1, &x2max, &y2);
2287         for (p = p->next; p != NULL; p = p->next) {
2288                 view_object = GL_VIEW_OBJECT (p->data);
2289                 object = gl_view_object_get_object (view_object);
2290                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2291                 if ( x2 > x2max ) x2max = x2;
2292         }
2293
2294         /* now adjust the object positions to line up the right edges */
2295         for (p = view->selected_object_list; p != NULL; p = p->next) {
2296                 view_object = GL_VIEW_OBJECT (p->data);
2297                 object = gl_view_object_get_object (view_object);
2298                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2299                 dx = x2max - x2;
2300                 gl_label_object_set_position_relative (object, dx, 0.0);
2301         }
2302
2303         gl_debug (DEBUG_VIEW, "END");
2304 }
2305
2306 /*****************************************************************************/
2307 /* Align selected objects to horizontal center of objects.                   */
2308 /*****************************************************************************/
2309 void
2310 gl_view_align_selection_hcenter (glView *view)
2311 {
2312         GList         *p;
2313         glViewObject  *view_object;
2314         glLabelObject *object;
2315         gdouble        dx, dxmin, xsum, xavg, xcenter, x1, y1, x2, y2;
2316         gint           n;
2317
2318         gl_debug (DEBUG_VIEW, "START");
2319
2320         g_return_if_fail (view && GL_IS_VIEW (view));
2321
2322         g_return_if_fail (!gl_view_is_selection_empty (view) &&
2323                           !gl_view_is_selection_atomic (view));
2324
2325         /* find average center of objects */
2326         xsum = 0.0;
2327         n = 0;
2328         for (p = view->selected_object_list; p != NULL; p = p->next) {
2329                 view_object = GL_VIEW_OBJECT (p->data);
2330                 object = gl_view_object_get_object (view_object);
2331                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2332                 xsum += (x1 + x2) / 2.0;
2333                 n++;
2334         }
2335         xavg = xsum / n;
2336
2337         /* find center of object closest to average center */
2338         p = view->selected_object_list;
2339         view_object = GL_VIEW_OBJECT (p->data);
2340         object = gl_view_object_get_object (view_object);
2341         gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2342         dxmin = fabs (xavg - (x1 + x2)/2.0);
2343         xcenter = (x1 + x2)/2.0;
2344         for (p = p->next; p != NULL; p = p->next) {
2345                 view_object = GL_VIEW_OBJECT (p->data);
2346                 object = gl_view_object_get_object (view_object);
2347                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2348                 dx = fabs (xavg - (x1 + x2)/2.0);
2349                 if ( dx < dxmin ) {
2350                         dxmin = dx;
2351                         xcenter = (x1 + x2)/2.0;
2352                 }
2353         }
2354
2355         /* now adjust the object positions to line up this center */
2356         for (p = view->selected_object_list; p != NULL; p = p->next) {
2357                 view_object = GL_VIEW_OBJECT (p->data);
2358                 object = gl_view_object_get_object (view_object);
2359                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2360                 dx = xcenter - (x1 + x2)/2.0;
2361                 gl_label_object_set_position_relative (object, dx, 0.0);
2362         }
2363
2364         gl_debug (DEBUG_VIEW, "END");
2365 }
2366
2367 /*****************************************************************************/
2368 /* Align selected objects to top most edge.                                  */
2369 /*****************************************************************************/
2370 void
2371 gl_view_align_selection_top (glView *view)
2372 {
2373         GList         *p;
2374         glViewObject  *view_object;
2375         glLabelObject *object;
2376         gdouble        dy, y1min, x1, y1, x2, y2;
2377
2378         gl_debug (DEBUG_VIEW, "START");
2379
2380         g_return_if_fail (view && GL_IS_VIEW (view));
2381
2382         g_return_if_fail (!gl_view_is_selection_empty (view) &&
2383                           !gl_view_is_selection_atomic (view));
2384
2385         /* find top most edge */
2386         p = view->selected_object_list;
2387         view_object = GL_VIEW_OBJECT (p->data);
2388         object = gl_view_object_get_object (view_object);
2389         gl_label_object_get_extent (object, &x1, &y1min, &x2, &y2);
2390         for (p = p->next; p != NULL; p = p->next) {
2391                 view_object = GL_VIEW_OBJECT (p->data);
2392                 object = gl_view_object_get_object (view_object);
2393                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2394                 if ( y1 < y1min ) y1min = y1;
2395         }
2396
2397         /* now adjust the object positions to line up the top edges */
2398         for (p = view->selected_object_list; p != NULL; p = p->next) {
2399                 view_object = GL_VIEW_OBJECT (p->data);
2400                 object = gl_view_object_get_object (view_object);
2401                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2402                 dy = y1min - y1;
2403                 gl_label_object_set_position_relative (object, 0.0, dy);
2404         }
2405
2406         gl_debug (DEBUG_VIEW, "END");
2407 }
2408
2409 /*****************************************************************************/
2410 /* Align selected objects to bottom most edge.                               */
2411 /*****************************************************************************/
2412 void
2413 gl_view_align_selection_bottom (glView *view)
2414 {
2415         GList         *p;
2416         glViewObject  *view_object;
2417         glLabelObject *object;
2418         gdouble        dy, y2max, x1, y1, x2, y2;
2419
2420         gl_debug (DEBUG_VIEW, "START");
2421
2422         g_return_if_fail (view && GL_IS_VIEW (view));
2423
2424         g_return_if_fail (!gl_view_is_selection_empty (view) &&
2425                           !gl_view_is_selection_atomic (view));
2426
2427         /* find bottom most edge */
2428         p = view->selected_object_list;
2429         view_object = GL_VIEW_OBJECT (p->data);
2430         object = gl_view_object_get_object (view_object);
2431         gl_label_object_get_extent (object, &x1, &y1, &x2, &y2max);
2432         for (p = p->next; p != NULL; p = p->next) {
2433                 view_object = GL_VIEW_OBJECT (p->data);
2434                 object = gl_view_object_get_object (view_object);
2435                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2436                 if ( y2 > y2max ) y2max = y2;
2437         }
2438
2439         /* now adjust the object positions to line up the bottom edges */
2440         for (p = view->selected_object_list; p != NULL; p = p->next) {
2441                 view_object = GL_VIEW_OBJECT (p->data);
2442                 object = gl_view_object_get_object (view_object);
2443                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2444                 dy = y2max - y2;
2445                 gl_label_object_set_position_relative (object, 0.0, dy);
2446         }
2447
2448         gl_debug (DEBUG_VIEW, "END");
2449 }
2450
2451 /*****************************************************************************/
2452 /* Align selected objects to viertical center of objects.                    */
2453 /*****************************************************************************/
2454 void
2455 gl_view_align_selection_vcenter (glView *view)
2456 {
2457         GList         *p;
2458         glViewObject  *view_object;
2459         glLabelObject *object;
2460         gdouble        dy, dymin, ysum, yavg, ycenter, x1, y1, x2, y2;
2461         gint           n;
2462
2463         gl_debug (DEBUG_VIEW, "START");
2464
2465         g_return_if_fail (view && GL_IS_VIEW (view));
2466
2467         g_return_if_fail (!gl_view_is_selection_empty (view) &&
2468                           !gl_view_is_selection_atomic (view));
2469
2470         /* find average center of objects */
2471         ysum = 0.0;
2472         n = 0;
2473         for (p = view->selected_object_list; p != NULL; p = p->next) {
2474                 view_object = GL_VIEW_OBJECT (p->data);
2475                 object = gl_view_object_get_object (view_object);
2476                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2477                 ysum += (y1 + y2) / 2.0;
2478                 n++;
2479         }
2480         yavg = ysum / n;
2481
2482         /* find center of object closest to average center */
2483         p = view->selected_object_list;
2484         view_object = GL_VIEW_OBJECT (p->data);
2485         object = gl_view_object_get_object (view_object);
2486         gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2487         dymin = fabs (yavg - (y1 + y2)/2.0);
2488         ycenter = (y1 + y2)/2.0;
2489         for (p = p->next; p != NULL; p = p->next) {
2490                 view_object = GL_VIEW_OBJECT (p->data);
2491                 object = gl_view_object_get_object (view_object);
2492                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2493                 dy = fabs (yavg - (y1 + y2)/2.0);
2494                 if ( dy < dymin ) {
2495                         dymin = dy;
2496                         ycenter = (y1 + y2)/2.0;
2497                 }
2498         }
2499
2500         /* now adjust the object positions to line up this center */
2501         for (p = view->selected_object_list; p != NULL; p = p->next) {
2502                 view_object = GL_VIEW_OBJECT (p->data);
2503                 object = gl_view_object_get_object (view_object);
2504                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2505                 dy = ycenter - (y1 + y2)/2.0;
2506                 gl_label_object_set_position_relative (object, 0.0, dy);
2507         }
2508
2509         gl_debug (DEBUG_VIEW, "END");
2510 }
2511
2512 /*****************************************************************************/
2513 /* Center selected objects to in center of label.                            */
2514 /*****************************************************************************/
2515 void
2516 gl_view_center_selection_horiz (glView *view)
2517 {
2518         GList         *p;
2519         glViewObject  *view_object;
2520         glLabelObject *object;
2521         gdouble        dx, x_label_center, x_obj_center, x1, y1, x2, y2, w, h;
2522
2523         gl_debug (DEBUG_VIEW, "START");
2524
2525         g_return_if_fail (view && GL_IS_VIEW (view));
2526
2527         g_return_if_fail (!gl_view_is_selection_empty (view));
2528
2529         gl_label_get_size (view->label, &w, &h);
2530         x_label_center = w / 2.0;
2531
2532         /* adjust the object positions */
2533         for (p = view->selected_object_list; p != NULL; p = p->next) {
2534                 view_object = GL_VIEW_OBJECT (p->data);
2535                 object = gl_view_object_get_object (view_object);
2536                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2537                 x_obj_center = (x1 + x2) / 2.0;
2538                 dx = x_label_center - x_obj_center;
2539                 gl_label_object_set_position_relative (object, dx, 0.0);
2540         }
2541
2542         gl_debug (DEBUG_VIEW, "END");
2543 }
2544
2545
2546 /*****************************************************************************/
2547 /* Center selected objects to in center of label.                            */
2548 /*****************************************************************************/
2549 void
2550 gl_view_center_selection_vert (glView *view)
2551 {
2552         GList         *p;
2553         glViewObject  *view_object;
2554         glLabelObject *object;
2555         gdouble        dy, y_label_center, y_obj_center, x1, y1, x2, y2, w, h;
2556
2557         gl_debug (DEBUG_VIEW, "START");
2558
2559         g_return_if_fail (view && GL_IS_VIEW (view));
2560
2561         g_return_if_fail (!gl_view_is_selection_empty (view));
2562
2563         gl_label_get_size (view->label, &w, &h);
2564         y_label_center = h / 2.0;
2565
2566         /* adjust the object positions */
2567         for (p = view->selected_object_list; p != NULL; p = p->next) {
2568                 view_object = GL_VIEW_OBJECT (p->data);
2569                 object = gl_view_object_get_object (view_object);
2570                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2571                 y_obj_center = (y1 + y2) / 2.0;
2572                 dy = y_label_center - y_obj_center;
2573                 gl_label_object_set_position_relative (object, 0.0, dy);
2574         }
2575
2576         gl_debug (DEBUG_VIEW, "END");
2577 }
2578
2579
2580 /*****************************************************************************/
2581 /* Move selected objects                                                     */
2582 /*****************************************************************************/
2583 void
2584 gl_view_move_selection (glView  *view,
2585                 gdouble  dx,
2586                 gdouble  dy)
2587 {
2588         GList *p;
2589         glLabelObject *object;
2590
2591         gl_debug (DEBUG_VIEW, "START");
2592
2593         g_return_if_fail (view && GL_IS_VIEW (view));
2594
2595         for (p = view->selected_object_list; p != NULL; p = p->next) {
2596
2597                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2598                 gl_label_object_set_position_relative (object, dx, dy);
2599
2600         }
2601
2602         gl_debug (DEBUG_VIEW, "END");
2603 }
2604
2605 /*****************************************************************************/
2606 /* Can text properties be set for selection?                                 */
2607 /*****************************************************************************/
2608 gboolean
2609 gl_view_can_selection_text (glView            *view)
2610 {
2611         GList *p;
2612         glLabelObject *object;
2613
2614         gl_debug (DEBUG_VIEW, "");
2615
2616         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
2617
2618         for (p = view->selected_object_list; p != NULL; p = p->next) {
2619
2620                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2621                 if (gl_label_object_can_text (object)) {
2622                         return TRUE;
2623                 }
2624
2625         }
2626
2627         return FALSE;
2628 }
2629
2630 /*****************************************************************************/
2631 /* Set font family for all text contained in selected objects.               */
2632 /*****************************************************************************/
2633 void
2634 gl_view_set_selection_font_family (glView            *view,
2635                                    const gchar       *font_family)
2636 {
2637         GList *p;
2638         glLabelObject *object;
2639
2640         gl_debug (DEBUG_VIEW, "START");
2641
2642         g_return_if_fail (view && GL_IS_VIEW (view));
2643
2644         for (p = view->selected_object_list; p != NULL; p = p->next) {
2645
2646                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2647                 gl_label_object_set_font_family (object, font_family);
2648
2649         }
2650
2651         gl_debug (DEBUG_VIEW, "END");
2652 }
2653
2654 /*****************************************************************************/
2655 /* Set font size for all text contained in selected objects.                 */
2656 /*****************************************************************************/
2657 void
2658 gl_view_set_selection_font_size (glView            *view,
2659                                  gdouble            font_size)
2660 {
2661         GList *p;
2662         glLabelObject *object;
2663
2664         gl_debug (DEBUG_VIEW, "START");
2665
2666         g_return_if_fail (view && GL_IS_VIEW (view));
2667
2668         for (p = view->selected_object_list; p != NULL; p = p->next) {
2669
2670                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2671                 gl_label_object_set_font_size (object, font_size);
2672
2673         }
2674
2675         gl_debug (DEBUG_VIEW, "END");
2676 }
2677
2678 /*****************************************************************************/
2679 /* Set font weight for all text contained in selected objects.               */
2680 /*****************************************************************************/
2681 void
2682 gl_view_set_selection_font_weight (glView            *view,
2683                                    GnomeFontWeight    font_weight)
2684 {
2685         GList *p;
2686         glLabelObject *object;
2687
2688         gl_debug (DEBUG_VIEW, "START");
2689
2690         g_return_if_fail (view && GL_IS_VIEW (view));
2691
2692         for (p = view->selected_object_list; p != NULL; p = p->next) {
2693
2694                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2695                 gl_label_object_set_font_weight (object, font_weight);
2696
2697         }
2698
2699         gl_debug (DEBUG_VIEW, "END");
2700 }
2701
2702 /*****************************************************************************/
2703 /* Set font italic flag for all text contained in selected objects.          */
2704 /*****************************************************************************/
2705 void
2706 gl_view_set_selection_font_italic_flag (glView            *view,
2707                                         gboolean           font_italic_flag)
2708 {
2709         GList *p;
2710         glLabelObject *object;
2711
2712         gl_debug (DEBUG_VIEW, "START");
2713
2714         g_return_if_fail (view && GL_IS_VIEW (view));
2715
2716         for (p = view->selected_object_list; p != NULL; p = p->next) {
2717
2718                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2719                 gl_label_object_set_font_italic_flag (object, font_italic_flag);
2720
2721         }
2722
2723         gl_debug (DEBUG_VIEW, "END");
2724 }
2725
2726 /*****************************************************************************/
2727 /* Set text alignment for all text contained in selected objects.            */
2728 /*****************************************************************************/
2729 void
2730 gl_view_set_selection_text_alignment (glView            *view,
2731                                       GtkJustification   text_alignment)
2732 {
2733         GList *p;
2734         glLabelObject *object;
2735
2736         gl_debug (DEBUG_VIEW, "START");
2737
2738         g_return_if_fail (view && GL_IS_VIEW (view));
2739
2740         for (p = view->selected_object_list; p != NULL; p = p->next) {
2741
2742                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2743                 gl_label_object_set_text_alignment (object, text_alignment);
2744
2745         }
2746
2747         gl_debug (DEBUG_VIEW, "END");
2748 }
2749
2750 /*****************************************************************************/
2751 /* Set text color for all text contained in selected objects.                */
2752 /*****************************************************************************/
2753 void
2754 gl_view_set_selection_text_color (glView            *view,
2755                                   guint              text_color)
2756 {
2757         GList *p;
2758         glLabelObject *object;
2759
2760         gl_debug (DEBUG_VIEW, "START");
2761
2762         g_return_if_fail (view && GL_IS_VIEW (view));
2763
2764         for (p = view->selected_object_list; p != NULL; p = p->next) {
2765
2766                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2767                 gl_label_object_set_text_color (object, text_color);
2768
2769         }
2770
2771         gl_debug (DEBUG_VIEW, "END");
2772 }
2773
2774 /*****************************************************************************/
2775 /* Can fill properties be set for selection?                                 */
2776 /*****************************************************************************/
2777 gboolean
2778 gl_view_can_selection_fill (glView            *view)
2779 {
2780         GList *p;
2781         glLabelObject *object;
2782
2783         gl_debug (DEBUG_VIEW, "");
2784
2785         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
2786
2787         for (p = view->selected_object_list; p != NULL; p = p->next) {
2788
2789                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2790                 if (gl_label_object_can_fill (object)) {
2791                         return TRUE;
2792                 }
2793
2794         }
2795
2796         return FALSE;
2797 }
2798
2799 /*****************************************************************************/
2800 /* Set fill color for all selected objects.                                  */
2801 /*****************************************************************************/
2802 void
2803 gl_view_set_selection_fill_color (glView            *view,
2804                                   guint              fill_color)
2805 {
2806         GList *p;
2807         glLabelObject *object;
2808
2809         gl_debug (DEBUG_VIEW, "START");
2810
2811         g_return_if_fail (view && GL_IS_VIEW (view));
2812
2813         for (p = view->selected_object_list; p != NULL; p = p->next) {
2814
2815                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2816                 gl_label_object_set_fill_color (object, fill_color);
2817
2818         }
2819
2820         gl_debug (DEBUG_VIEW, "END");
2821 }
2822
2823 /*****************************************************************************/
2824 /* Can line color properties be set for selection?                           */
2825 /*****************************************************************************/
2826 gboolean
2827 gl_view_can_selection_line_color (glView            *view)
2828 {
2829         GList *p;
2830         glLabelObject *object;
2831
2832         gl_debug (DEBUG_VIEW, "");
2833
2834         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
2835
2836         for (p = view->selected_object_list; p != NULL; p = p->next) {
2837
2838                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2839                 if (gl_label_object_can_line_color (object)) {
2840                         return TRUE;
2841                 }
2842
2843         }
2844
2845         return FALSE;
2846 }
2847
2848 /*****************************************************************************/
2849 /* Set line color for all selected objects.                                  */
2850 /*****************************************************************************/
2851 void
2852 gl_view_set_selection_line_color (glView            *view,
2853                                   guint              line_color)
2854 {
2855         GList *p;
2856         glLabelObject *object;
2857
2858         gl_debug (DEBUG_VIEW, "START");
2859
2860         g_return_if_fail (view && GL_IS_VIEW (view));
2861
2862         for (p = view->selected_object_list; p != NULL; p = p->next) {
2863
2864                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2865                 gl_label_object_set_line_color (object, line_color);
2866
2867         }
2868
2869         gl_debug (DEBUG_VIEW, "END");
2870 }
2871
2872 /*****************************************************************************/
2873 /* Can line width properties be set for selection?                           */
2874 /*****************************************************************************/
2875 gboolean
2876 gl_view_can_selection_line_width (glView            *view)
2877 {
2878         GList *p;
2879         glLabelObject *object;
2880
2881         gl_debug (DEBUG_VIEW, "");
2882
2883         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
2884
2885         for (p = view->selected_object_list; p != NULL; p = p->next) {
2886
2887                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2888                 if (gl_label_object_can_line_width (object)) {
2889                         return TRUE;
2890                 }
2891
2892         }
2893
2894         return FALSE;
2895 }
2896
2897 /*****************************************************************************/
2898 /* Set line width for all selected objects.                                  */
2899 /*****************************************************************************/
2900 void
2901 gl_view_set_selection_line_width (glView            *view,
2902                                   gdouble            line_width)
2903 {
2904         GList *p;
2905         glLabelObject *object;
2906
2907         gl_debug (DEBUG_VIEW, "START");
2908
2909         g_return_if_fail (view && GL_IS_VIEW (view));
2910
2911         for (p = view->selected_object_list; p != NULL; p = p->next) {
2912
2913                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2914                 gl_label_object_set_line_width (object, line_width);
2915
2916         }
2917
2918         gl_debug (DEBUG_VIEW, "END");
2919 }
2920
2921 /*****************************************************************************/
2922 /* "Cut" selected items and place in clipboard selections.                   */
2923 /*****************************************************************************/
2924 void
2925 gl_view_cut (glView *view)
2926 {
2927         gl_debug (DEBUG_VIEW, "START");
2928
2929         g_return_if_fail (view && GL_IS_VIEW (view));
2930
2931         gl_view_copy (view);
2932         gl_view_delete_selection (view);
2933
2934         gl_debug (DEBUG_VIEW, "END");
2935 }
2936
2937 /*****************************************************************************/
2938 /* "Copy" selected items to clipboard selections.                            */
2939 /*****************************************************************************/
2940 void
2941 gl_view_copy (glView *view)
2942 {
2943         GList *p;
2944         glViewObject *view_object;
2945         glLabelObject *object;
2946         glTemplate *template;
2947         gboolean rotate_flag;
2948
2949         gl_debug (DEBUG_VIEW, "START");
2950
2951         g_return_if_fail (view && GL_IS_VIEW (view));
2952
2953         if (view->selected_object_list) {
2954
2955                 if ( view->selection_data ) {
2956                         g_object_unref (view->selection_data);
2957                 }
2958                 template = gl_label_get_template (view->label);
2959                 rotate_flag = gl_label_get_rotate_flag (view->label);
2960                 view->selection_data = GL_LABEL(gl_label_new ());
2961                 gl_label_set_template (view->selection_data, template);
2962                 gl_label_set_rotate_flag (view->selection_data, rotate_flag);
2963                 gl_template_free (&template);
2964
2965                 for (p = view->selected_object_list; p != NULL; p = p->next) {
2966
2967                         view_object = GL_VIEW_OBJECT (p->data);
2968                         object = gl_view_object_get_object (view_object);
2969
2970                         gl_label_object_dup (object, view->selection_data);
2971
2972                 }
2973
2974                 gtk_selection_owner_set (view->invisible,
2975                                          clipboard_atom, GDK_CURRENT_TIME);
2976                 view->have_selection = TRUE;
2977
2978         }
2979
2980         gl_debug (DEBUG_VIEW, "END");
2981 }
2982
2983 /*****************************************************************************/
2984 /* "Paste" from private clipboard selection.                                 */
2985 /*****************************************************************************/
2986 void
2987 gl_view_paste (glView *view)
2988 {
2989         gl_debug (DEBUG_VIEW, "START");
2990
2991         g_return_if_fail (view && GL_IS_VIEW (view));
2992
2993         gtk_selection_convert (GTK_WIDGET (view->invisible),
2994                                clipboard_atom, GDK_SELECTION_TYPE_STRING,
2995                                GDK_CURRENT_TIME);
2996
2997         gl_debug (DEBUG_VIEW, "END");
2998 }
2999
3000 /*****************************************************************************/
3001 /* Zoom in one "notch"                                                       */
3002 /*****************************************************************************/
3003 void
3004 gl_view_zoom_in (glView *view)
3005 {
3006         gint i, i_min;
3007         gdouble dist, dist_min;
3008
3009         gl_debug (DEBUG_VIEW, "START");
3010
3011         g_return_if_fail (view && GL_IS_VIEW (view));
3012
3013         /* Find index of current scale (or best match) */
3014         i_min = 1;              /* start with 2nd largest scale */
3015         dist_min = fabs (zooms[1] - view->zoom);
3016         for (i = 2; i < N_ZOOMS; i++) {
3017                 dist = fabs (zooms[i] - view->zoom);
3018                 if (dist < dist_min) {
3019                         i_min = i;
3020                         dist_min = dist;
3021                 }
3022         }
3023
3024         /* zoom in one "notch" */
3025         i = MAX (0, i_min - 1);
3026         gl_debug (DEBUG_VIEW, "zoom[%d] = %g", i, zooms[i]);
3027         set_zoom_real (view, zooms[i], FALSE);
3028
3029         gl_debug (DEBUG_VIEW, "END");
3030 }
3031
3032 /*****************************************************************************/
3033 /* Zoom out one "notch"                                                      */
3034 /*****************************************************************************/
3035 void
3036 gl_view_zoom_out (glView *view)
3037 {
3038         gint i, i_min;
3039         gdouble dist, dist_min;
3040
3041         gl_debug (DEBUG_VIEW, "START");
3042
3043         g_return_if_fail (view && GL_IS_VIEW (view));
3044
3045         /* Find index of current scale (or best match) */
3046         i_min = 0;              /* start with largest scale */
3047         dist_min = fabs (zooms[0] - view->zoom);
3048         for (i = 1; i < N_ZOOMS; i++) {
3049                 dist = fabs (zooms[i] - view->zoom);
3050                 if (dist < dist_min) {
3051                         i_min = i;
3052                         dist_min = dist;
3053                 }
3054         }
3055
3056         /* zoom out one "notch" */
3057         if (i_min >= N_ZOOMS)
3058                 return;
3059         i = i_min + 1;
3060         if (i >= N_ZOOMS)
3061                 return;
3062         set_zoom_real (view, zooms[i], FALSE);
3063
3064         gl_debug (DEBUG_VIEW, "END");
3065 }
3066
3067 /*****************************************************************************/
3068 /* Set zoom to best fit.                                                     */
3069 /*****************************************************************************/
3070 void
3071 gl_view_zoom_to_fit (glView *view)
3072 {
3073         gint w_view, h_view;
3074         gdouble w_label, h_label;
3075         gdouble x_scale, y_scale, scale;
3076
3077         gl_debug (DEBUG_VIEW, "");
3078
3079         if ( ! GTK_WIDGET_VISIBLE(view)) {
3080                 set_zoom_real (view, 1.0, TRUE);
3081                 return;
3082         }
3083
3084         w_view = GTK_WIDGET(view)->allocation.width;
3085         h_view = GTK_WIDGET(view)->allocation.height;
3086
3087         gl_label_get_size (GL_LABEL(view->label), &w_label, &h_label);
3088
3089         gl_debug (DEBUG_VIEW, "View size: %d, %d", w_view, h_view);
3090         gl_debug (DEBUG_VIEW, "Label size: %g, %g", w_label, h_label);
3091
3092         /* Calculate best scale */
3093         x_scale = (double)(w_view - ZOOMTOFIT_PAD) / w_label;
3094         y_scale = (double)(h_view - ZOOMTOFIT_PAD) / h_label;
3095         scale = MIN (x_scale, y_scale);
3096         gl_debug (DEBUG_VIEW, "Candidate zooms: %g, %g => %g", x_scale, y_scale, scale);
3097
3098         /* Limit */
3099         gl_debug (DEBUG_VIEW, "Scale: %g", scale);
3100         scale = MIN (scale, zooms[0]*view->home_scale);
3101         scale = MAX (scale, zooms[N_ZOOMS-1]*view->home_scale);
3102         gl_debug (DEBUG_VIEW, "Limitted scale: %g", scale);
3103
3104         set_zoom_real (view, scale/view->home_scale, TRUE);
3105 }
3106
3107 /*****************************************************************************/
3108 /* Set current zoom factor to explicit value.                                */
3109 /*****************************************************************************/
3110 void
3111 gl_view_set_zoom (glView  *view,
3112                   gdouble zoom)
3113 {
3114         gl_debug (DEBUG_VIEW, "START");
3115
3116         set_zoom_real (view, zoom, FALSE);
3117
3118         gl_debug (DEBUG_VIEW, "END");
3119 }
3120
3121 /*---------------------------------------------------------------------------*/
3122 /* PRIVATE.  Set canvas scale.                                               *
3123 /*---------------------------------------------------------------------------*/
3124 static void
3125 set_zoom_real (glView          *view,
3126                gdouble          zoom,
3127                gboolean         zoom_to_fit_flag)
3128 {
3129         gl_debug (DEBUG_VIEW, "START");
3130
3131         g_return_if_fail (view && GL_IS_VIEW (view));
3132         g_return_if_fail (zoom > 0.0);
3133
3134         /* Limit, if needed */
3135         gl_debug (DEBUG_VIEW, "Zoom requested: %g", zoom);
3136         zoom = MIN (zoom, zooms[0]);
3137         zoom = MAX (zoom, zooms[N_ZOOMS-1]);
3138         gl_debug (DEBUG_VIEW, "Limitted zoom: %g", zoom);
3139
3140         if ( zoom != view->zoom ) {
3141
3142                 view->zoom = zoom;
3143                 view->zoom_to_fit_flag = zoom_to_fit_flag;
3144                 gnome_canvas_set_pixels_per_unit (GNOME_CANVAS (view->canvas),
3145                                                   zoom*view->home_scale);
3146
3147                 g_signal_emit (G_OBJECT(view), signals[ZOOM_CHANGED], 0, zoom);
3148
3149         }
3150
3151         gl_debug (DEBUG_VIEW, "END");
3152
3153 }
3154
3155
3156 /*---------------------------------------------------------------------------*/
3157 /* PRIVATE. Size allocation changed callback.                                */
3158 /*---------------------------------------------------------------------------*/
3159 static void
3160 size_allocate_cb (glView          *view)
3161 {
3162         gl_debug (DEBUG_VIEW, "START");
3163
3164         if (view->zoom_to_fit_flag) {
3165                 /* Maintain best fit zoom */
3166                 gl_view_zoom_to_fit (view);
3167         }
3168
3169         gl_debug (DEBUG_VIEW, "END");
3170 }
3171
3172
3173
3174 /*---------------------------------------------------------------------------*/
3175 /* PRIVATE. Screen changed callback.                                         */
3176 /*---------------------------------------------------------------------------*/
3177 static void
3178 screen_changed_cb (glView          *view)
3179 {
3180         gl_debug (DEBUG_VIEW, "START");
3181
3182         view->home_scale = get_home_scale (view);
3183
3184         gnome_canvas_set_pixels_per_unit (GNOME_CANVAS (view->canvas),
3185                                           view->zoom * view->home_scale);
3186
3187         if (view->zoom_to_fit_flag) {
3188                 /* Maintain best fit zoom */
3189                 gl_view_zoom_to_fit (view);
3190         }
3191
3192         gl_debug (DEBUG_VIEW, "END");
3193 }
3194
3195
3196
3197 /*****************************************************************************/
3198 /* Get current zoom factor.                                                  */
3199 /*****************************************************************************/
3200 gdouble
3201 gl_view_get_zoom (glView *view)
3202 {
3203         gl_debug (DEBUG_VIEW, "");
3204
3205         g_return_val_if_fail (view && GL_IS_VIEW (view), 1.0);
3206
3207         return view->zoom;
3208 }
3209
3210 /*****************************************************************************/
3211 /* Is this the maximum zoom level.                                           */
3212 /*****************************************************************************/
3213 gboolean
3214 gl_view_is_zoom_max (glView *view)
3215 {
3216         gl_debug (DEBUG_VIEW, "");
3217
3218         g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
3219
3220         return view->zoom >= zooms[0];
3221 }
3222
3223 /*****************************************************************************/
3224 /* Is this the minimum zoom level.                                           */
3225 /*****************************************************************************/
3226 gboolean
3227 gl_view_is_zoom_min (glView *view)
3228 {
3229         gl_debug (DEBUG_VIEW, "");
3230
3231         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
3232
3233         return view->zoom <= zooms[N_ZOOMS-1];
3234 }
3235
3236 /*****************************************************************************/
3237 /* Launch merge properties dialog.                                           */
3238 /*****************************************************************************/
3239 void
3240 gl_view_edit_merge_props (glView *view)
3241 {
3242         gl_debug (DEBUG_VIEW, "");
3243
3244         g_return_if_fail (view && GL_IS_VIEW (view));
3245
3246         if (view->merge_props_dialog != NULL) {
3247                 gtk_widget_show_all (view->merge_props_dialog);
3248                 gtk_window_present (GTK_WINDOW(view->merge_props_dialog));
3249                 return;
3250         }
3251
3252         view->merge_props_dialog = gl_merge_properties_dialog_new (view);
3253         gtk_widget_show_all (view->merge_props_dialog);
3254
3255         g_signal_connect (G_OBJECT(view->merge_props_dialog), "destroy",
3256                           G_CALLBACK (gtk_widget_destroyed),
3257                           &view->merge_props_dialog);
3258 }
3259
3260 /*---------------------------------------------------------------------------*/
3261 /* PRIVATE.  Canvas event handler.                                           */
3262 /*---------------------------------------------------------------------------*/
3263 static int
3264 canvas_event (GnomeCanvas *canvas,
3265               GdkEvent    *event,
3266               glView      *view)
3267 {
3268         gdouble x, y;
3269
3270         gl_debug (DEBUG_VIEW, "");
3271
3272         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
3273
3274         /* emit pointer signals regardless of state */
3275         switch (event->type) {
3276         case GDK_MOTION_NOTIFY:
3277                 gl_debug (DEBUG_VIEW, "MOTION_NOTIFY");
3278                 gnome_canvas_window_to_world (canvas,
3279                                               event->motion.x,
3280                                               event->motion.y, &x, &y);
3281                 g_signal_emit (G_OBJECT(view), signals[POINTER_MOVED], 0, x, y);
3282                 break; /* fall through */
3283
3284         case GDK_LEAVE_NOTIFY:
3285                 gl_debug (DEBUG_VIEW, "LEAVEW_NOTIFY");
3286                 g_signal_emit (G_OBJECT(view), signals[POINTER_EXIT], 0);
3287                 break; /* fall through */
3288
3289         default:
3290                 break; /* fall through */
3291         }
3292
3293
3294         switch (view->state) {
3295
3296         case GL_VIEW_STATE_ARROW:
3297                 return canvas_event_arrow_mode (canvas, event, view);
3298
3299         case GL_VIEW_STATE_OBJECT_CREATE:
3300                 switch (view->create_type) {
3301                 case GL_LABEL_OBJECT_BOX:
3302                         return gl_view_box_create_event_handler (canvas,
3303                                                                  event,
3304                                                                  view);
3305                         break;
3306                 case GL_LABEL_OBJECT_ELLIPSE:
3307                         return gl_view_ellipse_create_event_handler (canvas,
3308                                                                      event,
3309                                                                      view);
3310                         break;
3311                 case GL_LABEL_OBJECT_LINE:
3312                         return gl_view_line_create_event_handler (canvas,
3313                                                                   event,
3314                                                                   view);
3315                         break;
3316                 case GL_LABEL_OBJECT_IMAGE:
3317                         return gl_view_image_create_event_handler (canvas,
3318                                                                    event,
3319                                                                    view);
3320                         break;
3321                 case GL_LABEL_OBJECT_TEXT:
3322                         return gl_view_text_create_event_handler (canvas,
3323                                                                   event,
3324                                                                   view);
3325                         break;
3326                 case GL_LABEL_OBJECT_BARCODE:
3327                         return gl_view_barcode_create_event_handler (canvas,
3328                                                                      event,
3329                                                                      view);
3330                         break;
3331                 default:
3332                         /*Should not happen!*/
3333                         g_warning ("Invalid label object type.");
3334                         return FALSE;
3335         }
3336
3337         default:
3338                 g_warning ("Invalid view state.");      /*Should not happen!*/
3339                 return FALSE;
3340
3341         }
3342 }
3343
3344 /*---------------------------------------------------------------------------*/
3345 /* PRIVATE.  Canvas event handler (arrow mode)                               */
3346 /*---------------------------------------------------------------------------*/
3347 static int
3348 canvas_event_arrow_mode (GnomeCanvas *canvas,
3349                          GdkEvent    *event,
3350                          glView      *view)
3351 {
3352         static gdouble x0, y0;
3353         static gboolean dragging = FALSE;
3354         static GnomeCanvasItem *item;
3355         gdouble x, y, x1, y1, x2, y2;
3356         GnomeCanvasGroup *group;
3357         GdkCursor *cursor;
3358
3359         gl_debug (DEBUG_VIEW, "");
3360
3361         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
3362
3363         switch (event->type) {
3364
3365         case GDK_BUTTON_PRESS:
3366                 gl_debug (DEBUG_VIEW, "BUTTON_PRESS");
3367                 gtk_widget_grab_focus (GTK_WIDGET(canvas));
3368                 switch (event->button.button) {
3369                 case 1:
3370                         gnome_canvas_window_to_world (canvas,
3371                                                       event->button.x,
3372                                                       event->button.y, &x, &y);
3373
3374                         if (!object_at (view, x, y)) {
3375                                 if (!(event->button.state & GDK_CONTROL_MASK)) {
3376                                         gl_view_unselect_all (view);
3377                                 }
3378
3379                                 dragging = TRUE;
3380                                 gnome_canvas_item_grab (canvas->root,
3381                                                         GDK_POINTER_MOTION_MASK |
3382                                                         GDK_BUTTON_RELEASE_MASK |
3383                                                         GDK_BUTTON_PRESS_MASK,
3384                                                         NULL, event->button.time);
3385                                 group =
3386                                     gnome_canvas_root (GNOME_CANVAS
3387                                                        (view->canvas));
3388                                 item =
3389                                     gnome_canvas_item_new (group,
3390                                                            gnome_canvas_rect_get_type (),
3391                                                            "x1", x-DELTA,
3392                                                            "y1", y-DELTA,
3393                                                            "x2", x+DELTA,
3394                                                            "y2", y+DELTA,
3395                                                            "width_pixels", 2,
3396                                                            "outline_color_rgba",
3397                                                            SEL_LINE_COLOR,
3398                                                            "fill_color_rgba",
3399                                                            SEL_FILL_COLOR,
3400                                                            NULL);
3401                                 x0 = x;
3402                                 y0 = y;
3403
3404                         }
3405                         return FALSE;
3406                 case 3:
3407                         gnome_canvas_window_to_world (canvas,
3408                                                       event->button.x,
3409                                                       event->button.y, &x, &y);
3410
3411                         if (!object_at (view, x, y)) {
3412                                 /* bring up apropriate menu for selection. */
3413                                 gl_view_popup_menu (view, event);
3414                         }
3415                         return FALSE;
3416                 default:
3417                         return FALSE;
3418                 }
3419
3420         case GDK_BUTTON_RELEASE:
3421                 gl_debug (DEBUG_VIEW, "BUTTON_RELEASE");
3422                 switch (event->button.button) {
3423                 case 1:
3424                         if (dragging) {
3425                                 dragging = FALSE;
3426                                 gnome_canvas_item_ungrab (canvas->root,
3427                                                           event->button.time);
3428                                 gnome_canvas_window_to_world (canvas,
3429                                                               event->button.x,
3430                                                               event->button.y,
3431                                                               &x, &y);
3432                                 x1 = MIN (x, x0);
3433                                 y1 = MIN (y, y0);
3434                                 x2 = MAX (x, x0);
3435                                 y2 = MAX (y, y0);
3436                                 gl_view_select_region (view, x1, y1, x2, y2);
3437                                 gtk_object_destroy (GTK_OBJECT (item));
3438                                 return TRUE;
3439                         }
3440                         return FALSE;
3441
3442                 default:
3443                         return FALSE;
3444                 }
3445
3446         case GDK_MOTION_NOTIFY:
3447                 gl_debug (DEBUG_VIEW, "MOTION_NOTIFY");
3448                 gnome_canvas_window_to_world (canvas,
3449                                               event->motion.x,
3450                                               event->motion.y, &x, &y);
3451                 if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
3452                         gl_debug (DEBUG_VIEW,
3453                                   "Dragging: (x0=%g, y0=%g), (x=%g, y=%g)", x0, y0, x, y);
3454                         gnome_canvas_item_set (item,
3455                                                "x1", MIN (x, x0) - DELTA,
3456                                                "y1", MIN (y, y0) - DELTA,
3457                                                "x2", MAX (x, x0) + DELTA,
3458                                                "y2", MAX (y, y0) + DELTA,
3459                                                NULL);
3460                         return TRUE;
3461                 } else {
3462                         return FALSE;
3463                 }
3464
3465         case GDK_KEY_PRESS:
3466                 gl_debug (DEBUG_VIEW, "KEY_PRESS");
3467                 if (!dragging) {
3468                         switch (event->key.keyval) {
3469                         case GDK_Left:
3470                         case GDK_KP_Left:
3471                                 gl_view_move_selection (view,
3472                                                         -1.0 / (view->zoom), 0.0);
3473                                 break;
3474                         case GDK_Up:
3475                         case GDK_KP_Up:
3476                                 gl_view_move_selection (view,
3477                                                         0.0, -1.0 / (view->zoom));
3478                                 break;
3479                         case GDK_Right:
3480                         case GDK_KP_Right:
3481                                 gl_view_move_selection (view,
3482                                                         1.0 / (view->zoom), 0.0);
3483                                 break;
3484                         case GDK_Down:
3485                         case GDK_KP_Down:
3486                                 gl_view_move_selection (view,
3487                                                         0.0, 1.0 / (view->zoom));
3488                                 break;
3489                         case GDK_Delete:
3490                         case GDK_KP_Delete:
3491                                 gl_view_delete_selection (view);
3492                                 cursor = gdk_cursor_new (GDK_LEFT_PTR);
3493                                 gdk_window_set_cursor (view->canvas->window,
3494                                                        cursor);
3495                                 gdk_cursor_unref (cursor);
3496                                 break;
3497                         default:
3498                                 return FALSE;
3499                         }
3500                 }
3501                 return TRUE;    /* We handled this or we were dragging. */
3502
3503         default:
3504                 gl_debug (DEBUG_VIEW, "default");
3505                 return FALSE;
3506         }
3507
3508 }
3509
3510 /*---------------------------------------------------------------------------*/
3511 /* PRIVATE.  create menu for selections.                                     */
3512 /*---------------------------------------------------------------------------*/
3513 void
3514 construct_selection_menu (glView *view)
3515 {
3516         GtkWidget *menu, *menuitem, *submenu;
3517
3518         gl_debug (DEBUG_VIEW, "START");
3519
3520         g_return_if_fail (view && GL_IS_VIEW (view));
3521
3522         menu = gtk_menu_new ();
3523
3524         /*
3525          * Submenu: Order
3526          */
3527         menuitem = gtk_menu_item_new_with_mnemonic (_("_Order"));
3528         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3529         gtk_widget_show (menuitem);
3530         submenu = gtk_menu_new ();
3531         gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
3532
3533         menuitem = gtk_image_menu_item_new_from_stock (GL_STOCK_ORDER_TOP, NULL);
3534         gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menuitem);
3535         gtk_widget_show (menuitem);
3536         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
3537                                   G_CALLBACK (gl_view_raise_selection), view);
3538
3539         menuitem = gtk_image_menu_item_new_from_stock (GL_STOCK_ORDER_BOTTOM, NULL);
3540         gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menuitem);
3541         gtk_widget_show (menuitem);
3542         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
3543                                   G_CALLBACK (gl_view_lower_selection), view);
3544
3545         /*
3546          * Submenu: Rotate/Flip
3547          */
3548         menuitem = gtk_menu_item_new_with_mnemonic (_("_Rotate/Flip"));
3549         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3550         gtk_widget_show (menuitem);
3551         submenu = gtk_menu_new ();
3552         gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
3553
3554         menuitem = gtk_image_menu_item_new_from_stock (GL_STOCK_ROTATE_LEFT, NULL);
3555         gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menuitem);
3556         gtk_widget_show (menuitem);
3557         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
3558                                   G_CALLBACK (gl_view_rotate_selection_left), view);
3559
3560         menuitem = gtk_image_menu_item_new_from_stock (GL_STOCK_ROTATE_RIGHT, NULL);
3561         gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menuitem);
3562         gtk_widget_show (menuitem);
3563         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
3564                                   G_CALLBACK (gl_view_rotate_selection_right), view);
3565
3566         menuitem = gtk_image_menu_item_new_from_stock (GL_STOCK_FLIP_HORIZ, NULL);
3567         gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menuitem);
3568         gtk_widget_show (menuitem);
3569         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
3570                                   G_CALLBACK (gl_view_flip_selection_horiz), view);
3571
3572         menuitem = gtk_image_menu_item_new_from_stock (GL_STOCK_FLIP_VERT, NULL);
3573         gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menuitem);
3574         gtk_widget_show (menuitem);
3575         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
3576                                   G_CALLBACK (gl_view_flip_selection_vert), view);
3577
3578         /*
3579          * Submenu: Align Horizontally
3580          */
3581         menuitem = gtk_menu_item_new_with_mnemonic (_("Align _Horizontally"));
3582         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3583         gtk_widget_show (menuitem);
3584         submenu = gtk_menu_new ();
3585         gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
3586
3587         menuitem = gtk_image_menu_item_new_from_stock (GL_STOCK_ALIGN_LEFT, NULL);
3588         gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menuitem);
3589         gtk_widget_show (menuitem);
3590         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
3591                                   G_CALLBACK (gl_view_align_selection_left), view);
3592         view->multi_selection_items =
3593                 g_list_prepend (view->multi_selection_items, menuitem);
3594
3595         menuitem = gtk_image_menu_item_new_from_stock (GL_STOCK_ALIGN_HCENTER, NULL);
3596         gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menuitem);
3597         gtk_widget_show (menuitem);
3598         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
3599                                   G_CALLBACK (gl_view_align_selection_hcenter), view);
3600         view->multi_selection_items =
3601                 g_list_prepend (view->multi_selection_items, menuitem);
3602
3603         menuitem = gtk_image_menu_item_new_from_stock (GL_STOCK_ALIGN_RIGHT, NULL);
3604         gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menuitem);
3605         gtk_widget_show (menuitem);
3606         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
3607                                   G_CALLBACK (gl_view_align_selection_right), view);
3608         view->multi_selection_items =
3609                 g_list_prepend (view->multi_selection_items, menuitem);
3610
3611         menuitem = gtk_image_menu_item_new_from_stock (GL_STOCK_CENTER_HORIZ, NULL);
3612         gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menuitem);
3613         gtk_widget_show (menuitem);
3614         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
3615                                   G_CALLBACK (gl_view_center_selection_horiz), view);
3616
3617         /*
3618          * Submenu: Align Vertically
3619          */
3620         menuitem = gtk_menu_item_new_with_mnemonic (_("Align _Vertically"));
3621         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3622         gtk_widget_show (menuitem);
3623         submenu = gtk_menu_new ();
3624         gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
3625
3626         menuitem = gtk_image_menu_item_new_from_stock (GL_STOCK_ALIGN_TOP, NULL);
3627         gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menuitem);
3628         gtk_widget_show (menuitem);
3629         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
3630                                   G_CALLBACK (gl_view_align_selection_top), view);
3631         view->multi_selection_items =
3632                 g_list_prepend (view->multi_selection_items, menuitem);
3633
3634         menuitem = gtk_image_menu_item_new_from_stock (GL_STOCK_ALIGN_VCENTER, NULL);
3635         gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menuitem);
3636         gtk_widget_show (menuitem);
3637         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
3638                                   G_CALLBACK (gl_view_align_selection_vcenter), view);
3639         view->multi_selection_items =
3640                 g_list_prepend (view->multi_selection_items, menuitem);
3641
3642         menuitem = gtk_image_menu_item_new_from_stock (GL_STOCK_ALIGN_BOTTOM, NULL);
3643         gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menuitem);
3644         gtk_widget_show (menuitem);
3645         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
3646                                   G_CALLBACK (gl_view_align_selection_bottom), view);
3647         view->multi_selection_items =
3648                 g_list_prepend (view->multi_selection_items, menuitem);
3649
3650         menuitem = gtk_image_menu_item_new_from_stock (GL_STOCK_CENTER_VERT, NULL);
3651         gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menuitem);
3652         gtk_widget_show (menuitem);
3653         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
3654                                   G_CALLBACK (gl_view_center_selection_vert), view);
3655
3656         /*
3657          * Separator -------------------------
3658          */
3659         menuitem = gtk_menu_item_new ();
3660         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3661         gtk_widget_show (menuitem);
3662
3663         menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_CUT, NULL);
3664         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3665         gtk_widget_show (menuitem);
3666         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
3667                                   G_CALLBACK (gl_view_cut), view);
3668
3669         menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_COPY, NULL);
3670         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3671         gtk_widget_show (menuitem);
3672         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
3673                                   G_CALLBACK (gl_view_copy), view);
3674
3675         menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_PASTE, NULL);
3676         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3677         gtk_widget_show (menuitem);
3678         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
3679                                   G_CALLBACK (gl_view_paste), view);
3680
3681         menuitem = gtk_menu_item_new_with_mnemonic (_("_Delete"));
3682         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3683         gtk_widget_show (menuitem);
3684         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
3685                                   G_CALLBACK (gl_view_delete_selection), view);
3686
3687
3688         view->selection_menu = menu;
3689
3690         gl_debug (DEBUG_VIEW, "END");
3691 }
3692
3693 /*---------------------------------------------------------------------------*/
3694 /* PRIVATE.  create menu for empty selections.                               */
3695 /*---------------------------------------------------------------------------*/
3696 void
3697 construct_empty_selection_menu (glView *view)
3698 {
3699         GtkWidget *menu, *menuitem, *submenu;
3700
3701         gl_debug (DEBUG_VIEW, "START");
3702
3703         g_return_if_fail (view && GL_IS_VIEW (view));
3704
3705         menu = gtk_menu_new ();
3706
3707         menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_PASTE, NULL);
3708         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3709         gtk_widget_show (menuitem);
3710         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
3711                                   G_CALLBACK (gl_view_paste), view);
3712
3713
3714         view->empty_selection_menu = menu;
3715
3716         gl_debug (DEBUG_VIEW, "END");
3717 }
3718
3719 /****************************************************************************/
3720 /* popup menu.                                                              */
3721 /****************************************************************************/
3722 void
3723 gl_view_popup_menu (glView       *view,
3724                     GdkEvent     *event)
3725 {
3726         GtkMenu *menu;
3727         GList   *p;
3728
3729         gl_debug (DEBUG_VIEW, "START");
3730
3731         g_return_if_fail (view && GL_IS_VIEW (view));
3732
3733         if (gl_view_is_selection_empty (view)) {
3734
3735                 if (view->empty_selection_menu != NULL) {
3736                         gtk_menu_popup (GTK_MENU (view->empty_selection_menu),
3737                                         NULL, NULL, NULL, NULL,
3738                                         event->button.button,
3739                                         event->button.time);
3740                 }
3741
3742         } else {
3743
3744                 for (p=view->atomic_selection_items; p!=NULL; p=p->next) {
3745                         gtk_widget_set_sensitive (GTK_WIDGET(p->data),
3746                                                   gl_view_is_selection_atomic(view));
3747                 }
3748
3749                 for (p=view->multi_selection_items; p!=NULL; p=p->next) {
3750                         gtk_widget_set_sensitive (GTK_WIDGET(p->data),
3751                                                   !gl_view_is_selection_atomic(view));
3752                 }
3753
3754                 if (view->selection_menu != NULL) {
3755                         gtk_menu_popup (GTK_MENU (view->selection_menu),
3756                                         NULL, NULL, NULL, NULL,
3757                                         event->button.button,
3758                                         event->button.time);
3759                 }
3760
3761         }
3762
3763         gl_debug (DEBUG_VIEW, "END");
3764 }
3765
3766 /*---------------------------------------------------------------------------*/
3767 /* PRIVATE.  Handle "selection-clear" signal.                                */
3768 /*---------------------------------------------------------------------------*/
3769 static void
3770 selection_clear_cb (GtkWidget         *widget,
3771                     GdkEventSelection *event,
3772                     gpointer          data)
3773 {
3774         glView *view = GL_VIEW (data);
3775
3776         gl_debug (DEBUG_VIEW, "START");
3777
3778         g_return_if_fail (view && GL_IS_VIEW (view));
3779
3780         view->have_selection = FALSE;
3781         g_object_unref (view->selection_data);
3782         view->selection_data = NULL;
3783
3784         gl_debug (DEBUG_VIEW, "END");
3785 }
3786
3787 /*---------------------------------------------------------------------------*/
3788 /* PRIVATE.  Handle "selection-get" signal.                                  */
3789 /*---------------------------------------------------------------------------*/
3790 static void
3791 selection_get_cb (GtkWidget        *widget,
3792                   GtkSelectionData *selection_data,
3793                   guint            info,
3794                   guint            time,
3795                   gpointer         data)
3796 {
3797         glView *view = GL_VIEW (data);
3798         gchar *buffer;
3799         glXMLLabelStatus status;
3800
3801         gl_debug (DEBUG_VIEW, "START");
3802
3803         g_return_if_fail (view && GL_IS_VIEW (view));
3804
3805         if (view->have_selection) {
3806
3807                 buffer = gl_xml_label_save_buffer (view->selection_data,
3808                                                    &status);
3809                 gtk_selection_data_set (selection_data,
3810                                         GDK_SELECTION_TYPE_STRING, 8, buffer,
3811                                         strlen (buffer));
3812                 g_free (buffer);
3813         }
3814
3815         gl_debug (DEBUG_VIEW, "END");
3816 }
3817
3818 /*---------------------------------------------------------------------------*/
3819 /* PRIVATE.  Handle "selection-received" signal.  (Result of Paste)          */
3820 /*---------------------------------------------------------------------------*/
3821 static void
3822 selection_received_cb (GtkWidget        *widget,
3823                        GtkSelectionData *selection_data,
3824                        guint            time,
3825                        gpointer         data)
3826 {
3827         glView *view = GL_VIEW (data);
3828         glLabel *label = NULL;
3829         glXMLLabelStatus status;
3830         GList *p, *p_next;
3831         glLabelObject *object, *newobject;
3832         glViewObject *view_object;
3833
3834         gl_debug (DEBUG_VIEW, "START");
3835
3836         g_return_if_fail (view && GL_IS_VIEW (view));
3837
3838         if (selection_data->length < 0) {
3839                 return;
3840         }
3841         if (selection_data->type != GDK_SELECTION_TYPE_STRING) {
3842                 return;
3843         }
3844
3845         gl_view_unselect_all (view);
3846
3847         label = gl_xml_label_open_buffer (selection_data->data, &status);
3848         for (p = label->objects; p != NULL; p = p_next) {
3849                 p_next = p->next;
3850
3851                 object = (glLabelObject *) p->data;
3852                 newobject = gl_label_object_dup (object, view->label);
3853
3854                 gl_debug (DEBUG_VIEW, "object pasted");
3855
3856                 if (GL_IS_LABEL_BOX (newobject)) {
3857                         view_object = gl_view_box_new (GL_LABEL_BOX(newobject),
3858                                                        view);
3859                 } else if (GL_IS_LABEL_ELLIPSE (newobject)) {
3860                         view_object = gl_view_ellipse_new (GL_LABEL_ELLIPSE(newobject),
3861                                                            view);
3862                 } else if (GL_IS_LABEL_LINE (newobject)) {
3863                         view_object = gl_view_line_new (GL_LABEL_LINE(newobject),
3864                                                         view);
3865                 } else if (GL_IS_LABEL_IMAGE (newobject)) {
3866                         view_object = gl_view_image_new (GL_LABEL_IMAGE(newobject),
3867                                                          view);
3868                 } else if (GL_IS_LABEL_TEXT (newobject)) {
3869                         view_object = gl_view_text_new (GL_LABEL_TEXT(newobject),
3870                                                         view);
3871                 } else if (GL_IS_LABEL_BARCODE (newobject)) {
3872                         view_object = gl_view_barcode_new (GL_LABEL_BARCODE(newobject),
3873                                                            view);
3874                 } else {
3875                         /* Should not happen! */
3876                         view_object = NULL;
3877                         g_warning ("Invalid label object type.");
3878                 }
3879                 gl_view_select_object (view, view_object);
3880         }
3881         g_object_unref (label);
3882
3883         gl_debug (DEBUG_VIEW, "END");
3884 }
3885
3886 /****************************************************************************/
3887 /* Set default font family.                                                 */
3888 /****************************************************************************/
3889 void
3890 gl_view_set_default_font_family (glView            *view,
3891                                  const gchar       *font_family)
3892 {
3893         gl_debug (DEBUG_VIEW, "START");
3894
3895         g_return_if_fail (view && GL_IS_VIEW (view));
3896
3897         if (view->default_font_family) {
3898                 g_free (view->default_font_family);
3899         }
3900         view->default_font_family = g_strdup (font_family);
3901
3902         gl_debug (DEBUG_VIEW, "END");
3903 }
3904
3905
3906 /****************************************************************************/
3907 /* Set default font size.                                                   */
3908 /****************************************************************************/
3909 void
3910 gl_view_set_default_font_size (glView            *view,
3911                                gdouble            font_size)
3912 {
3913         gl_debug (DEBUG_VIEW, "START");
3914
3915         g_return_if_fail (view && GL_IS_VIEW (view));
3916
3917         view->default_font_size = font_size;
3918
3919         gl_debug (DEBUG_VIEW, "END");
3920 }
3921
3922
3923 /****************************************************************************/
3924 /* Set default font weight.                                                 */
3925 /****************************************************************************/
3926 void
3927 gl_view_set_default_font_weight (glView            *view,
3928                                  GnomeFontWeight    font_weight)
3929 {
3930         gl_debug (DEBUG_VIEW, "START");
3931
3932         g_return_if_fail (view && GL_IS_VIEW (view));
3933
3934         view->default_font_weight = font_weight;
3935
3936         gl_debug (DEBUG_VIEW, "END");
3937 }
3938
3939
3940 /****************************************************************************/
3941 /* Set default font italic flag.                                            */
3942 /****************************************************************************/
3943 void
3944 gl_view_set_default_font_italic_flag (glView            *view,
3945                                       gboolean           font_italic_flag)
3946 {
3947         gl_debug (DEBUG_VIEW, "START");
3948
3949         g_return_if_fail (view && GL_IS_VIEW (view));
3950
3951         view->default_font_italic_flag = font_italic_flag;
3952
3953         gl_debug (DEBUG_VIEW, "END");
3954 }
3955
3956
3957 /****************************************************************************/
3958 /* Set default text color.                                                  */
3959 /****************************************************************************/
3960 void
3961 gl_view_set_default_text_color (glView            *view,
3962                                 guint              text_color)
3963 {
3964         gl_debug (DEBUG_VIEW, "START");
3965
3966         g_return_if_fail (view && GL_IS_VIEW (view));
3967
3968         view->default_text_color = text_color;
3969
3970         gl_debug (DEBUG_VIEW, "END");
3971 }
3972
3973
3974 /****************************************************************************/
3975 /* Set default text alignment.                                              */
3976 /****************************************************************************/
3977 void
3978 gl_view_set_default_text_alignment (glView            *view,
3979                                     GtkJustification   text_alignment)
3980 {
3981         gl_debug (DEBUG_VIEW, "START");
3982
3983         g_return_if_fail (view && GL_IS_VIEW (view));
3984
3985         view->default_text_alignment = text_alignment;
3986         gl_debug (DEBUG_VIEW, "END");
3987 }
3988
3989
3990 /****************************************************************************/
3991 /* Set default line width.                                                  */
3992 /****************************************************************************/
3993 void
3994 gl_view_set_default_line_width (glView            *view,
3995                                 gdouble            line_width)
3996 {
3997         gl_debug (DEBUG_VIEW, "START");
3998
3999         g_return_if_fail (view && GL_IS_VIEW (view));
4000
4001         view->default_line_width = line_width;
4002
4003         gl_debug (DEBUG_VIEW, "END");
4004 }
4005
4006
4007 /****************************************************************************/
4008 /* Set default line color.                                                  */
4009 /****************************************************************************/
4010 void
4011 gl_view_set_default_line_color (glView            *view,
4012                                 guint              line_color)
4013 {
4014         gl_debug (DEBUG_VIEW, "START");
4015
4016         g_return_if_fail (view && GL_IS_VIEW (view));
4017
4018         view->default_line_color = line_color;
4019
4020         gl_debug (DEBUG_VIEW, "END");
4021 }
4022
4023
4024 /****************************************************************************/
4025 /* Set default fill color.                                                  */
4026 /****************************************************************************/
4027 void
4028 gl_view_set_default_fill_color (glView            *view,
4029                                 guint              fill_color)
4030 {
4031         gl_debug (DEBUG_VIEW, "START");
4032
4033         g_return_if_fail (view && GL_IS_VIEW (view));
4034
4035         view->default_fill_color = fill_color;
4036
4037         gl_debug (DEBUG_VIEW, "END");
4038 }
4039
4040
4041
4042 /****************************************************************************/
4043 /* Get default font family.                                                 */
4044 /****************************************************************************/
4045 gchar *
4046 gl_view_get_default_font_family (glView            *view)
4047 {
4048         gl_debug (DEBUG_VIEW, "START");
4049
4050         g_return_val_if_fail (view && GL_IS_VIEW (view), NULL);
4051
4052         gl_debug (DEBUG_VIEW, "END");
4053
4054         return g_strdup (view->default_font_family);
4055 }
4056
4057
4058 /****************************************************************************/
4059 /* Get default font size.                                                   */
4060 /****************************************************************************/
4061 gdouble
4062 gl_view_get_default_font_size (glView            *view)
4063 {
4064         gl_debug (DEBUG_VIEW, "START");
4065
4066         g_return_val_if_fail (view && GL_IS_VIEW (view), 12.0);
4067
4068         gl_debug (DEBUG_VIEW, "END");
4069
4070         return view->default_font_size;
4071 }
4072
4073
4074 /****************************************************************************/
4075 /* Get default font weight.                                                 */
4076 /****************************************************************************/
4077 GnomeFontWeight
4078 gl_view_get_default_font_weight (glView            *view)
4079 {
4080         gl_debug (DEBUG_VIEW, "START");
4081
4082         g_return_val_if_fail (view && GL_IS_VIEW (view), GNOME_FONT_BOOK);
4083
4084         gl_debug (DEBUG_VIEW, "END");
4085
4086         return view->default_font_weight;
4087 }
4088
4089
4090 /****************************************************************************/
4091 /* Get default font italic flag.                                            */
4092 /****************************************************************************/
4093 gboolean
4094 gl_view_get_default_font_italic_flag (glView            *view)
4095 {
4096         gl_debug (DEBUG_VIEW, "START");
4097
4098         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
4099
4100         gl_debug (DEBUG_VIEW, "END");
4101
4102         return view->default_font_italic_flag;
4103 }
4104
4105
4106 /****************************************************************************/
4107 /* Get default text color.                                                  */
4108 /****************************************************************************/
4109 guint
4110 gl_view_get_default_text_color (glView            *view)
4111 {
4112         gl_debug (DEBUG_VIEW, "START");
4113
4114         g_return_val_if_fail (view && GL_IS_VIEW (view), 0);
4115
4116         gl_debug (DEBUG_VIEW, "END");
4117
4118         return view->default_text_color;
4119 }
4120
4121
4122 /****************************************************************************/
4123 /* Get default text alignment.                                              */
4124 /****************************************************************************/
4125 GtkJustification
4126 gl_view_get_default_text_alignment (glView            *view)
4127 {
4128         gl_debug (DEBUG_VIEW, "START");
4129
4130         g_return_val_if_fail (view && GL_IS_VIEW (view), GTK_JUSTIFY_LEFT);
4131
4132         gl_debug (DEBUG_VIEW, "END");
4133
4134         return view->default_text_alignment;
4135 }
4136
4137
4138 /****************************************************************************/
4139 /* Get default line width.                                                  */
4140 /****************************************************************************/
4141 gdouble
4142 gl_view_get_default_line_width (glView            *view)
4143 {
4144         gl_debug (DEBUG_VIEW, "START");
4145
4146         g_return_val_if_fail (view && GL_IS_VIEW (view), 1.0);
4147
4148         gl_debug (DEBUG_VIEW, "END");
4149
4150         return view->default_line_width;
4151 }
4152
4153
4154 /****************************************************************************/
4155 /* Get default line color.                                                  */
4156 /****************************************************************************/
4157 guint gl_view_get_default_line_color (glView            *view)
4158 {
4159         gl_debug (DEBUG_VIEW, "START");
4160
4161         g_return_val_if_fail (view && GL_IS_VIEW (view), 0);
4162
4163         gl_debug (DEBUG_VIEW, "END");
4164
4165         return view->default_line_color;
4166 }
4167
4168
4169 /****************************************************************************/
4170 /* Get default fill color.                                                  */
4171 /****************************************************************************/
4172 guint gl_view_get_default_fill_color (glView            *view)
4173 {
4174         gl_debug (DEBUG_VIEW, "START");
4175
4176         g_return_val_if_fail (view && GL_IS_VIEW (view), 0);
4177
4178         gl_debug (DEBUG_VIEW, "END");
4179
4180         return view->default_fill_color;
4181 }
4182