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