]> git.sur5r.net Git - glabels/blob - glabels2/src/view.c
Added support for Business Card CD Labels (Clipped circular shape).
[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 "marshal.h"
44
45 #include "debug.h"
46
47 /*==========================================================================*/
48 /* Private macros and constants.                                            */
49 /*==========================================================================*/
50
51 #define BG_COLOR        GL_COLOR (192, 192, 192)
52 #define OUTLINE_COLOR   GL_COLOR (173, 216, 230)
53 #define PAPER_COLOR     GL_COLOR (255, 255, 255)
54 #define GRID_COLOR      BG_COLOR
55 #define MARKUP_COLOR    GL_COLOR (240, 100, 100)
56
57 #define SEL_LINE_COLOR  GL_COLOR_A (0, 0, 255, 128)
58 #define SEL_FILL_COLOR  GL_COLOR_A (192, 192, 255, 128)
59
60 #define ARC_FINE         2 /* Resolution in degrees of large arcs */
61 #define ARC_COURSE       5 /* Resolution in degrees of small arcs */
62
63 /*==========================================================================*/
64 /* Private types.                                                           */
65 /*==========================================================================*/
66
67 enum {
68         SELECTION_CHANGED,
69         ZOOM_CHANGED,
70         POINTER_MOVED,
71         POINTER_EXIT,
72         MODE_CHANGED,
73         LAST_SIGNAL
74 };
75
76
77 /*==========================================================================*/
78 /* Private globals                                                          */
79 /*==========================================================================*/
80
81 static GtkContainerClass *parent_class;
82
83 static guint signals[LAST_SIGNAL] = {0};
84
85 /* "CLIPBOARD" selection */
86 static GdkAtom clipboard_atom = GDK_NONE;
87
88 static gdouble scales[] = {
89         8.0, 6.0, 4.0, 3.0,
90         2.0,
91         1.5, 1.0, 0.5, 0.25,
92 };
93 #define N_SCALES G_N_ELEMENTS(scales)
94 #define HOME_SCALE 2.0
95
96 /*==========================================================================*/
97 /* Local function prototypes                                                */
98 /*==========================================================================*/
99
100 static void       gl_view_class_init              (glViewClass *class);
101 static void       gl_view_init                    (glView *view);
102 static void       gl_view_finalize                (GObject *object);
103
104 static void       gl_view_construct               (glView *view);
105 static GtkWidget *gl_view_construct_canvas        (glView *view);
106 static void       gl_view_construct_selection     (glView *view);
107
108 static gdouble    get_apropriate_scale            (gdouble w, gdouble h);
109
110 static void       draw_layers                     (glView *view);
111
112 static void       draw_label_layer                (glView *view);
113
114 static void       draw_highlight_layer            (glView *view);
115
116 static void       draw_bg_fg_layers               (glView *view);
117 static void       draw_bg_fg_rect                 (glView *view);
118 static void       draw_bg_fg_rounded_rect         (glView *view);
119 static void       draw_bg_fg_round                (glView *view);
120 static void       draw_bg_fg_cd                   (glView *view);
121 static void       draw_bg_fg_cd_bc                (glView *view);
122
123 static void       draw_grid_layer                 (glView *view);
124
125 static void       draw_markup_layer               (glView *view);
126
127 static void       draw_markup_margin              (glView *view,
128                                                    glTemplateMarkupMargin *margin);
129 static void       draw_markup_margin_rect         (glView *view,
130                                                    glTemplateMarkupMargin *margin);
131 static void       draw_markup_margin_rounded_rect (glView *view,
132                                                    glTemplateMarkupMargin *margin);
133 static void       draw_markup_margin_round        (glView *view,
134                                                    glTemplateMarkupMargin *margin);
135 static void       draw_markup_margin_cd           (glView *view,
136                                                    glTemplateMarkupMargin *margin);
137 static void       draw_markup_margin_cd_bc        (glView *view,
138                                                    glTemplateMarkupMargin *margin);
139
140 static void       draw_markup_line                (glView *view,
141                                                    glTemplateMarkupLine   *line);
142
143
144 static void       select_object_real              (glView *view,
145                                                    glViewObject *view_object);
146 static void       unselect_object_real            (glView *view,
147                                                    glViewObject *view_object);
148
149 static gboolean   object_at                       (glView *view,
150                                                    gdouble x, gdouble y);
151
152 static gboolean   is_item_member_of_group         (glView          *view,
153                                                    GnomeCanvasItem *item,
154                                                    GnomeCanvasItem *group);
155
156 static int        canvas_event                    (GnomeCanvas *canvas,
157                                                    GdkEvent    *event,
158                                                    glView      *view);
159 static int        canvas_event_arrow_mode         (GnomeCanvas *canvas,
160                                                    GdkEvent    *event,
161                                                    glView      *view);
162
163 static void       construct_selection_menu       (glView *view);
164
165 static void       construct_empty_selection_menu (glView *view);
166
167 static void       selection_clear_cb             (GtkWidget         *widget,
168                                                   GdkEventSelection *event,
169                                                   gpointer          data);
170
171 static void       selection_get_cb               (GtkWidget         *widget,
172                                                   GtkSelectionData  *selection_data,
173                                                   guint             info,
174                                                   guint             time,
175                                                   gpointer          data);
176
177 static void       selection_received_cb          (GtkWidget         *widget,
178                                                   GtkSelectionData  *selection_data,
179                                                   guint             time,
180                                                   gpointer          data);
181 \f
182 /****************************************************************************/
183 /* Boilerplate Object stuff.                                                */
184 /****************************************************************************/
185 guint
186 gl_view_get_type (void)
187 {
188         static guint view_type = 0;
189
190         if (!view_type) {
191                 GTypeInfo view_info = {
192                         sizeof (glViewClass),
193                         NULL,
194                         NULL,
195                         (GClassInitFunc) gl_view_class_init,
196                         NULL,
197                         NULL,
198                         sizeof (glView),
199                         0,
200                         (GInstanceInitFunc) gl_view_init,
201                 };
202
203                 view_type =
204                     g_type_register_static (gtk_vbox_get_type (),
205                                             "glView", &view_info, 0);
206         }
207
208         return view_type;
209 }
210
211 static void
212 gl_view_class_init (glViewClass *class)
213 {
214         GObjectClass *object_class = (GObjectClass *) class;
215
216         gl_debug (DEBUG_VIEW, "START");
217
218         parent_class = g_type_class_peek_parent (class);
219
220         object_class->finalize = gl_view_finalize;
221
222         signals[SELECTION_CHANGED] =
223                 g_signal_new ("selection_changed",
224                               G_OBJECT_CLASS_TYPE (object_class),
225                               G_SIGNAL_RUN_LAST,
226                               G_STRUCT_OFFSET (glViewClass, selection_changed),
227                               NULL, NULL,
228                               gl_marshal_VOID__VOID,
229                               G_TYPE_NONE,
230                               0);
231
232         signals[ZOOM_CHANGED] =
233                 g_signal_new ("zoom_changed",
234                               G_OBJECT_CLASS_TYPE (object_class),
235                               G_SIGNAL_RUN_LAST,
236                               G_STRUCT_OFFSET (glViewClass, zoom_changed),
237                               NULL, NULL,
238                               gl_marshal_VOID__DOUBLE,
239                               G_TYPE_NONE,
240                               1, G_TYPE_DOUBLE);
241
242         signals[POINTER_MOVED] =
243                 g_signal_new ("pointer_moved",
244                               G_OBJECT_CLASS_TYPE (object_class),
245                               G_SIGNAL_RUN_LAST,
246                               G_STRUCT_OFFSET (glViewClass, pointer_moved),
247                               NULL, NULL,
248                               gl_marshal_VOID__DOUBLE_DOUBLE,
249                               G_TYPE_NONE,
250                               2, G_TYPE_DOUBLE, G_TYPE_DOUBLE);
251
252         signals[POINTER_EXIT] =
253                 g_signal_new ("pointer_exit",
254                               G_OBJECT_CLASS_TYPE (object_class),
255                               G_SIGNAL_RUN_LAST,
256                               G_STRUCT_OFFSET (glViewClass, pointer_exit),
257                               NULL, NULL,
258                               gl_marshal_VOID__VOID,
259                               G_TYPE_NONE,
260                               0);
261
262         signals[MODE_CHANGED] =
263                 g_signal_new ("mode_changed",
264                               G_OBJECT_CLASS_TYPE (object_class),
265                               G_SIGNAL_RUN_LAST,
266                               G_STRUCT_OFFSET (glViewClass, mode_changed),
267                               NULL, NULL,
268                               gl_marshal_VOID__VOID,
269                               G_TYPE_NONE,
270                               0);
271
272         gl_debug (DEBUG_VIEW, "END");
273 }
274
275 static void
276 gl_view_init (glView *view)
277 {
278         gl_debug (DEBUG_VIEW, "START");
279
280         view->label = NULL;
281
282         view->grid_spacing = 9;
283
284         gl_debug (DEBUG_VIEW, "END");
285 }
286
287 static void
288 gl_view_finalize (GObject *object)
289 {
290         glView *view;
291
292         gl_debug (DEBUG_VIEW, "START");
293
294         g_return_if_fail (object != NULL);
295         g_return_if_fail (GL_IS_VIEW (object));
296
297         view = GL_VIEW (object);
298
299         G_OBJECT_CLASS (parent_class)->finalize (object);
300
301         gl_debug (DEBUG_VIEW, "END");
302 }
303
304 /****************************************************************************/
305 /* NEW view object.                                                         */
306 /****************************************************************************/
307 GtkWidget *
308 gl_view_new (glLabel *label)
309 {
310         glView *view = g_object_new (gl_view_get_type (), NULL);
311
312         gl_debug (DEBUG_VIEW, "START");
313
314         view->label = label;
315
316         gl_view_construct (view);
317
318         gl_debug (DEBUG_VIEW, "END");
319
320         return GTK_WIDGET (view);
321 }
322
323 /*---------------------------------------------------------------------------*/
324 /* PRIVATE.  Construct composite widget.                                     */
325 /*---------------------------------------------------------------------------*/
326 static void
327 gl_view_construct (glView *view)
328 {
329         GtkWidget *wvbox, *wscroll;
330
331         gl_debug (DEBUG_VIEW, "START");
332
333         g_return_if_fail (GL_IS_VIEW (view));
334
335         wvbox = GTK_WIDGET (view);
336
337         view->state = GL_VIEW_STATE_ARROW;
338         view->object_list = NULL;
339
340         gl_view_construct_canvas (view);
341         wscroll = gtk_scrolled_window_new (NULL, NULL);
342         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (wscroll),
343                                         GTK_POLICY_AUTOMATIC,
344                                         GTK_POLICY_AUTOMATIC);
345         gtk_box_pack_start (GTK_BOX (wvbox), wscroll, TRUE, TRUE, 0);
346         gtk_container_add (GTK_CONTAINER (wscroll), view->canvas);
347
348         gl_view_construct_selection (view);
349
350         construct_selection_menu (view);
351         construct_empty_selection_menu (view);
352
353         gl_debug (DEBUG_VIEW, "END");
354 }
355
356 /*---------------------------------------------------------------------------*/
357 /* PRIVATE.  Create canvas w/ a background in the shape of the label/card.   */
358 /*---------------------------------------------------------------------------*/
359 static GtkWidget *
360 gl_view_construct_canvas (glView *view)
361 {
362         gdouble   scale;
363         glLabel  *label = view->label;
364         gdouble   label_width, label_height;
365         GdkColor *bg_color;
366
367         gl_debug (DEBUG_VIEW, "START");
368
369         g_return_val_if_fail (GL_IS_VIEW (view), NULL);
370         g_return_val_if_fail (label != NULL, NULL);
371
372         gtk_widget_push_colormap (gdk_rgb_get_colormap ());
373         view->canvas = gnome_canvas_new_aa ();
374         gtk_widget_pop_colormap ();
375
376         bg_color = gl_color_to_gdk_color (BG_COLOR);
377         gtk_widget_modify_bg (GTK_WIDGET(view->canvas), GTK_STATE_NORMAL, bg_color);
378         g_free (bg_color);
379
380         gl_label_get_size (label, &label_width, &label_height);
381         gl_debug (DEBUG_VIEW, "Label size: w=%lf, h=%lf",
382                   label_width, label_height);
383
384         scale = get_apropriate_scale (label_width, label_height);
385         gl_debug (DEBUG_VIEW, "scale =%lf", scale);
386
387         gl_debug (DEBUG_VIEW, "Canvas size: w=%lf, h=%lf",
388                               scale * label_width + 40,
389                               scale * label_height + 40);
390         gtk_widget_set_size_request (GTK_WIDGET(view->canvas),
391                                      scale * label_width + 40,
392                                      scale * label_height + 40);
393         gnome_canvas_set_pixels_per_unit (GNOME_CANVAS (view->canvas),
394                                           scale);
395         view->scale = scale;
396
397         gnome_canvas_set_scroll_region (GNOME_CANVAS (view->canvas),
398                                         0.0, 0.0, label_width, label_height);
399
400         draw_layers (view);
401
402         g_signal_connect (G_OBJECT (view->canvas), "event",
403                           G_CALLBACK (canvas_event), view);
404
405         gl_debug (DEBUG_VIEW, "END");
406
407         return view->canvas;
408 }
409
410 /*---------------------------------------------------------------------------*/
411 /* PRIVATE.  Create clipboard selection targets.                             */
412 /*---------------------------------------------------------------------------*/
413 static void
414 gl_view_construct_selection (glView *view)
415 {
416         gl_debug (DEBUG_VIEW, "START");
417
418         g_return_if_fail (GL_IS_VIEW (view));
419
420         view->have_selection = FALSE;
421         view->selection_data = NULL;
422         view->invisible = gtk_invisible_new ();
423
424         view->selected_object_list = NULL;
425
426         if (!clipboard_atom) {
427                 clipboard_atom = gdk_atom_intern ("GLABELS_CLIPBOARD", FALSE);
428         }
429
430         gtk_selection_add_target (view->invisible,
431                                   clipboard_atom, GDK_SELECTION_TYPE_STRING, 1);
432
433         g_signal_connect (G_OBJECT (view->invisible),
434                           "selection_clear_event",
435                           G_CALLBACK (selection_clear_cb), view);
436
437         g_signal_connect (G_OBJECT (view->invisible), "selection_get",
438                           G_CALLBACK (selection_get_cb), view);
439
440         g_signal_connect (G_OBJECT (view->invisible),
441                           "selection_received",
442                           G_CALLBACK (selection_received_cb), view);
443
444         gl_debug (DEBUG_VIEW, "END");
445 }
446
447 /*---------------------------------------------------------------------------*/
448 /* PRIVATE.  Determine an apropriate scale for given label & screen size     */
449 /*---------------------------------------------------------------------------*/
450 static gdouble
451 get_apropriate_scale (gdouble w, gdouble h)
452 {
453         gdouble w_screen, h_screen;
454         gint i;
455         gdouble k;
456
457         gl_debug (DEBUG_VIEW, "");
458
459         w_screen = (gdouble) gdk_screen_width ();
460         h_screen = (gdouble) gdk_screen_height ();
461
462         for (i = 0; i < N_SCALES; i++) {
463                 k = scales[i];
464                 if (k <= HOME_SCALE) {
465                         if ((k * w < (w_screen - 256))
466                             && (k * h < (h_screen - 256)))
467                                 return k;
468                 }
469         }
470
471         return 0.25;
472 }
473
474 /*---------------------------------------------------------------------------*/
475 /* PRIVATE.  Create, draw and order layers.                                  */
476 /*---------------------------------------------------------------------------*/
477 static void
478 draw_layers (glView *view)
479 {
480         draw_bg_fg_layers (view);
481         draw_grid_layer (view);
482         draw_markup_layer (view);
483         draw_highlight_layer (view); /* Must be done before label layer */
484         draw_label_layer (view);
485
486         gnome_canvas_item_raise_to_top (GNOME_CANVAS_ITEM(view->fg_group));
487         gnome_canvas_item_raise_to_top (GNOME_CANVAS_ITEM(view->highlight_group));
488 }
489
490 /*---------------------------------------------------------------------------*/
491 /* PRIVATE.  Draw label layer.                                               */
492 /*---------------------------------------------------------------------------*/
493 static void
494 draw_label_layer (glView *view)
495 {
496         GnomeCanvasGroup *group;
497         glLabel          *label;
498         GList            *p_obj;
499         glLabelObject    *object;
500         glViewObject     *view_object;
501
502         group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
503         view->label_group = GNOME_CANVAS_GROUP(
504                 gnome_canvas_item_new (group,
505                                        gnome_canvas_group_get_type (),
506                                        "x", 0.0,
507                                        "y", 0.0,
508                                        NULL));
509
510         label = view->label;
511
512         for (p_obj = label->objects; p_obj != NULL; p_obj = p_obj->next) {
513                 object = (glLabelObject *) p_obj->data;
514
515                 if (GL_IS_LABEL_BOX (object)) {
516                         view_object = gl_view_box_new (GL_LABEL_BOX(object),
517                                                        view);
518                 } else if (GL_IS_LABEL_ELLIPSE (object)) {
519                         view_object = gl_view_ellipse_new (GL_LABEL_ELLIPSE(object),
520                                                            view);
521                 } else if (GL_IS_LABEL_LINE (object)) {
522                         view_object = gl_view_line_new (GL_LABEL_LINE(object),
523                                                         view);
524                 } else if (GL_IS_LABEL_IMAGE (object)) {
525                         view_object = gl_view_image_new (GL_LABEL_IMAGE(object),
526                                                          view);
527                 } else if (GL_IS_LABEL_TEXT (object)) {
528                         view_object = gl_view_text_new (GL_LABEL_TEXT(object),
529                                                         view);
530                 } else if (GL_IS_LABEL_BARCODE (object)) {
531                         view_object = gl_view_barcode_new (GL_LABEL_BARCODE(object),
532                                                            view);
533                 } else {
534                         /* Should not happen! */
535                         view_object = NULL;
536                         g_warning ("Invalid label object type.");
537                 }
538         }
539 }
540
541 /*---------------------------------------------------------------------------*/
542 /* PRIVATE.  Create highlight layer.                                         */
543 /*---------------------------------------------------------------------------*/
544 static void
545 draw_highlight_layer (glView *view)
546 {
547         GnomeCanvasGroup *group;
548
549         group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
550         view->highlight_group = GNOME_CANVAS_GROUP(
551                 gnome_canvas_item_new (group,
552                                        gnome_canvas_group_get_type (),
553                                        "x", 0.0,
554                                        "y", 0.0,
555                                        NULL));
556 }
557
558 /*---------------------------------------------------------------------------*/
559 /* PRIVATE.  Draw background and foreground outlines.                        */
560 /*---------------------------------------------------------------------------*/
561 static void
562 draw_bg_fg_layers (glView *view)
563 {
564         glLabel          *label;
565         glTemplate       *template;
566         GnomeCanvasGroup *group;
567
568         group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
569         view->bg_group = GNOME_CANVAS_GROUP(
570                 gnome_canvas_item_new (group,
571                                        gnome_canvas_group_get_type (),
572                                        "x", 0.0,
573                                        "y", 0.0,
574                                        NULL));
575         view->fg_group = GNOME_CANVAS_GROUP(
576                 gnome_canvas_item_new (group,
577                                        gnome_canvas_group_get_type (),
578                                        "x", 0.0,
579                                        "y", 0.0,
580                                        NULL));
581
582         label = view->label;
583         template = gl_label_get_template (label);
584
585         switch (template->label.style) {
586
587         case GL_TEMPLATE_STYLE_RECT:
588                 if (template->label.rect.r == 0.0) {
589                         /* Square corners. */
590                         draw_bg_fg_rect (view);
591                 } else {
592                         /* Rounded corners. */
593                         draw_bg_fg_rounded_rect (view);
594                 }
595                 break;
596
597         case GL_TEMPLATE_STYLE_ROUND:
598                 draw_bg_fg_round (view);
599                 break;
600
601         case GL_TEMPLATE_STYLE_CD:
602                 if ((template->label.cd.w == 0.0) && (template->label.cd.h == 0.0) ) {
603                         draw_bg_fg_cd (view);
604                 } else {
605                         draw_bg_fg_cd_bc (view);
606                 }
607                 break;
608
609         default:
610                 g_warning ("Unknown template label style");
611                 break;
612         }
613 }
614
615 /*---------------------------------------------------------------------------*/
616 /* PRIVATE.  Draw simple recangular background.                              */
617 /*---------------------------------------------------------------------------*/
618 static void
619 draw_bg_fg_rect (glView *view)
620 {
621         glLabel          *label = view->label;
622         glTemplate       *template;
623         gdouble           w, h;
624         GnomeCanvasItem  *item;
625
626         gl_debug (DEBUG_VIEW, "START");
627
628         g_return_if_fail (GL_IS_VIEW (view));
629         g_return_if_fail (label != NULL);
630
631         gl_label_get_size (label, &w, &h);
632         template = gl_label_get_template (label);
633
634         /* Background */
635         item = gnome_canvas_item_new (view->bg_group,
636                                       gnome_canvas_rect_get_type (),
637                                       "x1", 0.0,
638                                       "y1", 0.0,
639                                       "x2", w,
640                                       "y2", h,
641                                       "fill_color_rgba", PAPER_COLOR,
642                                       NULL);
643
644         /* Foreground */
645         item = gnome_canvas_item_new (view->fg_group,
646                                       gnome_canvas_rect_get_type (),
647                                       "x1", 0.0,
648                                       "y1", 0.0,
649                                       "x2", w,
650                                       "y2", h,
651                                       "width_pixels", 2,
652                                       "outline_color_rgba", OUTLINE_COLOR,
653                                       NULL);
654
655         gl_debug (DEBUG_VIEW, "END");
656 }
657
658 /*---------------------------------------------------------------------------*/
659 /* PRIVATE.  Draw rounded recangular background.                             */
660 /*---------------------------------------------------------------------------*/
661 static void
662 draw_bg_fg_rounded_rect (glView *view)
663 {
664         glLabel           *label = view->label;
665         GnomeCanvasPoints *points;
666         gint               i_coords, i_theta;
667         glTemplate        *template;
668         gdouble            r, w, h;
669         GnomeCanvasItem   *item;
670
671         gl_debug (DEBUG_VIEW, "START");
672
673         g_return_if_fail (GL_IS_VIEW (view));
674         g_return_if_fail (label != NULL);
675
676         gl_label_get_size (label, &w, &h);
677         template = gl_label_get_template (label);
678         r = template->label.rect.r;
679
680         points = gnome_canvas_points_new (4 * (1 + 90 / ARC_COURSE));
681         i_coords = 0;
682         for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
683                 points->coords[i_coords++] =
684                     r - r * sin (i_theta * G_PI / 180.0);
685                 points->coords[i_coords++] =
686                     r - r * cos (i_theta * G_PI / 180.0);
687         }
688         for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
689                 points->coords[i_coords++] =
690                     r - r * cos (i_theta * G_PI / 180.0);
691                 points->coords[i_coords++] =
692                     (h - r) + r * sin (i_theta * G_PI / 180.0);
693         }
694         for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
695                 points->coords[i_coords++] =
696                     (w - r) + r * sin (i_theta * G_PI / 180.0);
697                 points->coords[i_coords++] =
698                     (h - r) + r * cos (i_theta * G_PI / 180.0);
699         }
700         for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
701                 points->coords[i_coords++] =
702                     (w - r) + r * cos (i_theta * G_PI / 180.0);
703                 points->coords[i_coords++] =
704                     r - r * sin (i_theta * G_PI / 180.0);
705         }
706
707         /* Background */
708         item = gnome_canvas_item_new (view->bg_group,
709                                       gnome_canvas_polygon_get_type (),
710                                       "points", points,
711                                       "fill_color_rgba", PAPER_COLOR,
712                                       NULL);
713
714         /* Foreground */
715         item = gnome_canvas_item_new (view->fg_group,
716                                       gnome_canvas_polygon_get_type (),
717                                       "points", points,
718                                       "width_pixels", 2,
719                                       "outline_color_rgba", OUTLINE_COLOR,
720                                       NULL);
721
722         gnome_canvas_points_free (points);
723
724         gl_debug (DEBUG_VIEW, "END");
725 }
726
727 /*---------------------------------------------------------------------------*/
728 /* PRIVATE.  Draw round background.                                          */
729 /*---------------------------------------------------------------------------*/
730 static void
731 draw_bg_fg_round (glView *view)
732 {
733         glLabel          *label = view->label;
734         glTemplate       *template;
735         gdouble           r;
736         GnomeCanvasItem  *item;
737
738         gl_debug (DEBUG_VIEW, "START");
739
740         g_return_if_fail (GL_IS_VIEW (view));
741         g_return_if_fail (label != NULL);
742
743         template = gl_label_get_template (label);
744
745         r = template->label.round.r;
746
747         /* Background */
748         item = gnome_canvas_item_new (view->bg_group,
749                                       gnome_canvas_ellipse_get_type (),
750                                       "x1", 0.0,
751                                       "y1", 0.0,
752                                       "x2", 2.0*r,
753                                       "y2", 2.0*r,
754                                       "fill_color_rgba", PAPER_COLOR,
755                                       NULL);
756
757         /* Foreground */
758         item = gnome_canvas_item_new (view->fg_group,
759                                       gnome_canvas_ellipse_get_type (),
760                                       "x1", 0.0,
761                                       "y1", 0.0,
762                                       "x2", 2.0*r,
763                                       "y2", 2.0*r,
764                                       "width_pixels", 2,
765                                       "outline_color_rgba", OUTLINE_COLOR,
766                                       NULL);
767
768         gl_debug (DEBUG_VIEW, "END");
769 }
770
771 /*---------------------------------------------------------------------------*/
772 /* PRIVATE.  Draw CD style background, circular w/ concentric hole.          */
773 /*---------------------------------------------------------------------------*/
774 static void
775 draw_bg_fg_cd (glView *view)
776 {
777         glLabel          *label = view->label;
778         glTemplate       *template;
779         gdouble           r1, r2;
780         GnomeCanvasItem  *item;
781
782         gl_debug (DEBUG_VIEW, "START");
783
784         g_return_if_fail (GL_IS_VIEW (view));
785         g_return_if_fail (label != NULL);
786
787         template = gl_label_get_template (label);
788
789         r1 = template->label.cd.r1;
790         r2 = template->label.cd.r2;
791
792         /* Background */
793         /* outer circle */
794         item = gnome_canvas_item_new (view->bg_group,
795                                       gnome_canvas_ellipse_get_type (),
796                                       "x1", 0.0,
797                                       "y1", 0.0,
798                                       "x2", 2.0*r1,
799                                       "y2", 2.0*r1,
800                                       "fill_color_rgba", PAPER_COLOR,
801                                       NULL);
802         /* hole */
803         item = gnome_canvas_item_new (view->bg_group,
804                                       gnome_canvas_ellipse_get_type (),
805                                       "x1", r1 - r2,
806                                       "y1", r1 - r2,
807                                       "x2", r1 + r2,
808                                       "y2", r1 + r2,
809                                       "fill_color_rgba", GRID_COLOR,
810                                       NULL);
811
812         /* Foreground */
813         /* outer circle */
814         item = gnome_canvas_item_new (view->fg_group,
815                                       gnome_canvas_ellipse_get_type (),
816                                       "x1", 0.0,
817                                       "y1", 0.0,
818                                       "x2", 2.0*r1,
819                                       "y2", 2.0*r1,
820                                       "width_pixels", 2,
821                                       "outline_color_rgba", OUTLINE_COLOR,
822                                       NULL);
823         /* hole */
824         item = gnome_canvas_item_new (view->fg_group,
825                                       gnome_canvas_ellipse_get_type (),
826                                       "x1", r1 - r2,
827                                       "y1", r1 - r2,
828                                       "x2", r1 + r2,
829                                       "y2", r1 + r2,
830                                       "width_pixels", 2,
831                                       "outline_color_rgba", OUTLINE_COLOR,
832                                       NULL);
833
834         gl_debug (DEBUG_VIEW, "END");
835 }
836
837 /*---------------------------------------------------------------------------*/
838 /* PRIVATE.  Draw Business Card CD style background, CD w/ chopped ends.     */
839 /*---------------------------------------------------------------------------*/
840 static void
841 draw_bg_fg_cd_bc (glView *view)
842 {
843         glLabel           *label = view->label;
844         glTemplate        *template;
845         GnomeCanvasPoints *points;
846         gint               i_coords, i_theta;
847         gdouble            theta1, theta2;
848         gdouble            x0, y0, w, h, r1, r2;
849         GnomeCanvasItem   *item;
850
851         gl_debug (DEBUG_VIEW, "START");
852
853         g_return_if_fail (GL_IS_VIEW (view));
854         g_return_if_fail (label != NULL);
855
856         template = gl_label_get_template (label);
857         gl_label_get_size (label, &w, &h);
858         x0 = w/2.0;
859         y0 = h/2.0;
860
861         r1 = template->label.cd.r1;
862         r2 = template->label.cd.r2;
863
864         theta1 = (180.0/G_PI) * acos (w / (2.0*r1));
865         theta2 = (180.0/G_PI) * asin (h / (2.0*r1));
866
867         points = gnome_canvas_points_new (360/ARC_FINE + 1);
868         i_coords = 0;
869
870         points->coords[i_coords++] = x0 + r1 * cos (theta1 * G_PI / 180.0);
871         points->coords[i_coords++] = y0 + r1 * sin (theta1 * G_PI / 180.0);
872
873         for ( i_theta = theta1 + ARC_FINE; i_theta < theta2; i_theta +=ARC_FINE ) {
874                 points->coords[i_coords++] = x0 + r1 * cos (i_theta * G_PI / 180.0);
875                 points->coords[i_coords++] = y0 + r1 * sin (i_theta * G_PI / 180.0);
876         }
877
878         points->coords[i_coords++] = x0 + r1 * cos (theta2 * G_PI / 180.0);
879         points->coords[i_coords++] = y0 + r1 * sin (theta2 * G_PI / 180.0);
880
881
882         if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
883                 points->coords[i_coords++] = x0 + r1 * cos ((180-theta2) * G_PI / 180.0);
884                 points->coords[i_coords++] = y0 + r1 * sin ((180-theta2) * G_PI / 180.0);
885         }
886
887         for ( i_theta = 180-theta2+ARC_FINE; i_theta < (180-theta1); i_theta +=ARC_FINE ) {
888                 points->coords[i_coords++] = x0 + r1 * cos (i_theta * G_PI / 180.0);
889                 points->coords[i_coords++] = y0 + r1 * sin (i_theta * G_PI / 180.0);
890         }
891
892         points->coords[i_coords++] = x0 + r1 * cos ((180-theta1) * G_PI / 180.0);
893         points->coords[i_coords++] = y0 + r1 * sin ((180-theta1) * G_PI / 180.0);
894
895         if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
896                 points->coords[i_coords++] = x0 + r1 * cos ((180+theta1) * G_PI / 180.0);
897                 points->coords[i_coords++] = y0 + r1 * sin ((180+theta1) * G_PI / 180.0);
898         }
899
900         for ( i_theta = 180+theta1+ARC_FINE; i_theta < (180+theta2); i_theta +=ARC_FINE ) {
901                 points->coords[i_coords++] = x0 + r1 * cos (i_theta * G_PI / 180.0);
902                 points->coords[i_coords++] = y0 + r1 * sin (i_theta * G_PI / 180.0);
903         }
904
905         points->coords[i_coords++] = x0 + r1 * cos ((180+theta2) * G_PI / 180.0);
906         points->coords[i_coords++] = y0 + r1 * sin ((180+theta2) * G_PI / 180.0);
907
908         if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
909                 points->coords[i_coords++] = x0 + r1 * cos ((360-theta2) * G_PI / 180.0);
910                 points->coords[i_coords++] = y0 + r1 * sin ((360-theta2) * G_PI / 180.0);
911         }
912
913         for ( i_theta = 360-theta2+ARC_FINE; i_theta < (360-theta1); i_theta +=ARC_FINE ) {
914                 points->coords[i_coords++] = x0 + r1 * cos (i_theta * G_PI / 180.0);
915                 points->coords[i_coords++] = y0 + r1 * sin (i_theta * G_PI / 180.0);
916         }
917
918         if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
919                 points->coords[i_coords++] = x0 + r1 * cos ((360-theta1) * G_PI / 180.0);
920                 points->coords[i_coords++] = y0 + r1 * sin ((360-theta1) * G_PI / 180.0);
921         }
922
923         points->num_points = i_coords / 2;
924
925         /* Background */
926         /* outer circle */
927         item = gnome_canvas_item_new (view->bg_group,
928                                       gnome_canvas_polygon_get_type (),
929                                       "points", points,
930                                       "fill_color_rgba", PAPER_COLOR,
931                                       NULL);
932         /* hole */
933         item = gnome_canvas_item_new (view->bg_group,
934                                       gnome_canvas_ellipse_get_type (),
935                                       "x1", x0 - r2,
936                                       "y1", y0 - r2,
937                                       "x2", x0 + r2,
938                                       "y2", y0 + r2,
939                                       "fill_color_rgba", GRID_COLOR,
940                                       NULL);
941
942         /* Foreground */
943         /* outer circle */
944         item = gnome_canvas_item_new (view->fg_group,
945                                       gnome_canvas_polygon_get_type (),
946                                       "points", points,
947                                       "width_pixels", 2,
948                                       "outline_color_rgba", OUTLINE_COLOR,
949                                       NULL);
950         /* hole */
951         item = gnome_canvas_item_new (view->fg_group,
952                                       gnome_canvas_ellipse_get_type (),
953                                       "x1", x0 - r2,
954                                       "y1", y0 - r2,
955                                       "x2", x0 + r2,
956                                       "y2", y0 + r2,
957                                       "width_pixels", 2,
958                                       "outline_color_rgba", OUTLINE_COLOR,
959                                       NULL);
960
961         gnome_canvas_points_free (points);
962
963         gl_debug (DEBUG_VIEW, "END");
964 }
965
966 /*---------------------------------------------------------------------------*/
967 /* PRIVATE.  Draw grid lines.                                                */
968 /*---------------------------------------------------------------------------*/
969 static void
970 draw_grid_layer (glView *view)
971 {
972         gdouble            w, h, x, y;
973         GnomeCanvasPoints *points;
974         GnomeCanvasItem  *item;
975         GnomeCanvasGroup *group;
976
977         gl_debug (DEBUG_VIEW, "START");
978
979         g_return_if_fail (view && GL_IS_VIEW (view));
980         g_return_if_fail (view->label && GL_IS_LABEL(view->label));
981
982         gl_label_get_size (view->label, &w, &h);
983
984         group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
985         view->grid_group = GNOME_CANVAS_GROUP(
986                 gnome_canvas_item_new (group,
987                                        gnome_canvas_group_get_type (),
988                                        "x", 0.0,
989                                        "y", 0.0,
990                                        NULL));
991         points = gnome_canvas_points_new (2);
992
993         points->coords[1] = 0.0;
994         points->coords[3] = h;
995         for ( x=0.0; x < w; x += view->grid_spacing ) {
996                 points->coords[0] = points->coords[2] = x;
997                 item = gnome_canvas_item_new (view->grid_group,
998                                               gnome_canvas_line_get_type (),
999                                               "points", points,
1000                                               "width_pixels", 1,
1001                                               "fill_color_rgba", GRID_COLOR,
1002                                               NULL);
1003         }
1004         points->coords[0] = points->coords[2] = w;
1005         item = gnome_canvas_item_new (view->grid_group,
1006                                       gnome_canvas_line_get_type (),
1007                                       "points", points,
1008                                       "width_pixels", 1,
1009                                       "fill_color_rgba", GRID_COLOR,
1010                                       NULL);
1011
1012         points->coords[0] = 0.0;
1013         points->coords[2] = w;
1014         for ( y=0.0; y < h; y += view->grid_spacing ) {
1015                 points->coords[1] = points->coords[3] = y;
1016                 item = gnome_canvas_item_new (view->grid_group,
1017                                               gnome_canvas_line_get_type (),
1018                                               "points", points,
1019                                               "width_pixels", 1,
1020                                               "fill_color_rgba", GRID_COLOR,
1021                                               NULL);
1022         }
1023         points->coords[1] = points->coords[3] = h;
1024         item = gnome_canvas_item_new (view->grid_group,
1025                                       gnome_canvas_line_get_type (),
1026                                       "points", points,
1027                                       "width_pixels", 1,
1028                                       "fill_color_rgba", GRID_COLOR,
1029                                       NULL);
1030
1031         gnome_canvas_points_free (points);
1032
1033         gl_debug (DEBUG_VIEW, "END");
1034 }
1035
1036 /*---------------------------------------------------------------------------*/
1037 /* PRIVATE.  Draw markup lines.                                              */
1038 /*---------------------------------------------------------------------------*/
1039 static void
1040 draw_markup_layer (glView *view)
1041 {
1042         GnomeCanvasGroup *group;
1043         glLabel          *label;
1044         glTemplate       *template;
1045         GList            *p;
1046         glTemplateMarkup *markup;
1047
1048         group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
1049         view->markup_group = GNOME_CANVAS_GROUP(
1050                 gnome_canvas_item_new (group,
1051                                        gnome_canvas_group_get_type (),
1052                                        "x", 0.0,
1053                                        "y", 0.0,
1054                                        NULL));
1055         label = view->label;
1056         template = gl_label_get_template (label);
1057
1058         for ( p=template->label.any.markups; p != NULL; p=p->next ) {
1059                 markup = (glTemplateMarkup *)p->data;
1060
1061                 switch (markup->type) {
1062                 case GL_TEMPLATE_MARKUP_MARGIN:
1063                         draw_markup_margin (view,
1064                                             (glTemplateMarkupMargin *)markup);
1065                         break;
1066                 case GL_TEMPLATE_MARKUP_LINE:
1067                         draw_markup_line (view,
1068                                           (glTemplateMarkupLine *)markup);
1069                         break;
1070                 default:
1071                         g_warning ("Unknown template markup type");
1072                         break;
1073                 }
1074         }
1075 }
1076
1077 /*---------------------------------------------------------------------------*/
1078 /* PRIVATE.  Draw margin markup.                                             */
1079 /*---------------------------------------------------------------------------*/
1080 static void
1081 draw_markup_margin (glView                 *view,
1082                     glTemplateMarkupMargin *margin)
1083 {
1084         glLabel    *label;
1085         glTemplate *template;
1086
1087         label = view->label;
1088         template = gl_label_get_template (label);
1089
1090         switch (template->label.style) {
1091
1092         case GL_TEMPLATE_STYLE_RECT:
1093                 if (template->label.rect.r == 0.0) {
1094                         /* Square corners. */
1095                         draw_markup_margin_rect (view, margin);
1096                 } else {
1097                         if ( margin->size < template->label.rect.r) {
1098                                 /* Rounded corners. */
1099                                 draw_markup_margin_rounded_rect (view, margin);
1100                         } else {
1101                                 /* Square corners. */
1102                                 draw_markup_margin_rect (view, margin);
1103                         }
1104                 }
1105                 break;
1106
1107         case GL_TEMPLATE_STYLE_ROUND:
1108                 draw_markup_margin_round (view, margin);
1109                 break;
1110
1111         case GL_TEMPLATE_STYLE_CD:
1112                 if ((template->label.cd.w == 0.0) && (template->label.cd.h == 0.0) ) {
1113                         draw_markup_margin_cd (view, margin);
1114                 } else {
1115                         draw_markup_margin_cd_bc (view, margin);
1116                 }
1117                 break;
1118
1119         default:
1120                 g_warning ("Unknown template label style");
1121                 break;
1122         }
1123 }
1124
1125 /*---------------------------------------------------------------------------*/
1126 /* PRIVATE.  Draw simple recangular margin.                                  */
1127 /*---------------------------------------------------------------------------*/
1128 static void
1129 draw_markup_margin_rect (glView                 *view,
1130                          glTemplateMarkupMargin *margin)
1131 {
1132         glLabel          *label = view->label;
1133         glTemplate       *template;
1134         gdouble           w, h, m;
1135         GnomeCanvasItem  *item;
1136
1137         gl_debug (DEBUG_VIEW, "START");
1138
1139         g_return_if_fail (GL_IS_VIEW (view));
1140         g_return_if_fail (label != NULL);
1141
1142         gl_label_get_size (label, &w, &h);
1143         template = gl_label_get_template (label);
1144         m = margin->size;
1145
1146         /* Bounding box @ margin */
1147         gnome_canvas_item_new (view->markup_group,
1148                                gnome_canvas_rect_get_type (),
1149                                "x1", m,
1150                                "y1", m,
1151                                "x2", w - m,
1152                                "y2", h - m,
1153                                "width_pixels", 1,
1154                                "outline_color_rgba", MARKUP_COLOR,
1155                                NULL);
1156
1157         gl_debug (DEBUG_VIEW, "END");
1158 }
1159
1160 /*---------------------------------------------------------------------------*/
1161 /* PRIVATE.  Draw rounded recangular markup.                                 */
1162 /*---------------------------------------------------------------------------*/
1163 static void
1164 draw_markup_margin_rounded_rect (glView                 *view,
1165                                  glTemplateMarkupMargin *margin)
1166 {
1167         glLabel           *label = view->label;
1168         GnomeCanvasPoints *points;
1169         gint               i_coords, i_theta;
1170         glTemplate        *template;
1171         gdouble            r, w, h, m;
1172         GnomeCanvasItem   *item;
1173
1174         gl_debug (DEBUG_VIEW, "START");
1175
1176         g_return_if_fail (GL_IS_VIEW (view));
1177         g_return_if_fail (label != NULL);
1178
1179         gl_label_get_size (label, &w, &h);
1180         template = gl_label_get_template (label);
1181         r = template->label.rect.r;
1182         m = margin->size;
1183
1184         r = r - m;
1185         w = w - 2 * m;
1186         h = h - 2 * m;
1187
1188         /* rectangle with rounded corners */
1189         points = gnome_canvas_points_new (4 * (1 + 90 / ARC_COURSE));
1190         i_coords = 0;
1191         for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
1192                 points->coords[i_coords++] =
1193                         m + r - r * sin (i_theta * G_PI / 180.0);
1194                 points->coords[i_coords++] =
1195                         m + r - r * cos (i_theta * G_PI / 180.0);
1196         }
1197         for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
1198                 points->coords[i_coords++] =
1199                         m + r - r * cos (i_theta * G_PI / 180.0);
1200                 points->coords[i_coords++] =
1201                         m + (h - r) + r * sin (i_theta * G_PI / 180.0);
1202         }
1203         for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
1204                 points->coords[i_coords++] =
1205                         m + (w - r) + r * sin (i_theta * G_PI / 180.0);
1206                 points->coords[i_coords++] =
1207                         m + (h - r) + r * cos (i_theta * G_PI / 180.0);
1208         }
1209         for (i_theta = 0; i_theta <= 90; i_theta += ARC_COURSE) {
1210                 points->coords[i_coords++] =
1211                         m + (w - r) + r * cos (i_theta * G_PI / 180.0);
1212                 points->coords[i_coords++] =
1213                         m + r - r * sin (i_theta * G_PI / 180.0);
1214         }
1215         item = gnome_canvas_item_new (view->markup_group,
1216                                       gnome_canvas_polygon_get_type (),
1217                                       "points", points,
1218                                       "width_pixels", 1,
1219                                       "outline_color_rgba", MARKUP_COLOR,
1220                                       NULL);
1221         gnome_canvas_points_free (points);
1222
1223         gl_debug (DEBUG_VIEW, "END");
1224 }
1225
1226 /*---------------------------------------------------------------------------*/
1227 /* PRIVATE.  Draw round margin.                                              */
1228 /*---------------------------------------------------------------------------*/
1229 static void
1230 draw_markup_margin_round (glView                 *view,
1231                           glTemplateMarkupMargin *margin)
1232 {
1233         glLabel          *label = view->label;
1234         glTemplate       *template;
1235         gdouble           r, m;
1236         GnomeCanvasItem  *item;
1237
1238         gl_debug (DEBUG_VIEW, "START");
1239
1240         g_return_if_fail (GL_IS_VIEW (view));
1241         g_return_if_fail (label != NULL);
1242
1243         template = gl_label_get_template (label);
1244
1245         r = template->label.round.r;
1246         m = margin->size;
1247
1248         /* Margin outline */
1249         item = gnome_canvas_item_new (view->markup_group,
1250                                       gnome_canvas_ellipse_get_type (),
1251                                       "x1", m,
1252                                       "y1", m,
1253                                       "x2", 2.0*r - m,
1254                                       "y2", 2.0*r - m,
1255                                       "width_pixels", 1,
1256                                       "outline_color_rgba", MARKUP_COLOR,
1257                                       NULL);
1258
1259         gl_debug (DEBUG_VIEW, "END");
1260 }
1261
1262 /*---------------------------------------------------------------------------*/
1263 /* PRIVATE.  Draw CD margins.                                                */
1264 /*---------------------------------------------------------------------------*/
1265 static void
1266 draw_markup_margin_cd (glView                 *view,
1267                        glTemplateMarkupMargin *margin)
1268 {
1269         glLabel          *label = view->label;
1270         glTemplate       *template;
1271         gdouble           m, r1, r2;
1272         GnomeCanvasItem  *item;
1273
1274         gl_debug (DEBUG_VIEW, "START");
1275
1276         g_return_if_fail (GL_IS_VIEW (view));
1277         g_return_if_fail (label != NULL);
1278
1279         template = gl_label_get_template (label);
1280
1281         r1 = template->label.cd.r1;
1282         r2 = template->label.cd.r2;
1283         m  = margin->size;
1284
1285         /* outer margin */
1286         item = gnome_canvas_item_new (view->markup_group,
1287                                       gnome_canvas_ellipse_get_type (),
1288                                       "x1", m,
1289                                       "y1", m,
1290                                       "x2", 2.0*r1 - m,
1291                                       "y2", 2.0*r1 - m,
1292                                       "width_pixels", 1,
1293                                       "outline_color_rgba", MARKUP_COLOR,
1294                                       NULL);
1295         /* inner margin */
1296         item = gnome_canvas_item_new (view->markup_group,
1297                                       gnome_canvas_ellipse_get_type (),
1298                                       "x1", r1 - r2 - m,
1299                                       "y1", r1 - r2 - m,
1300                                       "x2", r1 + r2 + m,
1301                                       "y2", r1 + r2 + m,
1302                                       "width_pixels", 1,
1303                                       "outline_color_rgba", MARKUP_COLOR,
1304                                       NULL);
1305
1306         gl_debug (DEBUG_VIEW, "END");
1307 }
1308
1309 /*---------------------------------------------------------------------------*/
1310 /* PRIVATE.  Draw Business Card CD margins.                                  */
1311 /*---------------------------------------------------------------------------*/
1312 static void
1313 draw_markup_margin_cd_bc (glView                 *view,
1314                           glTemplateMarkupMargin *margin)
1315 {
1316         glLabel           *label = view->label;
1317         glTemplate        *template;
1318         gdouble            m, r1, r2;
1319         GnomeCanvasPoints *points;
1320         gint               i_coords, i_theta;
1321         gdouble            theta1, theta2;
1322         gdouble            x0, y0, w, h, r;
1323         GnomeCanvasItem   *item;
1324
1325         gl_debug (DEBUG_VIEW, "START");
1326
1327         g_return_if_fail (GL_IS_VIEW (view));
1328         g_return_if_fail (label != NULL);
1329
1330         template = gl_label_get_template (label);
1331         gl_label_get_size (label, &w, &h);
1332         x0 = w/2.0;
1333         y0 = h/2.0;
1334
1335         r1 = template->label.cd.r1;
1336         r2 = template->label.cd.r2;
1337         m  = margin->size;
1338
1339         /* outer margin */
1340         r = r1 - m;
1341         theta1 = (180.0/G_PI) * acos (w / (2.0*r1));
1342         theta2 = (180.0/G_PI) * asin (h / (2.0*r1));
1343
1344         points = gnome_canvas_points_new (360/ARC_FINE + 1);
1345         i_coords = 0;
1346
1347         points->coords[i_coords++] = x0 + r * cos (theta1 * G_PI / 180.0);
1348         points->coords[i_coords++] = y0 + r * sin (theta1 * G_PI / 180.0);
1349
1350         for ( i_theta = theta1 + ARC_FINE; i_theta < theta2; i_theta +=ARC_FINE ) {
1351                 points->coords[i_coords++] = x0 + r * cos (i_theta * G_PI / 180.0);
1352                 points->coords[i_coords++] = y0 + r * sin (i_theta * G_PI / 180.0);
1353         }
1354
1355         points->coords[i_coords++] = x0 + r * cos (theta2 * G_PI / 180.0);
1356         points->coords[i_coords++] = y0 + r * sin (theta2 * G_PI / 180.0);
1357
1358
1359         if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
1360                 points->coords[i_coords++] = x0 + r * cos ((180-theta2) * G_PI / 180.0);
1361                 points->coords[i_coords++] = y0 + r * sin ((180-theta2) * G_PI / 180.0);
1362         }
1363
1364         for ( i_theta = 180-theta2+ARC_FINE; i_theta < (180-theta1); i_theta +=ARC_FINE ) {
1365                 points->coords[i_coords++] = x0 + r * cos (i_theta * G_PI / 180.0);
1366                 points->coords[i_coords++] = y0 + r * sin (i_theta * G_PI / 180.0);
1367         }
1368
1369         points->coords[i_coords++] = x0 + r * cos ((180-theta1) * G_PI / 180.0);
1370         points->coords[i_coords++] = y0 + r * sin ((180-theta1) * G_PI / 180.0);
1371
1372         if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
1373                 points->coords[i_coords++] = x0 + r * cos ((180+theta1) * G_PI / 180.0);
1374                 points->coords[i_coords++] = y0 + r * sin ((180+theta1) * G_PI / 180.0);
1375         }
1376
1377         for ( i_theta = 180+theta1+ARC_FINE; i_theta < (180+theta2); i_theta +=ARC_FINE ) {
1378                 points->coords[i_coords++] = x0 + r * cos (i_theta * G_PI / 180.0);
1379                 points->coords[i_coords++] = y0 + r * sin (i_theta * G_PI / 180.0);
1380         }
1381
1382         points->coords[i_coords++] = x0 + r * cos ((180+theta2) * G_PI / 180.0);
1383         points->coords[i_coords++] = y0 + r * sin ((180+theta2) * G_PI / 180.0);
1384
1385         if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
1386                 points->coords[i_coords++] = x0 + r * cos ((360-theta2) * G_PI / 180.0);
1387                 points->coords[i_coords++] = y0 + r * sin ((360-theta2) * G_PI / 180.0);
1388         }
1389
1390         for ( i_theta = 360-theta2+ARC_FINE; i_theta < (360-theta1); i_theta +=ARC_FINE ) {
1391                 points->coords[i_coords++] = x0 + r * cos (i_theta * G_PI / 180.0);
1392                 points->coords[i_coords++] = y0 + r * sin (i_theta * G_PI / 180.0);
1393         }
1394
1395         if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
1396                 points->coords[i_coords++] = x0 + r * cos ((360-theta1) * G_PI / 180.0);
1397                 points->coords[i_coords++] = y0 + r * sin ((360-theta1) * G_PI / 180.0);
1398         }
1399
1400         points->num_points = i_coords / 2;
1401
1402         item = gnome_canvas_item_new (view->markup_group,
1403                                       gnome_canvas_polygon_get_type (),
1404                                       "points", points,
1405                                       "width_pixels", 1,
1406                                       "outline_color_rgba", MARKUP_COLOR,
1407                                       NULL);
1408
1409         gnome_canvas_points_free (points);
1410
1411         /* inner margin */
1412         item = gnome_canvas_item_new (view->markup_group,
1413                                       gnome_canvas_ellipse_get_type (),
1414                                       "x1", x0 - r2 - m,
1415                                       "y1", y0 - r2 - m,
1416                                       "x2", x0 + r2 + m,
1417                                       "y2", y0 + r2 + m,
1418                                       "width_pixels", 1,
1419                                       "outline_color_rgba", MARKUP_COLOR,
1420                                       NULL);
1421
1422         gl_debug (DEBUG_VIEW, "END");
1423 }
1424
1425 /*---------------------------------------------------------------------------*/
1426 /* PRIVATE.  Draw line markup.                                               */
1427 /*---------------------------------------------------------------------------*/
1428 static void
1429 draw_markup_line (glView               *view,
1430                   glTemplateMarkupLine *line)
1431 {
1432         GnomeCanvasPoints *points;
1433
1434         gl_debug (DEBUG_VIEW, "START");
1435
1436         g_return_if_fail (GL_IS_VIEW (view));
1437
1438         points = gnome_canvas_points_new (2);
1439         points->coords[0] = line->x1;
1440         points->coords[1] = line->y1;
1441         points->coords[2] = line->x2;
1442         points->coords[3] = line->y2;
1443
1444         /* Bounding box @ margin */
1445         gnome_canvas_item_new (view->markup_group,
1446                                gnome_canvas_line_get_type (),
1447                                "points", points,
1448                                "width_pixels", 1,
1449                                "fill_color_rgba", MARKUP_COLOR,
1450                                NULL);
1451
1452         gnome_canvas_points_free (points);
1453
1454         gl_debug (DEBUG_VIEW, "END");
1455 }
1456
1457 /*****************************************************************************/
1458 /* Show grid.                                                                */
1459 /*****************************************************************************/
1460 void       gl_view_show_grid               (glView            *view)
1461 {
1462         gnome_canvas_item_show (GNOME_CANVAS_ITEM(view->grid_group));
1463 }
1464
1465 /*****************************************************************************/
1466 /* Hide grid.                                                                */
1467 /*****************************************************************************/
1468 void       gl_view_hide_grid               (glView            *view)
1469 {
1470         gnome_canvas_item_hide (GNOME_CANVAS_ITEM(view->grid_group));
1471 }
1472
1473 /*****************************************************************************/
1474 /* Set grid spacing.                                                         */
1475 /*****************************************************************************/
1476 void       gl_view_set_grid_spacing        (glView            *view,
1477                                             gdouble            spacing)
1478 {
1479         view->grid_spacing = spacing;
1480
1481         gtk_object_destroy (GTK_OBJECT(view->grid_group));
1482         draw_grid_layer (view);
1483 }
1484
1485 /*****************************************************************************/
1486 /* Show markup.                                                              */
1487 /*****************************************************************************/
1488 void       gl_view_show_markup             (glView            *view)
1489 {
1490         gnome_canvas_item_show (GNOME_CANVAS_ITEM(view->markup_group));
1491 }
1492
1493 /*****************************************************************************/
1494 /* Hide markup.                                                              */
1495 /*****************************************************************************/
1496 void       gl_view_hide_markup             (glView            *view)
1497 {
1498         gnome_canvas_item_hide (GNOME_CANVAS_ITEM(view->markup_group));
1499 }
1500
1501 /*****************************************************************************/
1502 /* Set arrow mode.                                                           */
1503 /*****************************************************************************/
1504 void
1505 gl_view_arrow_mode (glView *view)
1506 {
1507         static GdkCursor *cursor = NULL;
1508
1509         gl_debug (DEBUG_VIEW, "START");
1510
1511         g_return_if_fail (GL_IS_VIEW (view));
1512
1513         if (!cursor) {
1514                 cursor = gdk_cursor_new (GDK_LEFT_PTR);
1515         }
1516
1517         gdk_window_set_cursor (view->canvas->window, cursor);
1518
1519         view->state = GL_VIEW_STATE_ARROW;
1520
1521         gl_debug (DEBUG_VIEW, "END");
1522 }
1523
1524 /*****************************************************************************/
1525 /* Set create text object mode.                                              */
1526 /*****************************************************************************/
1527 void
1528 gl_view_object_create_mode (glView            *view,
1529                             glLabelObjectType type)
1530 {
1531         GdkCursor *cursor;
1532
1533         gl_debug (DEBUG_VIEW, "START");
1534
1535         g_return_if_fail (GL_IS_VIEW (view));
1536
1537         switch (type) {
1538         case GL_LABEL_OBJECT_BOX:
1539                 cursor = gl_view_box_get_create_cursor ();
1540                 break;
1541         case GL_LABEL_OBJECT_ELLIPSE:
1542                 cursor = gl_view_ellipse_get_create_cursor ();
1543                 break;
1544         case GL_LABEL_OBJECT_LINE:
1545                 cursor = gl_view_line_get_create_cursor ();
1546                 break;
1547         case GL_LABEL_OBJECT_IMAGE:
1548                 cursor = gl_view_image_get_create_cursor ();
1549                 break;
1550         case GL_LABEL_OBJECT_TEXT:
1551                 cursor = gl_view_text_get_create_cursor ();
1552                 break;
1553         case GL_LABEL_OBJECT_BARCODE:
1554                 cursor = gl_view_barcode_get_create_cursor ();
1555                 break;
1556         default:
1557                 g_warning ("Invalid label object type.");/*Should not happen!*/
1558                 break;
1559         }
1560
1561         gdk_window_set_cursor (view->canvas->window, cursor);
1562
1563         view->state = GL_VIEW_STATE_OBJECT_CREATE;
1564         view->create_type = type;
1565
1566         gl_debug (DEBUG_VIEW, "END");
1567 }
1568
1569 /*****************************************************************************/
1570 /* Select given object (adding to current selection).                        */
1571 /*****************************************************************************/
1572 void
1573 gl_view_select_object (glView       *view,
1574                        glViewObject *view_object)
1575 {
1576         gl_debug (DEBUG_VIEW, "START");
1577
1578         select_object_real (view, view_object);
1579
1580         g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1581
1582         gl_debug (DEBUG_VIEW, "END");
1583 }
1584
1585 /*****************************************************************************/
1586 /* Unselect given object (removing from current selection).                  */
1587 /*****************************************************************************/
1588 void
1589 gl_view_unselect_object (glView       *view,
1590                          glViewObject *view_object)
1591 {
1592         gl_debug (DEBUG_VIEW, "START");
1593
1594         unselect_object_real (view, view_object);
1595
1596         g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1597
1598         gl_debug (DEBUG_VIEW, "END");
1599 }
1600
1601 /*****************************************************************************/
1602 /* Select all items.                                                         */
1603 /*****************************************************************************/
1604 void
1605 gl_view_select_all (glView *view)
1606 {
1607         GList *p, *p_next;
1608
1609         gl_debug (DEBUG_VIEW, "START");
1610
1611         g_return_if_fail (GL_IS_VIEW (view));
1612
1613         /* 1st unselect anything already selected. */
1614         for (p = view->selected_object_list; p != NULL; p = p_next) {
1615                 p_next = p->next;
1616                 unselect_object_real (view, GL_VIEW_OBJECT (p->data));
1617         }
1618
1619         /* Finally select all objects. */
1620         for (p = view->object_list; p != NULL; p = p->next) {
1621                 select_object_real (view, GL_VIEW_OBJECT (p->data));
1622         }
1623
1624         g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1625
1626         gl_debug (DEBUG_VIEW, "END");
1627 }
1628
1629 /*****************************************************************************/
1630 /* Remove all selections                                                     */
1631 /*****************************************************************************/
1632 void
1633 gl_view_unselect_all (glView *view)
1634 {
1635         GList *p, *p_next;
1636
1637         gl_debug (DEBUG_VIEW, "START");
1638
1639         g_return_if_fail (GL_IS_VIEW (view));
1640
1641         for (p = view->selected_object_list; p != NULL; p = p_next) {
1642                 p_next = p->next;
1643                 unselect_object_real (view, GL_VIEW_OBJECT (p->data));
1644         }
1645
1646         g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1647
1648         gl_debug (DEBUG_VIEW, "END");
1649 }
1650
1651 /*****************************************************************************/
1652 /* Select all objects within given rectangular region (adding to selection). */
1653 /*****************************************************************************/
1654 void
1655 gl_view_select_region (glView  *view,
1656                        gdouble  x1,
1657                        gdouble  y1,
1658                        gdouble  x2,
1659                        gdouble  y2)
1660 {
1661         GList *p;
1662         glViewObject *view_object;
1663         glLabelObject *object;
1664         gdouble i_x1, i_y1, i_x2, i_y2;
1665
1666         gl_debug (DEBUG_VIEW, "START");
1667
1668         g_return_if_fail (GL_IS_VIEW (view));
1669         g_return_if_fail ((x1 <= x2) && (y1 <= y2));
1670
1671         for (p = view->object_list; p != NULL; p = p->next) {
1672                 view_object = GL_VIEW_OBJECT(p->data);
1673                 if (!gl_view_is_object_selected (view, view_object)) {
1674
1675                         object = gl_view_object_get_object (view_object);
1676
1677                         gl_label_object_get_extent (object, &i_x1, &i_y1, &i_x2, &i_y2);
1678                         if ((i_x1 >= x1) && (i_x2 <= x2) && (i_y1 >= y1)
1679                             && (i_y2 <= y2)) {
1680                                 select_object_real (view, view_object);
1681                         }
1682
1683                 }
1684         }
1685
1686         g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1687
1688         gl_debug (DEBUG_VIEW, "END");
1689 }
1690
1691 /*---------------------------------------------------------------------------*/
1692 /* PRIVATE. Select an object.                                                */
1693 /*---------------------------------------------------------------------------*/
1694 static void
1695 select_object_real (glView       *view,
1696                     glViewObject *view_object)
1697 {
1698         gl_debug (DEBUG_VIEW, "START");
1699
1700         g_return_if_fail (GL_IS_VIEW (view));
1701         g_return_if_fail (GL_IS_VIEW_OBJECT (view_object));
1702
1703         if (!gl_view_is_object_selected (view, view_object)) {
1704                 view->selected_object_list =
1705                     g_list_prepend (view->selected_object_list, view_object);
1706         }
1707         gl_view_object_show_highlight (view_object);
1708         gtk_widget_grab_focus (GTK_WIDGET (view->canvas));
1709
1710         gl_debug (DEBUG_VIEW, "END");
1711 }
1712
1713 /*---------------------------------------------------------------------------*/
1714 /* PRIVATE.  Un-select object.                                               */
1715 /*---------------------------------------------------------------------------*/
1716 static void
1717 unselect_object_real (glView       *view,
1718                       glViewObject *view_object)
1719 {
1720         gl_debug (DEBUG_VIEW, "START");
1721
1722         g_return_if_fail (GL_IS_VIEW (view));
1723         g_return_if_fail (GL_IS_VIEW_OBJECT (view_object));
1724
1725         gl_view_object_hide_highlight (view_object);
1726
1727         view->selected_object_list =
1728             g_list_remove (view->selected_object_list, view_object);
1729
1730         gl_debug (DEBUG_VIEW, "END");
1731 }
1732
1733 /*---------------------------------------------------------------------------*/
1734 /* PRIVATE. Return object at (x,y).                                          */
1735 /*---------------------------------------------------------------------------*/
1736 static gboolean
1737 object_at (glView  *view,
1738            gdouble  x,
1739            gdouble  y)
1740 {
1741         GnomeCanvasItem *item, *p_item;
1742         GList *p;
1743
1744         gl_debug (DEBUG_VIEW, "");
1745
1746         g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
1747
1748         item = gnome_canvas_get_item_at (GNOME_CANVAS (view->canvas), x, y);
1749
1750         /* No item is at x, y */
1751         if (item == NULL)
1752                 return FALSE;
1753
1754         /* ignore items not in label or highlight layers, e.g. background items */
1755         if (!is_item_member_of_group(view, item, GNOME_CANVAS_ITEM(view->label_group)) &&
1756             !is_item_member_of_group(view, item, GNOME_CANVAS_ITEM(view->highlight_group)))
1757                 return FALSE;
1758
1759         return TRUE;
1760 }
1761
1762 /*---------------------------------------------------------------------------*/
1763 /* PRIVATE.  Is the item a child (or grandchild, etc.) of group.             */
1764 /*---------------------------------------------------------------------------*/
1765 static gboolean
1766 is_item_member_of_group (glView          *view,
1767                          GnomeCanvasItem *item,
1768                          GnomeCanvasItem *group)
1769 {
1770         GnomeCanvasItem *parent;
1771         GnomeCanvasItem *root_group;
1772
1773         root_group = GNOME_CANVAS_ITEM(gnome_canvas_root (GNOME_CANVAS (view->canvas)));
1774
1775         for ( parent=item->parent; parent && (parent!=root_group); parent=parent->parent) {
1776                 if (parent == group) return TRUE;
1777         }
1778         return FALSE;
1779 }
1780
1781 /*****************************************************************************/
1782 /* Is the object in our current selection?                                   */
1783 /*****************************************************************************/
1784 gboolean
1785 gl_view_is_object_selected (glView       *view,
1786                     glViewObject *view_object)
1787 {
1788         gl_debug (DEBUG_VIEW, "");
1789
1790         g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
1791         g_return_val_if_fail (GL_IS_VIEW_OBJECT (view_object), FALSE);
1792
1793         if (g_list_find (view->selected_object_list, view_object) == NULL) {
1794                 return FALSE;
1795         }
1796         return TRUE;
1797 }
1798
1799 /*****************************************************************************/
1800 /* Is our current selection empty?                                           */
1801 /*****************************************************************************/
1802 gboolean
1803 gl_view_is_selection_empty (glView *view)
1804 {
1805         gl_debug (DEBUG_VIEW, "");
1806
1807         g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
1808
1809         if (view->selected_object_list == NULL) {
1810                 return TRUE;
1811         } else {
1812                 return FALSE;
1813         }
1814 }
1815
1816 /*****************************************************************************/
1817 /* Is our current selection atomic?  I.e. only one item selected.            */
1818 /*****************************************************************************/
1819 gboolean
1820 gl_view_is_selection_atomic (glView *view)
1821 {
1822         gl_debug (DEBUG_VIEW, "");
1823
1824         g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
1825
1826         if (view->selected_object_list == NULL)
1827                 return FALSE;
1828         if (view->selected_object_list->next == NULL)
1829                 return TRUE;
1830         return FALSE;
1831 }
1832
1833 /*****************************************************************************/
1834 /* Delete selected objects. (Bypass clipboard)                               */
1835 /*****************************************************************************/
1836 void
1837 gl_view_delete_selection (glView *view)
1838 {
1839         GList *p, *p_next;
1840
1841         gl_debug (DEBUG_VIEW, "START");
1842
1843         g_return_if_fail (GL_IS_VIEW (view));
1844
1845         for (p = view->selected_object_list; p != NULL; p = p_next) {
1846                 p_next = p->next;
1847                 g_object_unref (G_OBJECT (p->data));
1848         }
1849
1850         g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1851
1852         gl_debug (DEBUG_VIEW, "END");
1853 }
1854
1855 /*****************************************************************************/
1856 /* Edit properties of selected object.                                       */
1857 /*****************************************************************************/
1858 void
1859 gl_view_edit_object_props (glView *view)
1860 {
1861         glViewObject *view_object;
1862
1863         gl_debug (DEBUG_VIEW, "START");
1864
1865         g_return_if_fail (GL_IS_VIEW (view));
1866
1867         if (gl_view_is_selection_atomic (view)) {
1868
1869                 view_object = GL_VIEW_OBJECT(view->selected_object_list->data);
1870                 gl_view_object_show_dialog (view_object);
1871
1872         }
1873
1874         gl_debug (DEBUG_VIEW, "END");
1875 }
1876
1877 /*****************************************************************************/
1878 /* Raise selected items to top.                                              */
1879 /*****************************************************************************/
1880 void
1881 gl_view_raise_selection (glView *view)
1882 {
1883         GList         *p;
1884         glViewObject  *view_object;
1885         glLabelObject *object;
1886
1887         gl_debug (DEBUG_VIEW, "START");
1888
1889         g_return_if_fail (GL_IS_VIEW (view));
1890
1891         for (p = view->selected_object_list; p != NULL; p = p->next) {
1892                 view_object = GL_VIEW_OBJECT (p->data);
1893                 object = gl_view_object_get_object (view_object);
1894                 gl_label_object_raise_to_top (object);
1895         }
1896
1897         gl_debug (DEBUG_VIEW, "END");
1898 }
1899
1900 /*****************************************************************************/
1901 /* Lower selected items to bottom.                                           */
1902 /*****************************************************************************/
1903 void
1904 gl_view_lower_selection (glView *view)
1905 {
1906         GList         *p;
1907         glViewObject  *view_object;
1908         glLabelObject *object;
1909
1910         gl_debug (DEBUG_VIEW, "START");
1911
1912         g_return_if_fail (GL_IS_VIEW (view));
1913
1914         for (p = view->selected_object_list; p != NULL; p = p->next) {
1915                 view_object = GL_VIEW_OBJECT (p->data);
1916                 object = gl_view_object_get_object (view_object);
1917                 gl_label_object_lower_to_bottom (object);
1918         }
1919
1920         gl_debug (DEBUG_VIEW, "END");
1921 }
1922
1923 /*****************************************************************************/
1924 /* Rotate selected objects by given angle.                                   */
1925 /*****************************************************************************/
1926 void
1927 gl_view_rotate_selection (glView *view,
1928                           gdouble theta_degs)
1929 {
1930         GList         *p;
1931         glViewObject  *view_object;
1932         glLabelObject *object;
1933
1934         gl_debug (DEBUG_VIEW, "START");
1935
1936         g_return_if_fail (GL_IS_VIEW (view));
1937
1938         for (p = view->selected_object_list; p != NULL; p = p->next) {
1939                 view_object = GL_VIEW_OBJECT (p->data);
1940                 object = gl_view_object_get_object (view_object);
1941                 gl_label_object_rotate (object, theta_degs);
1942         }
1943
1944         gl_debug (DEBUG_VIEW, "END");
1945 }
1946
1947 /*****************************************************************************/
1948 /* Rotate selected objects 90 degrees left.                                  */
1949 /*****************************************************************************/
1950 void
1951 gl_view_rotate_selection_left (glView *view)
1952 {
1953         GList         *p;
1954         glViewObject  *view_object;
1955         glLabelObject *object;
1956
1957         gl_debug (DEBUG_VIEW, "START");
1958
1959         g_return_if_fail (GL_IS_VIEW (view));
1960
1961         for (p = view->selected_object_list; p != NULL; p = p->next) {
1962                 view_object = GL_VIEW_OBJECT (p->data);
1963                 object = gl_view_object_get_object (view_object);
1964                 gl_label_object_rotate (object, -90.0);
1965         }
1966
1967         gl_debug (DEBUG_VIEW, "END");
1968 }
1969
1970 /*****************************************************************************/
1971 /* Rotate selected objects 90 degrees right.                                 */
1972 /*****************************************************************************/
1973 void
1974 gl_view_rotate_selection_right (glView *view)
1975 {
1976         GList         *p;
1977         glViewObject  *view_object;
1978         glLabelObject *object;
1979
1980         gl_debug (DEBUG_VIEW, "START");
1981
1982         g_return_if_fail (GL_IS_VIEW (view));
1983
1984         for (p = view->selected_object_list; p != NULL; p = p->next) {
1985                 view_object = GL_VIEW_OBJECT (p->data);
1986                 object = gl_view_object_get_object (view_object);
1987                 gl_label_object_rotate (object, 90.0);
1988         }
1989
1990         gl_debug (DEBUG_VIEW, "END");
1991 }
1992
1993 /*****************************************************************************/
1994 /* Flip selected objects horizontally.                                       */
1995 /*****************************************************************************/
1996 void
1997 gl_view_flip_selection_horiz (glView *view)
1998 {
1999         GList         *p;
2000         glViewObject  *view_object;
2001         glLabelObject *object;
2002
2003         gl_debug (DEBUG_VIEW, "START");
2004
2005         g_return_if_fail (GL_IS_VIEW (view));
2006
2007         for (p = view->selected_object_list; p != NULL; p = p->next) {
2008                 view_object = GL_VIEW_OBJECT (p->data);
2009                 object = gl_view_object_get_object (view_object);
2010                 gl_label_object_flip_horiz (object);
2011         }
2012
2013         gl_debug (DEBUG_VIEW, "END");
2014 }
2015
2016 /*****************************************************************************/
2017 /* Flip selected objects vertically.                                         */
2018 /*****************************************************************************/
2019 void
2020 gl_view_flip_selection_vert (glView *view)
2021 {
2022         GList         *p;
2023         glViewObject  *view_object;
2024         glLabelObject *object;
2025
2026         gl_debug (DEBUG_VIEW, "START");
2027
2028         g_return_if_fail (GL_IS_VIEW (view));
2029
2030         for (p = view->selected_object_list; p != NULL; p = p->next) {
2031                 view_object = GL_VIEW_OBJECT (p->data);
2032                 object = gl_view_object_get_object (view_object);
2033                 gl_label_object_flip_vert (object);
2034         }
2035
2036         gl_debug (DEBUG_VIEW, "END");
2037 }
2038
2039 /*****************************************************************************/
2040 /* Align selected objects to left most edge.                                 */
2041 /*****************************************************************************/
2042 void
2043 gl_view_align_selection_left (glView *view)
2044 {
2045         GList         *p;
2046         glViewObject  *view_object;
2047         glLabelObject *object;
2048         gdouble        dx, x1min, x1, y1, x2, y2;
2049
2050         gl_debug (DEBUG_VIEW, "START");
2051
2052         g_return_if_fail (GL_IS_VIEW (view));
2053
2054         g_return_if_fail (!gl_view_is_selection_empty (view) &&
2055                           !gl_view_is_selection_atomic (view));
2056
2057         /* find left most edge */
2058         p = view->selected_object_list;
2059         view_object = GL_VIEW_OBJECT (p->data);
2060         object = gl_view_object_get_object (view_object);
2061         gl_label_object_get_extent (object, &x1min, &y1, &x2, &y2);
2062         for (p = p->next; p != NULL; p = p->next) {
2063                 view_object = GL_VIEW_OBJECT (p->data);
2064                 object = gl_view_object_get_object (view_object);
2065                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2066                 if ( x1 < x1min ) x1min = x1;
2067         }
2068
2069         /* now adjust the object positions to line up the left edges */
2070         for (p = view->selected_object_list; p != NULL; p = p->next) {
2071                 view_object = GL_VIEW_OBJECT (p->data);
2072                 object = gl_view_object_get_object (view_object);
2073                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2074                 dx = x1min - x1;
2075                 gl_label_object_set_position_relative (object, dx, 0.0);
2076         }
2077
2078         gl_debug (DEBUG_VIEW, "END");
2079 }
2080
2081
2082 /*****************************************************************************/
2083 /* Align selected objects to right most edge.                                */
2084 /*****************************************************************************/
2085 void
2086 gl_view_align_selection_right (glView *view)
2087 {
2088         GList         *p;
2089         glViewObject  *view_object;
2090         glLabelObject *object;
2091         gdouble        dx, x2max, x1, y1, x2, y2;
2092
2093         gl_debug (DEBUG_VIEW, "START");
2094
2095         g_return_if_fail (GL_IS_VIEW (view));
2096
2097         g_return_if_fail (!gl_view_is_selection_empty (view) &&
2098                           !gl_view_is_selection_atomic (view));
2099
2100         /* find right most edge */
2101         p = view->selected_object_list;
2102         view_object = GL_VIEW_OBJECT (p->data);
2103         object = gl_view_object_get_object (view_object);
2104         gl_label_object_get_extent (object, &x1, &y1, &x2max, &y2);
2105         for (p = p->next; p != NULL; p = p->next) {
2106                 view_object = GL_VIEW_OBJECT (p->data);
2107                 object = gl_view_object_get_object (view_object);
2108                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2109                 if ( x2 > x2max ) x2max = x2;
2110         }
2111
2112         /* now adjust the object positions to line up the right edges */
2113         for (p = view->selected_object_list; p != NULL; p = p->next) {
2114                 view_object = GL_VIEW_OBJECT (p->data);
2115                 object = gl_view_object_get_object (view_object);
2116                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2117                 dx = x2max - x2;
2118                 gl_label_object_set_position_relative (object, dx, 0.0);
2119         }
2120
2121         gl_debug (DEBUG_VIEW, "END");
2122 }
2123
2124 /*****************************************************************************/
2125 /* Align selected objects to horizontal center of objects.                   */
2126 /*****************************************************************************/
2127 void
2128 gl_view_align_selection_hcenter (glView *view)
2129 {
2130         GList         *p;
2131         glViewObject  *view_object;
2132         glLabelObject *object;
2133         gdouble        dx, dxmin, xsum, xavg, xcenter, x1, y1, x2, y2;
2134         gint           n;
2135
2136         gl_debug (DEBUG_VIEW, "START");
2137
2138         g_return_if_fail (GL_IS_VIEW (view));
2139
2140         g_return_if_fail (!gl_view_is_selection_empty (view) &&
2141                           !gl_view_is_selection_atomic (view));
2142
2143         /* find average center of objects */
2144         xsum = 0.0;
2145         n = 0;
2146         for (p = view->selected_object_list; p != NULL; p = p->next) {
2147                 view_object = GL_VIEW_OBJECT (p->data);
2148                 object = gl_view_object_get_object (view_object);
2149                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2150                 xsum += (x1 + x2) / 2.0;
2151                 n++;
2152         }
2153         xavg = xsum / n;
2154
2155         /* find center of object closest to average center */
2156         p = view->selected_object_list;
2157         view_object = GL_VIEW_OBJECT (p->data);
2158         object = gl_view_object_get_object (view_object);
2159         gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2160         dxmin = fabs (xavg - (x1 + x2)/2.0);
2161         xcenter = (x1 + x2)/2.0;
2162         for (p = p->next; p != NULL; p = p->next) {
2163                 view_object = GL_VIEW_OBJECT (p->data);
2164                 object = gl_view_object_get_object (view_object);
2165                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2166                 dx = fabs (xavg - (x1 + x2)/2.0);
2167                 if ( dx < dxmin ) {
2168                         dxmin = dx;
2169                         xcenter = (x1 + x2)/2.0;
2170                 }
2171         }
2172
2173         /* now adjust the object positions to line up this center */
2174         for (p = view->selected_object_list; p != NULL; p = p->next) {
2175                 view_object = GL_VIEW_OBJECT (p->data);
2176                 object = gl_view_object_get_object (view_object);
2177                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2178                 dx = xcenter - (x1 + x2)/2.0;
2179                 gl_label_object_set_position_relative (object, dx, 0.0);
2180         }
2181
2182         gl_debug (DEBUG_VIEW, "END");
2183 }
2184
2185 /*****************************************************************************/
2186 /* Align selected objects to top most edge.                                  */
2187 /*****************************************************************************/
2188 void
2189 gl_view_align_selection_top (glView *view)
2190 {
2191         GList         *p;
2192         glViewObject  *view_object;
2193         glLabelObject *object;
2194         gdouble        dy, y1min, x1, y1, x2, y2;
2195
2196         gl_debug (DEBUG_VIEW, "START");
2197
2198         g_return_if_fail (GL_IS_VIEW (view));
2199
2200         g_return_if_fail (!gl_view_is_selection_empty (view) &&
2201                           !gl_view_is_selection_atomic (view));
2202
2203         /* find top most edge */
2204         p = view->selected_object_list;
2205         view_object = GL_VIEW_OBJECT (p->data);
2206         object = gl_view_object_get_object (view_object);
2207         gl_label_object_get_extent (object, &x1, &y1min, &x2, &y2);
2208         for (p = p->next; p != NULL; p = p->next) {
2209                 view_object = GL_VIEW_OBJECT (p->data);
2210                 object = gl_view_object_get_object (view_object);
2211                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2212                 if ( y1 < y1min ) y1min = y1;
2213         }
2214
2215         /* now adjust the object positions to line up the top edges */
2216         for (p = view->selected_object_list; p != NULL; p = p->next) {
2217                 view_object = GL_VIEW_OBJECT (p->data);
2218                 object = gl_view_object_get_object (view_object);
2219                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2220                 dy = y1min - y1;
2221                 gl_label_object_set_position_relative (object, 0.0, dy);
2222         }
2223
2224         gl_debug (DEBUG_VIEW, "END");
2225 }
2226
2227 /*****************************************************************************/
2228 /* Align selected objects to bottom most edge.                               */
2229 /*****************************************************************************/
2230 void
2231 gl_view_align_selection_bottom (glView *view)
2232 {
2233         GList         *p;
2234         glViewObject  *view_object;
2235         glLabelObject *object;
2236         gdouble        dy, y2max, x1, y1, x2, y2;
2237
2238         gl_debug (DEBUG_VIEW, "START");
2239
2240         g_return_if_fail (GL_IS_VIEW (view));
2241
2242         g_return_if_fail (!gl_view_is_selection_empty (view) &&
2243                           !gl_view_is_selection_atomic (view));
2244
2245         /* find bottom most edge */
2246         p = view->selected_object_list;
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, &y2max);
2250         for (p = p->next; p != NULL; p = p->next) {
2251                 view_object = GL_VIEW_OBJECT (p->data);
2252                 object = gl_view_object_get_object (view_object);
2253                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2254                 if ( y2 > y2max ) y2max = y2;
2255         }
2256
2257         /* now adjust the object positions to line up the bottom edges */
2258         for (p = view->selected_object_list; p != NULL; p = p->next) {
2259                 view_object = GL_VIEW_OBJECT (p->data);
2260                 object = gl_view_object_get_object (view_object);
2261                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2262                 dy = y2max - y2;
2263                 gl_label_object_set_position_relative (object, 0.0, dy);
2264         }
2265
2266         gl_debug (DEBUG_VIEW, "END");
2267 }
2268
2269 /*****************************************************************************/
2270 /* Align selected objects to viertical center of objects.                    */
2271 /*****************************************************************************/
2272 void
2273 gl_view_align_selection_vcenter (glView *view)
2274 {
2275         GList         *p;
2276         glViewObject  *view_object;
2277         glLabelObject *object;
2278         gdouble        dy, dymin, ysum, yavg, ycenter, x1, y1, x2, y2;
2279         gint           n;
2280
2281         gl_debug (DEBUG_VIEW, "START");
2282
2283         g_return_if_fail (GL_IS_VIEW (view));
2284
2285         g_return_if_fail (!gl_view_is_selection_empty (view) &&
2286                           !gl_view_is_selection_atomic (view));
2287
2288         /* find average center of objects */
2289         ysum = 0.0;
2290         n = 0;
2291         for (p = view->selected_object_list; p != NULL; p = p->next) {
2292                 view_object = GL_VIEW_OBJECT (p->data);
2293                 object = gl_view_object_get_object (view_object);
2294                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2295                 ysum += (y1 + y2) / 2.0;
2296                 n++;
2297         }
2298         yavg = ysum / n;
2299
2300         /* find center of object closest to average center */
2301         p = view->selected_object_list;
2302         view_object = GL_VIEW_OBJECT (p->data);
2303         object = gl_view_object_get_object (view_object);
2304         gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2305         dymin = fabs (yavg - (y1 + y2)/2.0);
2306         ycenter = (y1 + y2)/2.0;
2307         for (p = p->next; p != NULL; p = p->next) {
2308                 view_object = GL_VIEW_OBJECT (p->data);
2309                 object = gl_view_object_get_object (view_object);
2310                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2311                 dy = fabs (yavg - (y1 + y2)/2.0);
2312                 if ( dy < dymin ) {
2313                         dymin = dy;
2314                         ycenter = (y1 + y2)/2.0;
2315                 }
2316         }
2317
2318         /* now adjust the object positions to line up this center */
2319         for (p = view->selected_object_list; p != NULL; p = p->next) {
2320                 view_object = GL_VIEW_OBJECT (p->data);
2321                 object = gl_view_object_get_object (view_object);
2322                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2323                 dy = ycenter - (y1 + y2)/2.0;
2324                 gl_label_object_set_position_relative (object, 0.0, dy);
2325         }
2326
2327         gl_debug (DEBUG_VIEW, "END");
2328 }
2329
2330 /*****************************************************************************/
2331 /* Center selected objects to in center of label.                            */
2332 /*****************************************************************************/
2333 void
2334 gl_view_center_selection_horiz (glView *view)
2335 {
2336         GList         *p;
2337         glViewObject  *view_object;
2338         glLabelObject *object;
2339         gdouble        dx, x_label_center, x_obj_center, x1, y1, x2, y2, w, h;
2340
2341         gl_debug (DEBUG_VIEW, "START");
2342
2343         g_return_if_fail (GL_IS_VIEW (view));
2344
2345         g_return_if_fail (!gl_view_is_selection_empty (view));
2346
2347         gl_label_get_size (view->label, &w, &h);
2348         x_label_center = w / 2.0;
2349
2350         /* adjust the object positions */
2351         for (p = view->selected_object_list; p != NULL; p = p->next) {
2352                 view_object = GL_VIEW_OBJECT (p->data);
2353                 object = gl_view_object_get_object (view_object);
2354                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2355                 x_obj_center = (x1 + x2) / 2.0;
2356                 dx = x_label_center - x_obj_center;
2357                 gl_label_object_set_position_relative (object, dx, 0.0);
2358         }
2359
2360         gl_debug (DEBUG_VIEW, "END");
2361 }
2362
2363
2364 /*****************************************************************************/
2365 /* Center selected objects to in center of label.                            */
2366 /*****************************************************************************/
2367 void
2368 gl_view_center_selection_vert (glView *view)
2369 {
2370         GList         *p;
2371         glViewObject  *view_object;
2372         glLabelObject *object;
2373         gdouble        dy, y_label_center, y_obj_center, x1, y1, x2, y2, w, h;
2374
2375         gl_debug (DEBUG_VIEW, "START");
2376
2377         g_return_if_fail (GL_IS_VIEW (view));
2378
2379         g_return_if_fail (!gl_view_is_selection_empty (view));
2380
2381         gl_label_get_size (view->label, &w, &h);
2382         y_label_center = h / 2.0;
2383
2384         /* adjust the object positions */
2385         for (p = view->selected_object_list; p != NULL; p = p->next) {
2386                 view_object = GL_VIEW_OBJECT (p->data);
2387                 object = gl_view_object_get_object (view_object);
2388                 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
2389                 y_obj_center = (y1 + y2) / 2.0;
2390                 dy = y_label_center - y_obj_center;
2391                 gl_label_object_set_position_relative (object, 0.0, dy);
2392         }
2393
2394         gl_debug (DEBUG_VIEW, "END");
2395 }
2396
2397
2398 /*****************************************************************************/
2399 /* Move selected objects                                                     */
2400 /*****************************************************************************/
2401 void
2402 gl_view_move_selection (glView  *view,
2403                 gdouble  dx,
2404                 gdouble  dy)
2405 {
2406         GList *p;
2407         glLabelObject *object;
2408
2409         gl_debug (DEBUG_VIEW, "START");
2410
2411         g_return_if_fail (view && GL_IS_VIEW (view));
2412
2413         for (p = view->selected_object_list; p != NULL; p = p->next) {
2414
2415                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2416                 gl_label_object_set_position_relative (object, dx, dy);
2417
2418         }
2419
2420         gl_debug (DEBUG_VIEW, "END");
2421 }
2422
2423 /*****************************************************************************/
2424 /* "Cut" selected items and place in clipboard selections.                   */
2425 /*****************************************************************************/
2426 void
2427 gl_view_cut (glView *view)
2428 {
2429         gl_debug (DEBUG_VIEW, "START");
2430
2431         g_return_if_fail (GL_IS_VIEW (view));
2432
2433         gl_view_copy (view);
2434         gl_view_delete_selection (view);
2435
2436         gl_debug (DEBUG_VIEW, "END");
2437 }
2438
2439 /*****************************************************************************/
2440 /* "Copy" selected items to clipboard selections.                            */
2441 /*****************************************************************************/
2442 void
2443 gl_view_copy (glView *view)
2444 {
2445         GList *p;
2446         glViewObject *view_object;
2447         glLabelObject *object;
2448         glTemplate *template;
2449         gboolean rotate_flag;
2450
2451         gl_debug (DEBUG_VIEW, "START");
2452
2453         g_return_if_fail (GL_IS_VIEW (view));
2454
2455         if (view->selected_object_list) {
2456
2457                 if ( view->selection_data ) {
2458                         g_object_unref (view->selection_data);
2459                 }
2460                 template = gl_label_get_template (view->label);
2461                 rotate_flag = gl_label_get_rotate_flag (view->label);
2462                 view->selection_data = GL_LABEL(gl_label_new ());
2463                 gl_label_set_template (view->selection_data, template);
2464                 gl_label_set_rotate_flag (view->selection_data, rotate_flag);
2465                 gl_template_free (&template);
2466
2467                 for (p = view->selected_object_list; p != NULL; p = p->next) {
2468
2469                         view_object = GL_VIEW_OBJECT (p->data);
2470                         object = gl_view_object_get_object (view_object);
2471
2472                         gl_label_object_dup (object, view->selection_data);
2473
2474                 }
2475
2476                 gtk_selection_owner_set (view->invisible,
2477                                          clipboard_atom, GDK_CURRENT_TIME);
2478                 view->have_selection = TRUE;
2479
2480         }
2481
2482         gl_debug (DEBUG_VIEW, "END");
2483 }
2484
2485 /*****************************************************************************/
2486 /* "Paste" from private clipboard selection.                                 */
2487 /*****************************************************************************/
2488 void
2489 gl_view_paste (glView *view)
2490 {
2491         gl_debug (DEBUG_VIEW, "START");
2492
2493         g_return_if_fail (GL_IS_VIEW (view));
2494
2495         gtk_selection_convert (GTK_WIDGET (view->invisible),
2496                                clipboard_atom, GDK_SELECTION_TYPE_STRING,
2497                                GDK_CURRENT_TIME);
2498
2499         gl_debug (DEBUG_VIEW, "END");
2500 }
2501
2502 /*****************************************************************************/
2503 /* Zoom in one "notch"                                                       */
2504 /*****************************************************************************/
2505 void
2506 gl_view_zoom_in (glView *view)
2507 {
2508         gint i, i_min;
2509         gdouble dist, dist_min;
2510
2511         gl_debug (DEBUG_VIEW, "START");
2512
2513         g_return_if_fail (GL_IS_VIEW (view));
2514
2515         /* Find index of current scale (or best match) */
2516         i_min = 1;              /* start with 2nd largest scale */
2517         dist_min = fabs (scales[1] - view->scale);
2518         for (i = 2; i < N_SCALES; i++) {
2519                 dist = fabs (scales[i] - view->scale);
2520                 if (dist < dist_min) {
2521                         i_min = i;
2522                         dist_min = dist;
2523                 }
2524         }
2525
2526         /* zoom in one "notch" */
2527         i = MAX (0, i_min - 1);
2528         gl_view_set_zoom (view, scales[i] / HOME_SCALE);
2529
2530         gl_debug (DEBUG_VIEW, "END");
2531 }
2532
2533 /*****************************************************************************/
2534 /* Zoom out one "notch"                                                      */
2535 /*****************************************************************************/
2536 void
2537 gl_view_zoom_out (glView *view)
2538 {
2539         gint i, i_min;
2540         gdouble dist, dist_min;
2541
2542         gl_debug (DEBUG_VIEW, "START");
2543
2544         g_return_if_fail (GL_IS_VIEW (view));
2545
2546         /* Find index of current scale (or best match) */
2547         i_min = 0;              /* start with largest scale */
2548         dist_min = fabs (scales[0] - view->scale);
2549         for (i = 1; i < N_SCALES; i++) {
2550                 dist = fabs (scales[i] - view->scale);
2551                 if (dist < dist_min) {
2552                         i_min = i;
2553                         dist_min = dist;
2554                 }
2555         }
2556
2557         /* zoom out one "notch" */
2558         if (i_min >= N_SCALES)
2559                 return;
2560         i = i_min + 1;
2561         if (i >= N_SCALES)
2562                 return;
2563         gl_view_set_zoom (view, scales[i] / HOME_SCALE);
2564
2565         gl_debug (DEBUG_VIEW, "END");
2566 }
2567
2568 /*****************************************************************************/
2569 /* Set current zoom factor to explicit value.                                */
2570 /*****************************************************************************/
2571 void
2572 gl_view_set_zoom (glView  *view,
2573                   gdouble scale)
2574 {
2575         gl_debug (DEBUG_VIEW, "START");
2576
2577         g_return_if_fail (GL_IS_VIEW (view));
2578         g_return_if_fail (scale > 0.0);
2579
2580         view->scale = scale * HOME_SCALE;
2581         gnome_canvas_set_pixels_per_unit (GNOME_CANVAS (view->canvas),
2582                                           scale * HOME_SCALE);
2583
2584         g_signal_emit (G_OBJECT(view), signals[ZOOM_CHANGED], 0, scale);
2585
2586         gl_debug (DEBUG_VIEW, "END");
2587 }
2588
2589 /*****************************************************************************/
2590 /* Get current zoom factor.                                                  */
2591 /*****************************************************************************/
2592 gdouble
2593 gl_view_get_zoom (glView *view)
2594 {
2595         gl_debug (DEBUG_VIEW, "");
2596
2597         g_return_val_if_fail (GL_IS_VIEW (view), 1.0);
2598
2599         return view->scale / HOME_SCALE;
2600 }
2601
2602 /*****************************************************************************/
2603 /* Is this the maximum zoom level.                                           */
2604 /*****************************************************************************/
2605 gboolean
2606 gl_view_is_zoom_max (glView *view)
2607 {
2608         gl_debug (DEBUG_VIEW, "");
2609
2610         g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
2611
2612         return view->scale >= scales[0];
2613 }
2614
2615 /*****************************************************************************/
2616 /* Is this the minimum zoom level.                                           */
2617 /*****************************************************************************/
2618 gboolean
2619 gl_view_is_zoom_min (glView *view)
2620 {
2621         gl_debug (DEBUG_VIEW, "");
2622
2623         g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
2624
2625         return view->scale <= scales[N_SCALES-1];
2626 }
2627
2628 /*****************************************************************************/
2629 /* Launch merge properties dialog.                                           */
2630 /*****************************************************************************/
2631 void
2632 gl_view_edit_merge_props (glView *view)
2633 {
2634         gl_debug (DEBUG_VIEW, "");
2635
2636         g_return_if_fail (GL_IS_VIEW (view));
2637
2638         if (view->merge_props_dialog != NULL) {
2639                 gtk_widget_show_all (view->merge_props_dialog);
2640                 gtk_window_present (GTK_WINDOW(view->merge_props_dialog));
2641                 return;
2642         }
2643
2644         view->merge_props_dialog = gl_merge_properties_dialog_new (view);
2645         gtk_widget_show_all (view->merge_props_dialog);
2646
2647         g_signal_connect (G_OBJECT(view->merge_props_dialog), "destroy",
2648                           G_CALLBACK (gtk_widget_destroyed),
2649                           &view->merge_props_dialog);
2650 }
2651
2652 /*---------------------------------------------------------------------------*/
2653 /* PRIVATE.  Canvas event handler.                                           */
2654 /*---------------------------------------------------------------------------*/
2655 static int
2656 canvas_event (GnomeCanvas *canvas,
2657               GdkEvent    *event,
2658               glView      *view)
2659 {
2660         gdouble x, y;
2661
2662         gl_debug (DEBUG_VIEW, "");
2663
2664         /* emit pointer signals regardless of state */
2665         switch (event->type) {
2666         case GDK_MOTION_NOTIFY:
2667                 gl_debug (DEBUG_VIEW, "MOTION_NOTIFY");
2668                 gnome_canvas_window_to_world (canvas,
2669                                               event->motion.x,
2670                                               event->motion.y, &x, &y);
2671                 g_signal_emit (G_OBJECT(view), signals[POINTER_MOVED], 0, x, y);
2672                 break; /* fall through */
2673
2674         case GDK_LEAVE_NOTIFY:
2675                 gl_debug (DEBUG_VIEW, "LEAVEW_NOTIFY");
2676                 g_signal_emit (G_OBJECT(view), signals[POINTER_EXIT], 0);
2677                 break; /* fall through */
2678
2679         default:
2680                 break; /* fall through */
2681         }
2682
2683
2684         switch (view->state) {
2685
2686         case GL_VIEW_STATE_ARROW:
2687                 return canvas_event_arrow_mode (canvas, event, view);
2688
2689         case GL_VIEW_STATE_OBJECT_CREATE:
2690                 switch (view->create_type) {
2691                 case GL_LABEL_OBJECT_BOX:
2692                         return gl_view_box_create_event_handler (canvas,
2693                                                                  event,
2694                                                                  view);
2695                         break;
2696                 case GL_LABEL_OBJECT_ELLIPSE:
2697                         return gl_view_ellipse_create_event_handler (canvas,
2698                                                                      event,
2699                                                                      view);
2700                         break;
2701                 case GL_LABEL_OBJECT_LINE:
2702                         return gl_view_line_create_event_handler (canvas,
2703                                                                   event,
2704                                                                   view);
2705                         break;
2706                 case GL_LABEL_OBJECT_IMAGE:
2707                         return gl_view_image_create_event_handler (canvas,
2708                                                                    event,
2709                                                                    view);
2710                         break;
2711                 case GL_LABEL_OBJECT_TEXT:
2712                         return gl_view_text_create_event_handler (canvas,
2713                                                                   event,
2714                                                                   view);
2715                         break;
2716                 case GL_LABEL_OBJECT_BARCODE:
2717                         return gl_view_barcode_create_event_handler (canvas,
2718                                                                      event,
2719                                                                      view);
2720                         break;
2721                 default:
2722                         /*Should not happen!*/
2723                         g_warning ("Invalid label object type.");
2724                         return FALSE;
2725         }
2726
2727         default:
2728                 g_warning ("Invalid view state.");      /*Should not happen!*/
2729                 return FALSE;
2730
2731         }
2732 }
2733
2734 /*---------------------------------------------------------------------------*/
2735 /* PRIVATE.  Canvas event handler (arrow mode)                               */
2736 /*---------------------------------------------------------------------------*/
2737 static int
2738 canvas_event_arrow_mode (GnomeCanvas *canvas,
2739                          GdkEvent    *event,
2740                          glView      *view)
2741 {
2742         static gdouble x0, y0;
2743         static gboolean dragging = FALSE;
2744         static GnomeCanvasItem *item;
2745         gdouble x, y, x1, y1, x2, y2;
2746         GnomeCanvasGroup *group;
2747         GdkCursor *cursor;
2748
2749         gl_debug (DEBUG_VIEW, "");
2750
2751         switch (event->type) {
2752
2753         case GDK_BUTTON_PRESS:
2754                 gl_debug (DEBUG_VIEW, "BUTTON_PRESS");
2755                 switch (event->button.button) {
2756                 case 1:
2757                         gnome_canvas_window_to_world (canvas,
2758                                                       event->button.x,
2759                                                       event->button.y, &x, &y);
2760
2761                         if (!object_at (view, x, y)) {
2762                                 if (!(event->button.state & GDK_CONTROL_MASK)) {
2763                                         gl_view_unselect_all (view);
2764                                 }
2765
2766                                 dragging = TRUE;
2767                                 gnome_canvas_item_grab (canvas->root,
2768                                                         GDK_POINTER_MOTION_MASK |
2769                                                         GDK_BUTTON_RELEASE_MASK |
2770                                                         GDK_BUTTON_PRESS_MASK,
2771                                                         NULL, event->button.time);
2772                                 group =
2773                                     gnome_canvas_root (GNOME_CANVAS
2774                                                        (view->canvas));
2775                                 item =
2776                                     gnome_canvas_item_new (group,
2777                                                            gnome_canvas_rect_get_type (),
2778                                                            "x1", x, "y1", y,
2779                                                            "x2", x, "y2", y,
2780                                                            "width_pixels", 2,
2781                                                            "outline_color_rgba",
2782                                                            SEL_LINE_COLOR,
2783                                                            "fill_color_rgba",
2784                                                            SEL_FILL_COLOR,
2785                                                            NULL);
2786                                 x0 = x;
2787                                 y0 = y;
2788
2789                         }
2790                         return FALSE;
2791                 case 3:
2792                         gnome_canvas_window_to_world (canvas,
2793                                                       event->button.x,
2794                                                       event->button.y, &x, &y);
2795
2796                         if (!object_at (view, x, y)) {
2797                                 /* bring up apropriate menu for selection. */
2798                                 gl_view_popup_menu (view, event);
2799                         }
2800                         return FALSE;
2801                 default:
2802                         return FALSE;
2803                 }
2804
2805         case GDK_BUTTON_RELEASE:
2806                 gl_debug (DEBUG_VIEW, "BUTTON_RELEASE");
2807                 switch (event->button.button) {
2808                 case 1:
2809                         if (dragging) {
2810                                 dragging = FALSE;
2811                                 gnome_canvas_item_ungrab (canvas->root,
2812                                                           event->button.time);
2813                                 gnome_canvas_window_to_world (canvas,
2814                                                               event->button.x,
2815                                                               event->button.y,
2816                                                               &x, &y);
2817                                 x1 = MIN (x, x0);
2818                                 y1 = MIN (y, y0);
2819                                 x2 = MAX (x, x0);
2820                                 y2 = MAX (y, y0);
2821                                 gl_view_select_region (view, x1, y1, x2, y2);
2822                                 gtk_object_destroy (GTK_OBJECT (item));
2823                                 return TRUE;
2824                         }
2825                         return FALSE;
2826
2827                 default:
2828                         return FALSE;
2829                 }
2830
2831         case GDK_MOTION_NOTIFY:
2832                 gl_debug (DEBUG_VIEW, "MOTION_NOTIFY");
2833                 gnome_canvas_window_to_world (canvas,
2834                                               event->motion.x,
2835                                               event->motion.y, &x, &y);
2836                 if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
2837                         gnome_canvas_item_set (item,
2838                                                "x1", MIN (x, x0),
2839                                                "y1", MIN (y, y0),
2840                                                "x2", MAX (x, x0),
2841                                                "y2", MAX (y, y0), NULL);
2842                         return TRUE;
2843                 } else {
2844                         return FALSE;
2845                 }
2846
2847         case GDK_KEY_PRESS:
2848                 gl_debug (DEBUG_VIEW, "KEY_PRESS");
2849                 if (!dragging) {
2850                         switch (event->key.keyval) {
2851                         case GDK_Left:
2852                         case GDK_KP_Left:
2853                                 gl_view_move_selection (view,
2854                                                         -1.0 / (view->scale), 0.0);
2855                                 break;
2856                         case GDK_Up:
2857                         case GDK_KP_Up:
2858                                 gl_view_move_selection (view,
2859                                                         0.0, -1.0 / (view->scale));
2860                                 break;
2861                         case GDK_Right:
2862                         case GDK_KP_Right:
2863                                 gl_view_move_selection (view,
2864                                                         1.0 / (view->scale), 0.0);
2865                                 break;
2866                         case GDK_Down:
2867                         case GDK_KP_Down:
2868                                 gl_view_move_selection (view,
2869                                                         0.0, 1.0 / (view->scale));
2870                                 break;
2871                         case GDK_Delete:
2872                         case GDK_KP_Delete:
2873                                 gl_view_delete_selection (view);
2874                                 cursor = gdk_cursor_new (GDK_LEFT_PTR);
2875                                 gdk_window_set_cursor (view->canvas->window,
2876                                                        cursor);
2877                                 gdk_cursor_unref (cursor);
2878                                 break;
2879                         default:
2880                                 return FALSE;
2881                         }
2882                 }
2883                 return TRUE;    /* We handled this or we were dragging. */
2884
2885         default:
2886                 gl_debug (DEBUG_VIEW, "default");
2887                 return FALSE;
2888         }
2889
2890 }
2891
2892 /*---------------------------------------------------------------------------*/
2893 /* PRIVATE.  create menu for selections.                                     */
2894 /*---------------------------------------------------------------------------*/
2895 void
2896 construct_selection_menu (glView *view)
2897 {
2898         GtkWidget *menu, *menuitem, *submenu;
2899
2900         gl_debug (DEBUG_VIEW, "START");
2901
2902         g_return_if_fail (GL_IS_VIEW (view));
2903
2904         menu = gtk_menu_new ();
2905
2906         menuitem = gtk_image_menu_item_new_from_stock (GL_STOCK_PROPERTIES, NULL);
2907         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
2908         gtk_widget_show (menuitem);
2909         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
2910                                   G_CALLBACK (gl_view_edit_object_props), view);
2911         view->atomic_selection_items =
2912                 g_list_prepend (view->atomic_selection_items, menuitem);
2913
2914         /*
2915          * Separator -------------------------
2916          */
2917         menuitem = gtk_menu_item_new ();
2918         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
2919         gtk_widget_show (menuitem);
2920
2921         /*
2922          * Submenu: Order
2923          */
2924         menuitem = gtk_menu_item_new_with_mnemonic (_("_Order"));
2925         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
2926         gtk_widget_show (menuitem);
2927         submenu = gtk_menu_new ();
2928         gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
2929
2930         menuitem = gtk_image_menu_item_new_from_stock (GL_STOCK_ORDER_TOP, NULL);
2931         gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menuitem);
2932         gtk_widget_show (menuitem);
2933         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
2934                                   G_CALLBACK (gl_view_raise_selection), view);
2935
2936         menuitem = gtk_image_menu_item_new_from_stock (GL_STOCK_ORDER_BOTTOM, NULL);
2937         gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menuitem);
2938         gtk_widget_show (menuitem);
2939         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
2940                                   G_CALLBACK (gl_view_lower_selection), view);
2941
2942         /*
2943          * Submenu: Rotate/Flip
2944          */
2945         menuitem = gtk_menu_item_new_with_mnemonic (_("_Rotate/Flip"));
2946         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
2947         gtk_widget_show (menuitem);
2948         submenu = gtk_menu_new ();
2949         gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
2950
2951         menuitem = gtk_image_menu_item_new_from_stock (GL_STOCK_ROTATE_LEFT, NULL);
2952         gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menuitem);
2953         gtk_widget_show (menuitem);
2954         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
2955                                   G_CALLBACK (gl_view_rotate_selection_left), view);
2956
2957         menuitem = gtk_image_menu_item_new_from_stock (GL_STOCK_ROTATE_RIGHT, NULL);
2958         gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menuitem);
2959         gtk_widget_show (menuitem);
2960         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
2961                                   G_CALLBACK (gl_view_rotate_selection_right), view);
2962
2963         menuitem = gtk_image_menu_item_new_from_stock (GL_STOCK_FLIP_HORIZ, NULL);
2964         gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menuitem);
2965         gtk_widget_show (menuitem);
2966         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
2967                                   G_CALLBACK (gl_view_flip_selection_horiz), view);
2968
2969         menuitem = gtk_image_menu_item_new_from_stock (GL_STOCK_FLIP_VERT, NULL);
2970         gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menuitem);
2971         gtk_widget_show (menuitem);
2972         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
2973                                   G_CALLBACK (gl_view_flip_selection_vert), view);
2974
2975         /*
2976          * Submenu: Align Horizontally
2977          */
2978         menuitem = gtk_menu_item_new_with_mnemonic (_("Align _Horizontally"));
2979         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
2980         gtk_widget_show (menuitem);
2981         submenu = gtk_menu_new ();
2982         gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
2983
2984         menuitem = gtk_image_menu_item_new_from_stock (GL_STOCK_ALIGN_LEFT, NULL);
2985         gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menuitem);
2986         gtk_widget_show (menuitem);
2987         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
2988                                   G_CALLBACK (gl_view_align_selection_left), view);
2989         view->multi_selection_items =
2990                 g_list_prepend (view->multi_selection_items, menuitem);
2991
2992         menuitem = gtk_image_menu_item_new_from_stock (GL_STOCK_ALIGN_HCENTER, NULL);
2993         gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menuitem);
2994         gtk_widget_show (menuitem);
2995         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
2996                                   G_CALLBACK (gl_view_align_selection_hcenter), view);
2997         view->multi_selection_items =
2998                 g_list_prepend (view->multi_selection_items, menuitem);
2999
3000         menuitem = gtk_image_menu_item_new_from_stock (GL_STOCK_ALIGN_RIGHT, NULL);
3001         gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menuitem);
3002         gtk_widget_show (menuitem);
3003         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
3004                                   G_CALLBACK (gl_view_align_selection_right), view);
3005         view->multi_selection_items =
3006                 g_list_prepend (view->multi_selection_items, menuitem);
3007
3008         menuitem = gtk_image_menu_item_new_from_stock (GL_STOCK_CENTER_HORIZ, NULL);
3009         gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menuitem);
3010         gtk_widget_show (menuitem);
3011         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
3012                                   G_CALLBACK (gl_view_center_selection_horiz), view);
3013
3014         /*
3015          * Submenu: Align Vertically
3016          */
3017         menuitem = gtk_menu_item_new_with_mnemonic (_("Align _Vertically"));
3018         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3019         gtk_widget_show (menuitem);
3020         submenu = gtk_menu_new ();
3021         gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
3022
3023         menuitem = gtk_image_menu_item_new_from_stock (GL_STOCK_ALIGN_TOP, NULL);
3024         gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menuitem);
3025         gtk_widget_show (menuitem);
3026         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
3027                                   G_CALLBACK (gl_view_align_selection_top), view);
3028         view->multi_selection_items =
3029                 g_list_prepend (view->multi_selection_items, menuitem);
3030
3031         menuitem = gtk_image_menu_item_new_from_stock (GL_STOCK_ALIGN_VCENTER, NULL);
3032         gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menuitem);
3033         gtk_widget_show (menuitem);
3034         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
3035                                   G_CALLBACK (gl_view_align_selection_vcenter), view);
3036         view->multi_selection_items =
3037                 g_list_prepend (view->multi_selection_items, menuitem);
3038
3039         menuitem = gtk_image_menu_item_new_from_stock (GL_STOCK_ALIGN_BOTTOM, NULL);
3040         gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menuitem);
3041         gtk_widget_show (menuitem);
3042         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
3043                                   G_CALLBACK (gl_view_align_selection_bottom), view);
3044         view->multi_selection_items =
3045                 g_list_prepend (view->multi_selection_items, menuitem);
3046
3047         menuitem = gtk_image_menu_item_new_from_stock (GL_STOCK_CENTER_VERT, NULL);
3048         gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menuitem);
3049         gtk_widget_show (menuitem);
3050         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
3051                                   G_CALLBACK (gl_view_center_selection_vert), view);
3052
3053         /*
3054          * Separator -------------------------
3055          */
3056         menuitem = gtk_menu_item_new ();
3057         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3058         gtk_widget_show (menuitem);
3059
3060         menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_CUT, NULL);
3061         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3062         gtk_widget_show (menuitem);
3063         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
3064                                   G_CALLBACK (gl_view_cut), view);
3065
3066         menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_COPY, NULL);
3067         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3068         gtk_widget_show (menuitem);
3069         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
3070                                   G_CALLBACK (gl_view_copy), view);
3071
3072         menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_PASTE, NULL);
3073         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3074         gtk_widget_show (menuitem);
3075         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
3076                                   G_CALLBACK (gl_view_paste), view);
3077
3078         menuitem = gtk_menu_item_new_with_mnemonic (_("_Delete"));
3079         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3080         gtk_widget_show (menuitem);
3081         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
3082                                   G_CALLBACK (gl_view_delete_selection), view);
3083
3084
3085         view->selection_menu = menu;
3086
3087         gl_debug (DEBUG_VIEW, "END");
3088 }
3089
3090 /*---------------------------------------------------------------------------*/
3091 /* PRIVATE.  create menu for empty selections.                               */
3092 /*---------------------------------------------------------------------------*/
3093 void
3094 construct_empty_selection_menu (glView *view)
3095 {
3096         GtkWidget *menu, *menuitem, *submenu;
3097
3098         gl_debug (DEBUG_VIEW, "START");
3099
3100         g_return_if_fail (GL_IS_VIEW (view));
3101
3102         menu = gtk_menu_new ();
3103
3104         menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_PASTE, NULL);
3105         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3106         gtk_widget_show (menuitem);
3107         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
3108                                   G_CALLBACK (gl_view_paste), view);
3109
3110
3111         view->empty_selection_menu = menu;
3112
3113         gl_debug (DEBUG_VIEW, "END");
3114 }
3115
3116 /****************************************************************************/
3117 /* popup menu.                                                              */
3118 /****************************************************************************/
3119 void
3120 gl_view_popup_menu (glView       *view,
3121                     GdkEvent     *event)
3122 {
3123         GtkMenu *menu;
3124         GList   *p;
3125
3126         gl_debug (DEBUG_VIEW, "START");
3127
3128         g_return_if_fail (GL_IS_VIEW (view));
3129
3130         if (gl_view_is_selection_empty (view)) {
3131
3132                 if (view->empty_selection_menu != NULL) {
3133                         gtk_menu_popup (GTK_MENU (view->empty_selection_menu),
3134                                         NULL, NULL, NULL, NULL,
3135                                         event->button.button,
3136                                         event->button.time);
3137                 }
3138
3139         } else {
3140
3141                 for (p=view->atomic_selection_items; p!=NULL; p=p->next) {
3142                         gtk_widget_set_sensitive (GTK_WIDGET(p->data),
3143                                                   gl_view_is_selection_atomic(view));
3144                 }
3145
3146                 for (p=view->multi_selection_items; p!=NULL; p=p->next) {
3147                         gtk_widget_set_sensitive (GTK_WIDGET(p->data),
3148                                                   !gl_view_is_selection_atomic(view));
3149                 }
3150
3151                 if (view->selection_menu != NULL) {
3152                         gtk_menu_popup (GTK_MENU (view->selection_menu),
3153                                         NULL, NULL, NULL, NULL,
3154                                         event->button.button,
3155                                         event->button.time);
3156                 }
3157
3158         }
3159
3160         gl_debug (DEBUG_VIEW, "END");
3161 }
3162
3163 /*---------------------------------------------------------------------------*/
3164 /* PRIVATE.  Handle "selection-clear" signal.                                */
3165 /*---------------------------------------------------------------------------*/
3166 static void
3167 selection_clear_cb (GtkWidget         *widget,
3168                     GdkEventSelection *event,
3169                     gpointer          data)
3170 {
3171         glView *view = GL_VIEW (data);
3172
3173         gl_debug (DEBUG_VIEW, "START");
3174
3175         g_return_if_fail (GL_IS_VIEW (view));
3176
3177         view->have_selection = FALSE;
3178         g_object_unref (view->selection_data);
3179         view->selection_data = NULL;
3180
3181         gl_debug (DEBUG_VIEW, "END");
3182 }
3183
3184 /*---------------------------------------------------------------------------*/
3185 /* PRIVATE.  Handle "selection-get" signal.                                  */
3186 /*---------------------------------------------------------------------------*/
3187 static void
3188 selection_get_cb (GtkWidget        *widget,
3189                   GtkSelectionData *selection_data,
3190                   guint            info,
3191                   guint            time,
3192                   gpointer         data)
3193 {
3194         glView *view = GL_VIEW (data);
3195         gchar *buffer;
3196         glXMLLabelStatus status;
3197
3198         gl_debug (DEBUG_VIEW, "START");
3199
3200         g_return_if_fail (GL_IS_VIEW (view));
3201
3202         if (view->have_selection) {
3203
3204                 buffer = gl_xml_label_save_buffer (view->selection_data,
3205                                                    &status);
3206                 gtk_selection_data_set (selection_data,
3207                                         GDK_SELECTION_TYPE_STRING, 8, buffer,
3208                                         strlen (buffer));
3209                 g_free (buffer);
3210         }
3211
3212         gl_debug (DEBUG_VIEW, "END");
3213 }
3214
3215 /*---------------------------------------------------------------------------*/
3216 /* PRIVATE.  Handle "selection-received" signal.  (Result of Paste)          */
3217 /*---------------------------------------------------------------------------*/
3218 static void
3219 selection_received_cb (GtkWidget        *widget,
3220                        GtkSelectionData *selection_data,
3221                        guint            time,
3222                        gpointer         data)
3223 {
3224         glView *view = GL_VIEW (data);
3225         glLabel *label = NULL;
3226         glXMLLabelStatus status;
3227         GList *p, *p_next;
3228         glLabelObject *object, *newobject;
3229         glViewObject *view_object;
3230
3231         gl_debug (DEBUG_VIEW, "START");
3232
3233         g_return_if_fail (GL_IS_VIEW (view));
3234
3235         if (selection_data->length < 0) {
3236                 return;
3237         }
3238         if (selection_data->type != GDK_SELECTION_TYPE_STRING) {
3239                 return;
3240         }
3241
3242         gl_view_unselect_all (view);
3243
3244         label = gl_xml_label_open_buffer (selection_data->data, &status);
3245         for (p = label->objects; p != NULL; p = p_next) {
3246                 p_next = p->next;
3247
3248                 object = (glLabelObject *) p->data;
3249                 gl_label_object_set_parent (object, view->label);
3250
3251                 gl_debug (DEBUG_VIEW, "object pasted");
3252
3253                 if (GL_IS_LABEL_BOX (object)) {
3254                         view_object = gl_view_box_new (GL_LABEL_BOX(object),
3255                                                        view);
3256                 } else if (GL_IS_LABEL_ELLIPSE (object)) {
3257                         view_object = gl_view_ellipse_new (GL_LABEL_ELLIPSE(object),
3258                                                            view);
3259                 } else if (GL_IS_LABEL_LINE (object)) {
3260                         view_object = gl_view_line_new (GL_LABEL_LINE(object),
3261                                                         view);
3262                 } else if (GL_IS_LABEL_IMAGE (object)) {
3263                         view_object = gl_view_image_new (GL_LABEL_IMAGE(object),
3264                                                          view);
3265                 } else if (GL_IS_LABEL_TEXT (object)) {
3266                         view_object = gl_view_text_new (GL_LABEL_TEXT(object),
3267                                                         view);
3268                 } else if (GL_IS_LABEL_BARCODE (object)) {
3269                         view_object = gl_view_barcode_new (GL_LABEL_BARCODE(object),
3270                                                            view);
3271                 } else {
3272                         /* Should not happen! */
3273                         view_object = NULL;
3274                         g_warning ("Invalid label object type.");
3275                 }
3276                 gl_view_select_object (view, view_object);
3277         }
3278         g_object_unref (label);
3279
3280         gl_debug (DEBUG_VIEW, "END");
3281 }
3282