]> git.sur5r.net Git - glabels/blob - glabels2/src/view.c
Restructured template module to ultimately support multiple layouts and markups.
[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 "marshal.h"
42
43 #include "debug.h"
44
45 /*========================================================*/
46 /* Private macros and constants.                          */
47 /*========================================================*/
48
49 #define SEL_LINE_COLOR  GL_COLOR_A (0, 0, 255, 128)
50 #define SEL_FILL_COLOR  GL_COLOR_A (192, 192, 255, 128)
51
52 /*========================================================*/
53 /* Private types.                                         */
54 /*========================================================*/
55
56 enum {
57         SELECTION_CHANGED,
58         LAST_SIGNAL
59 };
60
61 /*===========================================*/
62 /* Private globals                           */
63 /*===========================================*/
64
65 static GtkContainerClass *parent_class;
66
67 static guint signals[LAST_SIGNAL] = {0};
68
69 /* "CLIPBOARD" selection */
70 static GdkAtom clipboard_atom = GDK_NONE;
71
72 #define HOME_SCALE 2.0
73 static gdouble scales[] = {
74         8.0, 6.0, 4.0, 3.0,
75         2.0,
76         1.5, 1.0, 0.5, 0.25,
77         0.0
78 };
79
80 /*===========================================*/
81 /* Local function prototypes                 */
82 /*===========================================*/
83
84 static void       gl_view_class_init              (glViewClass *class);
85 static void       gl_view_init                    (glView *view);
86 static void       gl_view_finalize                (GObject *object);
87
88 static void       gl_view_construct               (glView *view);
89 static GtkWidget *gl_view_construct_canvas        (glView *view);
90 static void       gl_view_construct_selection     (glView *view);
91
92 static gdouble    get_apropriate_scale            (gdouble w, gdouble h);
93
94 static void       draw_bg_fg                      (glView *view);
95 static void       draw_bg_fg_rect                 (glView *view);
96 static void       draw_bg_fg_rounded_rect         (glView *view);
97 static void       draw_bg_fg_round                (glView *view);
98 static void       draw_bg_fg_cd                   (glView *view);
99
100 static void       draw_markup                     (glView *view);
101
102 static void       draw_markup_margin              (glView *view,
103                                                    glTemplateMarkupMargin *margin);
104 static void       draw_markup_margin_rect         (glView *view,
105                                                    glTemplateMarkupMargin *margin);
106 static void       draw_markup_margin_rounded_rect (glView *view,
107                                                    glTemplateMarkupMargin *margin);
108 static void       draw_markup_margin_round        (glView *view,
109                                                    glTemplateMarkupMargin *margin);
110 static void       draw_markup_margin_cd           (glView *view,
111                                                    glTemplateMarkupMargin *margin);
112
113
114 static void       select_object_real              (glView *view,
115                                                    glViewObject *view_object);
116 static void       unselect_object_real            (glView *view,
117                                                    glViewObject *view_object);
118
119 static gboolean   object_at                       (glView *view,
120                                                    gdouble x, gdouble y);
121 static gboolean   is_object_selected              (glView *view,
122                                                    glViewObject *view_object);
123
124 static void       move_selection                  (glView *view,
125                                                    gdouble dx, gdouble dy);
126
127 static int        canvas_event                    (GnomeCanvas *canvas,
128                                                    GdkEvent    *event,
129                                                    glView      *view);
130 static int        canvas_event_arrow_mode         (GnomeCanvas *canvas,
131                                                    GdkEvent    *event,
132                                                    glView      *view);
133
134 static int        item_event_arrow_mode          (GnomeCanvasItem *item,
135                                                   GdkEvent        *event,
136                                                   glViewObject    *view_object);
137
138 static GtkWidget *new_selection_menu             (glView *view);
139
140 static void       popup_selection_menu           (glView       *view,
141                                                   glViewObject *view_object,
142                                                   GdkEvent     *event);
143
144 static void       selection_clear_cb             (GtkWidget         *widget,
145                                                   GdkEventSelection *event,
146                                                   gpointer          data);
147
148 static void       selection_get_cb               (GtkWidget         *widget,
149                                                   GtkSelectionData  *selection_data,
150                                                   guint             info,
151                                                   guint             time,
152                                                   gpointer          data);
153
154 static void       selection_received_cb          (GtkWidget         *widget,
155                                                   GtkSelectionData  *selection_data,
156                                                   guint             time,
157                                                   gpointer          data);
158 \f
159 /****************************************************************************/
160 /* Boilerplate Object stuff.                                                */
161 /****************************************************************************/
162 guint
163 gl_view_get_type (void)
164 {
165         static guint view_type = 0;
166
167         if (!view_type) {
168                 GTypeInfo view_info = {
169                         sizeof (glViewClass),
170                         NULL,
171                         NULL,
172                         (GClassInitFunc) gl_view_class_init,
173                         NULL,
174                         NULL,
175                         sizeof (glView),
176                         0,
177                         (GInstanceInitFunc) gl_view_init,
178                 };
179
180                 view_type =
181                     g_type_register_static (gtk_vbox_get_type (),
182                                             "glView", &view_info, 0);
183         }
184
185         return view_type;
186 }
187
188 static void
189 gl_view_class_init (glViewClass *class)
190 {
191         GObjectClass *object_class = (GObjectClass *) class;
192
193         gl_debug (DEBUG_VIEW, "START");
194
195         parent_class = g_type_class_peek_parent (class);
196
197         object_class->finalize = gl_view_finalize;
198
199         signals[SELECTION_CHANGED] =
200                 g_signal_new ("selection_changed",
201                               G_OBJECT_CLASS_TYPE (object_class),
202                               G_SIGNAL_RUN_LAST,
203                               G_STRUCT_OFFSET (glViewClass, selection_changed),
204                               NULL, NULL,
205                               gl_marshal_VOID__VOID,
206                               G_TYPE_NONE,
207                               0);
208
209         gl_debug (DEBUG_VIEW, "END");
210 }
211
212 static void
213 gl_view_init (glView *view)
214 {
215         gl_debug (DEBUG_VIEW, "START");
216
217         view->label = NULL;
218
219         gl_debug (DEBUG_VIEW, "END");
220 }
221
222 static void
223 gl_view_finalize (GObject *object)
224 {
225         glView *view;
226
227         gl_debug (DEBUG_VIEW, "START");
228
229         g_return_if_fail (object != NULL);
230         g_return_if_fail (GL_IS_VIEW (object));
231
232         view = GL_VIEW (object);
233
234         G_OBJECT_CLASS (parent_class)->finalize (object);
235
236         gl_debug (DEBUG_VIEW, "END");
237 }
238
239 /****************************************************************************/
240 /* NEW view object.                                                         */
241 /****************************************************************************/
242 GtkWidget *
243 gl_view_new (glLabel *label)
244 {
245         glView *view = g_object_new (gl_view_get_type (), NULL);
246
247         gl_debug (DEBUG_VIEW, "START");
248
249         view->label = label;
250
251         gl_view_construct (view);
252
253         gl_debug (DEBUG_VIEW, "END");
254
255         return GTK_WIDGET (view);
256 }
257
258 /*---------------------------------------------------------------------------*/
259 /* PRIVATE.  Construct composite widget.                                     */
260 /*---------------------------------------------------------------------------*/
261 static void
262 gl_view_construct (glView *view)
263 {
264         GtkWidget *wvbox, *wscroll;
265
266         gl_debug (DEBUG_VIEW, "START");
267
268         g_return_if_fail (GL_IS_VIEW (view));
269
270         wvbox = GTK_WIDGET (view);
271
272         view->state = GL_VIEW_STATE_ARROW;
273         view->object_list = NULL;
274
275         gl_view_construct_canvas (view);
276         wscroll = gtk_scrolled_window_new (NULL, NULL);
277         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (wscroll),
278                                         GTK_POLICY_AUTOMATIC,
279                                         GTK_POLICY_AUTOMATIC);
280         gtk_box_pack_start (GTK_BOX (wvbox), wscroll, TRUE, TRUE, 0);
281         gtk_container_add (GTK_CONTAINER (wscroll), view->canvas);
282
283         gl_view_construct_selection (view);
284
285         view->menu = new_selection_menu (view);
286
287         gl_debug (DEBUG_VIEW, "END");
288 }
289
290 /*---------------------------------------------------------------------------*/
291 /* PRIVATE.  Create canvas w/ a background in the shape of the label/card.   */
292 /*---------------------------------------------------------------------------*/
293 static GtkWidget *
294 gl_view_construct_canvas (glView *view)
295 {
296         gdouble scale;
297         glLabel *label = view->label;
298         gdouble label_width, label_height;
299         GList *p_obj;
300         glLabelObject *object;
301         glViewObject *view_object;
302
303         gl_debug (DEBUG_VIEW, "START");
304
305         g_return_val_if_fail (GL_IS_VIEW (view), NULL);
306         g_return_val_if_fail (label != NULL, NULL);
307
308         gtk_widget_push_colormap (gdk_rgb_get_colormap ());
309         view->canvas = gnome_canvas_new_aa ();
310         gtk_widget_pop_colormap ();
311
312         gl_label_get_size (label, &label_width, &label_height);
313         gl_debug (DEBUG_VIEW, "Label size: w=%lf, h=%lf",
314                   label_width, label_height);
315
316         scale = get_apropriate_scale (label_width, label_height);
317         gl_debug (DEBUG_VIEW, "scale =%lf", scale);
318
319         gl_debug (DEBUG_VIEW, "Canvas size: w=%lf, h=%lf",
320                               scale * label_width + 40,
321                               scale * label_height + 40);
322         gtk_widget_set_size_request (GTK_WIDGET(view->canvas),
323                                      scale * label_width + 40,
324                                      scale * label_height + 40);
325         gnome_canvas_set_pixels_per_unit (GNOME_CANVAS (view->canvas),
326                                           scale);
327         view->scale = scale;
328
329         gnome_canvas_set_scroll_region (GNOME_CANVAS (view->canvas),
330                                         0.0, 0.0, label_width, label_height);
331
332         /* Draw background shape of label/card */
333         draw_bg_fg (view);
334         gl_debug (DEBUG_VIEW, "n_bg_items = %d, n_fg_items = %d",
335                   view->n_bg_items, view->n_fg_items);
336
337         g_signal_connect (G_OBJECT (view->canvas), "event",
338                           G_CALLBACK (canvas_event), view);
339
340         for (p_obj = label->objects; p_obj != NULL; p_obj = p_obj->next) {
341                 object = (glLabelObject *) p_obj->data;
342
343                 if (GL_IS_LABEL_BOX (object)) {
344                         view_object = gl_view_box_new (GL_LABEL_BOX(object),
345                                                        view);
346                 } else if (GL_IS_LABEL_ELLIPSE (object)) {
347                         view_object = gl_view_ellipse_new (GL_LABEL_ELLIPSE(object),
348                                                            view);
349                 } else if (GL_IS_LABEL_LINE (object)) {
350                         view_object = gl_view_line_new (GL_LABEL_LINE(object),
351                                                         view);
352                 } else if (GL_IS_LABEL_IMAGE (object)) {
353                         view_object = gl_view_image_new (GL_LABEL_IMAGE(object),
354                                                          view);
355                 } else if (GL_IS_LABEL_TEXT (object)) {
356                         view_object = gl_view_text_new (GL_LABEL_TEXT(object),
357                                                         view);
358                 } else if (GL_IS_LABEL_BARCODE (object)) {
359                         view_object = gl_view_barcode_new (GL_LABEL_BARCODE(object),
360                                                            view);
361                 } else {
362                         /* Should not happen! */
363                         view_object = NULL;
364                         g_warning ("Invalid label object type.");
365                 }
366         }
367
368         gl_debug (DEBUG_VIEW, "END");
369
370         return view->canvas;
371 }
372
373 /*---------------------------------------------------------------------------*/
374 /* PRIVATE.  Create clipboard selection targets.                             */
375 /*---------------------------------------------------------------------------*/
376 static void
377 gl_view_construct_selection (glView *view)
378 {
379         gl_debug (DEBUG_VIEW, "START");
380
381         g_return_if_fail (GL_IS_VIEW (view));
382
383         view->have_selection = FALSE;
384         view->selection_data = NULL;
385         view->invisible = gtk_invisible_new ();
386
387         view->selected_object_list = NULL;
388
389         if (!clipboard_atom) {
390                 clipboard_atom = gdk_atom_intern ("GLABELS_CLIPBOARD", FALSE);
391         }
392
393         gtk_selection_add_target (view->invisible,
394                                   clipboard_atom, GDK_SELECTION_TYPE_STRING, 1);
395
396         g_signal_connect (G_OBJECT (view->invisible),
397                           "selection_clear_event",
398                           G_CALLBACK (selection_clear_cb), view);
399
400         g_signal_connect (G_OBJECT (view->invisible), "selection_get",
401                           G_CALLBACK (selection_get_cb), view);
402
403         g_signal_connect (G_OBJECT (view->invisible),
404                           "selection_received",
405                           G_CALLBACK (selection_received_cb), view);
406
407         gl_debug (DEBUG_VIEW, "END");
408 }
409
410 /*---------------------------------------------------------------------------*/
411 /* PRIVATE.  Determine an apropriate scale for given label & screen size     */
412 /*---------------------------------------------------------------------------*/
413 static gdouble
414 get_apropriate_scale (gdouble w, gdouble h)
415 {
416         gdouble w_screen, h_screen;
417         gint i;
418         gdouble k;
419
420         gl_debug (DEBUG_VIEW, "");
421
422         w_screen = (gdouble) gdk_screen_width ();
423         h_screen = (gdouble) gdk_screen_height ();
424
425         for (i = 0; scales[i] > 0.0; i++) {
426                 k = scales[i];
427                 if (k <= HOME_SCALE) {
428                         if ((k * w < (w_screen - 256))
429                             && (k * h < (h_screen - 256)))
430                                 return k;
431                 }
432         }
433
434         return 0.25;
435 }
436
437 /*---------------------------------------------------------------------------*/
438 /* PRIVATE.  Draw background and foreground outlines.                        */
439 /*---------------------------------------------------------------------------*/
440 static void
441 draw_bg_fg (glView *view)
442 {
443         glLabel    *label;
444         glTemplate *template;
445
446         view->n_bg_items = 0;
447         view->bg_item_list = NULL;
448         view->n_fg_items = 0;
449         view->fg_item_list = NULL;
450
451         label = view->label;
452         template = gl_label_get_template (label);
453
454         switch (template->label.style) {
455
456         case GL_TEMPLATE_STYLE_RECT:
457                 if (template->label.rect.r == 0.0) {
458                         /* Square corners. */
459                         draw_bg_fg_rect (view);
460                 } else {
461                         /* Rounded corners. */
462                         draw_bg_fg_rounded_rect (view);
463                 }
464                 break;
465
466         case GL_TEMPLATE_STYLE_ROUND:
467                 draw_bg_fg_round (view);
468                 break;
469
470         case GL_TEMPLATE_STYLE_CD:
471                 draw_bg_fg_cd (view);
472                 break;
473
474         default:
475                 g_warning ("Unknown template label style");
476                 break;
477         }
478 }
479
480 /*---------------------------------------------------------------------------*/
481 /* PRIVATE.  Draw simple recangular background.                              */
482 /*---------------------------------------------------------------------------*/
483 static void
484 draw_bg_fg_rect (glView *view)
485 {
486         glLabel          *label = view->label;
487         glTemplate       *template;
488         gdouble           w, h;
489         GnomeCanvasItem  *item;
490         GnomeCanvasGroup *group;
491
492         gl_debug (DEBUG_VIEW, "START");
493
494         g_return_if_fail (GL_IS_VIEW (view));
495         g_return_if_fail (label != NULL);
496
497         gl_label_get_size (label, &w, &h);
498         template = gl_label_get_template (label);
499
500         group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
501
502         /* Background */
503         item = gnome_canvas_item_new (group,
504                                       gnome_canvas_rect_get_type (),
505                                       "x1", 0.0,
506                                       "y1", 0.0,
507                                       "x2", w,
508                                       "y2", h,
509                                       "fill_color", "white",
510                                       NULL);
511         view->n_bg_items++;
512         view->bg_item_list = g_list_append (view->bg_item_list, item);
513
514         /* Markup */
515         draw_markup (view);
516
517         /* Foreground */
518         item = gnome_canvas_item_new (group,
519                                       gnome_canvas_rect_get_type (),
520                                       "x1", 0.0,
521                                       "y1", 0.0,
522                                       "x2", w,
523                                       "y2", h,
524                                       "width_pixels", 2,
525                                       "outline_color", "light blue",
526                                       NULL);
527         view->n_fg_items++;
528         view->fg_item_list = g_list_append (view->fg_item_list, item);
529
530         gl_debug (DEBUG_VIEW, "END");
531 }
532
533 /*---------------------------------------------------------------------------*/
534 /* PRIVATE.  Draw rounded recangular background.                             */
535 /*---------------------------------------------------------------------------*/
536 static void
537 draw_bg_fg_rounded_rect (glView *view)
538 {
539         glLabel           *label = view->label;
540         GnomeCanvasPoints *points;
541         gint               i_coords, i_theta;
542         glTemplate        *template;
543         gdouble            r, w, h;
544         GnomeCanvasItem   *item;
545         GnomeCanvasGroup  *group;
546
547         gl_debug (DEBUG_VIEW, "START");
548
549         g_return_if_fail (GL_IS_VIEW (view));
550         g_return_if_fail (label != NULL);
551
552         group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
553
554         gl_label_get_size (label, &w, &h);
555         template = gl_label_get_template (label);
556         r = template->label.rect.r;
557
558         points = gnome_canvas_points_new (4 * (1 + 90 / 5));
559         i_coords = 0;
560         for (i_theta = 0; i_theta <= 90; i_theta += 5) {
561                 points->coords[i_coords++] =
562                     r - r * sin (i_theta * M_PI / 180.0);
563                 points->coords[i_coords++] =
564                     r - r * cos (i_theta * M_PI / 180.0);
565         }
566         for (i_theta = 0; i_theta <= 90; i_theta += 5) {
567                 points->coords[i_coords++] =
568                     r - r * cos (i_theta * M_PI / 180.0);
569                 points->coords[i_coords++] =
570                     (h - r) + r * sin (i_theta * M_PI / 180.0);
571         }
572         for (i_theta = 0; i_theta <= 90; i_theta += 5) {
573                 points->coords[i_coords++] =
574                     (w - r) + r * sin (i_theta * M_PI / 180.0);
575                 points->coords[i_coords++] =
576                     (h - r) + r * cos (i_theta * M_PI / 180.0);
577         }
578         for (i_theta = 0; i_theta <= 90; i_theta += 5) {
579                 points->coords[i_coords++] =
580                     (w - r) + r * cos (i_theta * M_PI / 180.0);
581                 points->coords[i_coords++] =
582                     r - r * sin (i_theta * M_PI / 180.0);
583         }
584
585         /* Background */
586         item = gnome_canvas_item_new (group,
587                                       gnome_canvas_polygon_get_type (),
588                                       "points", points,
589                                       "fill_color", "white",
590                                       NULL);
591         view->n_bg_items++;
592         view->bg_item_list = g_list_append (view->bg_item_list, item);
593
594         /* Markup */
595         draw_markup (view);
596
597         /* Foreground */
598         item = gnome_canvas_item_new (group,
599                                       gnome_canvas_polygon_get_type (),
600                                       "points", points,
601                                       "width_pixels", 2,
602                                       "outline_color", "light blue",
603                                       NULL);
604         view->n_fg_items++;
605         view->fg_item_list = g_list_append (view->fg_item_list, item);
606
607         gnome_canvas_points_free (points);
608
609         gl_debug (DEBUG_VIEW, "END");
610 }
611
612 /*---------------------------------------------------------------------------*/
613 /* PRIVATE.  Draw round background.                                          */
614 /*---------------------------------------------------------------------------*/
615 static void
616 draw_bg_fg_round (glView *view)
617 {
618         glLabel          *label = view->label;
619         glTemplate       *template;
620         gdouble           r;
621         GnomeCanvasItem  *item;
622         GnomeCanvasGroup *group;
623
624         gl_debug (DEBUG_VIEW, "START");
625
626         g_return_if_fail (GL_IS_VIEW (view));
627         g_return_if_fail (label != NULL);
628
629         template = gl_label_get_template (label);
630
631         group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
632
633         r = template->label.round.r;
634
635         /* Background */
636         item = gnome_canvas_item_new (group,
637                                       gnome_canvas_ellipse_get_type (),
638                                       "x1", 0.0,
639                                       "y1", 0.0,
640                                       "x2", 2.0*r,
641                                       "y2", 2.0*r,
642                                       "fill_color", "white",
643                                       NULL);
644         view->n_bg_items++;
645         view->bg_item_list = g_list_append (view->bg_item_list, item);
646
647         /* Markup */
648         draw_markup (view);
649
650         /* Foreground */
651         item = gnome_canvas_item_new (group,
652                                       gnome_canvas_ellipse_get_type (),
653                                       "x1", 0.0,
654                                       "y1", 0.0,
655                                       "x2", 2.0*r,
656                                       "y2", 2.0*r,
657                                       "width_pixels", 2,
658                                       "outline_color", "light blue",
659                                       NULL);
660         view->n_fg_items++;
661         view->fg_item_list = g_list_append (view->fg_item_list, item);
662
663         gl_debug (DEBUG_VIEW, "END");
664 }
665
666 /*---------------------------------------------------------------------------*/
667 /* PRIVATE.  Draw CD style background, circular w/ concentric hole.          */
668 /*---------------------------------------------------------------------------*/
669 static void
670 draw_bg_fg_cd (glView *view)
671 {
672         glLabel          *label = view->label;
673         glTemplate       *template;
674         gdouble           r1, r2;
675         GnomeCanvasItem  *item;
676         GnomeCanvasGroup *group;
677
678         gl_debug (DEBUG_VIEW, "START");
679
680         g_return_if_fail (GL_IS_VIEW (view));
681         g_return_if_fail (label != NULL);
682
683         template = gl_label_get_template (label);
684
685         group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
686
687         r1 = template->label.cd.r1;
688         r2 = template->label.cd.r2;
689
690         /* Background */
691         /* outer circle */
692         item = gnome_canvas_item_new (group,
693                                       gnome_canvas_ellipse_get_type (),
694                                       "x1", 0.0,
695                                       "y1", 0.0,
696                                       "x2", 2.0*r1,
697                                       "y2", 2.0*r1,
698                                       "fill_color", "white",
699                                       NULL);
700         view->n_bg_items++;
701         view->bg_item_list = g_list_append (view->bg_item_list, item);
702         /* hole */
703         item = gnome_canvas_item_new (group,
704                                       gnome_canvas_ellipse_get_type (),
705                                       "x1", r1 - r2,
706                                       "y1", r1 - r2,
707                                       "x2", r1 + r2,
708                                       "y2", r1 + r2,
709                                       "fill_color", "gray",
710                                       NULL);
711         view->n_bg_items++;
712         view->bg_item_list = g_list_append (view->bg_item_list, item);
713
714         /* Markup */
715         draw_markup (view);
716
717         /* Foreground */
718         /* outer circle */
719         item = gnome_canvas_item_new (group,
720                                       gnome_canvas_ellipse_get_type (),
721                                       "x1", 0.0,
722                                       "y1", 0.0,
723                                       "x2", 2.0*r1,
724                                       "y2", 2.0*r1,
725                                       "width_pixels", 2,
726                                       "outline_color", "light blue",
727                                       NULL);
728         view->n_fg_items++;
729         view->fg_item_list = g_list_append (view->fg_item_list, item);
730         /* hole */
731         item = gnome_canvas_item_new (group,
732                                       gnome_canvas_ellipse_get_type (),
733                                       "x1", r1 - r2,
734                                       "y1", r1 - r2,
735                                       "x2", r1 + r2,
736                                       "y2", r1 + r2,
737                                       "width_pixels", 2,
738                                       "outline_color", "light blue",
739                                       NULL);
740         view->n_fg_items++;
741         view->fg_item_list = g_list_append (view->fg_item_list, item);
742
743         gl_debug (DEBUG_VIEW, "END");
744 }
745
746 /*---------------------------------------------------------------------------*/
747 /* PRIVATE.  Draw markup lines.                                              */
748 /*---------------------------------------------------------------------------*/
749 static void
750 draw_markup (glView *view)
751 {
752         glLabel          *label;
753         glTemplate       *template;
754         GList            *p;
755         glTemplateMarkup *markup;
756
757         label = view->label;
758         template = gl_label_get_template (label);
759
760         for ( p=template->label.any.markups; p != NULL; p=p->next ) {
761                 markup = (glTemplateMarkup *)p->data;
762
763                 switch (markup->type) {
764                 case GL_TEMPLATE_MARKUP_MARGIN:
765                         draw_markup_margin (view,
766                                             (glTemplateMarkupMargin *)markup);
767                         break;
768                 default:
769                         g_warning ("Unknown template markup type");
770                         break;
771                 }
772         }
773 }
774
775 /*---------------------------------------------------------------------------*/
776 /* PRIVATE.  Draw margin markup.                                             */
777 /*---------------------------------------------------------------------------*/
778 static void
779 draw_markup_margin (glView                 *view,
780                     glTemplateMarkupMargin *margin)
781 {
782         glLabel    *label;
783         glTemplate *template;
784
785         label = view->label;
786         template = gl_label_get_template (label);
787
788         switch (template->label.style) {
789
790         case GL_TEMPLATE_STYLE_RECT:
791                 if (template->label.rect.r == 0.0) {
792                         /* Square corners. */
793                         draw_markup_margin_rect (view, margin);
794                 } else {
795                         if ( margin->size < template->label.rect.r) {
796                                 /* Rounded corners. */
797                                 draw_markup_margin_rounded_rect (view, margin);
798                         } else {
799                                 /* Square corners. */
800                                 draw_markup_margin_rect (view, margin);
801                         }
802                 }
803                 break;
804
805         case GL_TEMPLATE_STYLE_ROUND:
806                 draw_markup_margin_round (view, margin);
807                 break;
808
809         case GL_TEMPLATE_STYLE_CD:
810                 draw_markup_margin_cd (view, margin);
811                 break;
812
813         default:
814                 g_warning ("Unknown template label style");
815                 break;
816         }
817 }
818
819 /*---------------------------------------------------------------------------*/
820 /* PRIVATE.  Draw simple recangular margin.                                  */
821 /*---------------------------------------------------------------------------*/
822 static void
823 draw_markup_margin_rect (glView                 *view,
824                          glTemplateMarkupMargin *margin)
825 {
826         glLabel          *label = view->label;
827         glTemplate       *template;
828         gdouble           w, h, m;
829         GnomeCanvasItem  *item;
830         GnomeCanvasGroup *group;
831
832         gl_debug (DEBUG_VIEW, "START");
833
834         g_return_if_fail (GL_IS_VIEW (view));
835         g_return_if_fail (label != NULL);
836
837         gl_label_get_size (label, &w, &h);
838         template = gl_label_get_template (label);
839         m = margin->size;
840
841         group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
842
843         /* Bounding box @ margin */
844         gnome_canvas_item_new (group,
845                                gnome_canvas_rect_get_type (),
846                                "x1", m,
847                                "y1", m,
848                                "x2", w - m,
849                                "y2", h - m,
850                                "width_pixels", 1,
851                                "outline_color", "light blue",
852                                NULL);
853         view->n_bg_items++;
854         view->bg_item_list = g_list_append (view->bg_item_list, item);
855
856         gl_debug (DEBUG_VIEW, "END");
857 }
858
859 /*---------------------------------------------------------------------------*/
860 /* PRIVATE.  Draw rounded recangular markup.                                 */
861 /*---------------------------------------------------------------------------*/
862 static void
863 draw_markup_margin_rounded_rect (glView                 *view,
864                                  glTemplateMarkupMargin *margin)
865 {
866         glLabel           *label = view->label;
867         GnomeCanvasPoints *points;
868         gint               i_coords, i_theta;
869         glTemplate        *template;
870         gdouble            r, w, h, m;
871         GnomeCanvasItem   *item;
872         GnomeCanvasGroup  *group;
873
874         gl_debug (DEBUG_VIEW, "START");
875
876         g_return_if_fail (GL_IS_VIEW (view));
877         g_return_if_fail (label != NULL);
878
879         group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
880
881         gl_label_get_size (label, &w, &h);
882         template = gl_label_get_template (label);
883         r = template->label.rect.r;
884         m = margin->size;
885
886         r = r - m;
887         w = w - 2 * m;
888         h = h - 2 * m;
889
890         /* rectangle with rounded corners */
891         points = gnome_canvas_points_new (4 * (1 + 90 / 5));
892         i_coords = 0;
893         for (i_theta = 0; i_theta <= 90; i_theta += 5) {
894                 points->coords[i_coords++] =
895                         m + r - r * sin (i_theta * M_PI / 180.0);
896                 points->coords[i_coords++] =
897                         m + r - r * cos (i_theta * M_PI / 180.0);
898         }
899         for (i_theta = 0; i_theta <= 90; i_theta += 5) {
900                 points->coords[i_coords++] =
901                         m + r - r * cos (i_theta * M_PI / 180.0);
902                 points->coords[i_coords++] =
903                         m + (h - r) + r * sin (i_theta * M_PI / 180.0);
904         }
905         for (i_theta = 0; i_theta <= 90; i_theta += 5) {
906                 points->coords[i_coords++] =
907                         m + (w - r) + r * sin (i_theta * M_PI / 180.0);
908                 points->coords[i_coords++] =
909                         m + (h - r) + r * cos (i_theta * M_PI / 180.0);
910         }
911         for (i_theta = 0; i_theta <= 90; i_theta += 5) {
912                 points->coords[i_coords++] =
913                         m + (w - r) + r * cos (i_theta * M_PI / 180.0);
914                 points->coords[i_coords++] =
915                         m + r - r * sin (i_theta * M_PI / 180.0);
916         }
917         item = gnome_canvas_item_new (group,
918                                       gnome_canvas_polygon_get_type (),
919                                       "points", points,
920                                       "width_pixels", 1,
921                                       "outline_color", "light blue",
922                                       NULL);
923         gnome_canvas_points_free (points);
924         view->n_bg_items++;
925         view->bg_item_list = g_list_append (view->bg_item_list, item);
926
927         gl_debug (DEBUG_VIEW, "END");
928 }
929
930 /*---------------------------------------------------------------------------*/
931 /* PRIVATE.  Draw round margin.                                              */
932 /*---------------------------------------------------------------------------*/
933 static void
934 draw_markup_margin_round (glView                 *view,
935                           glTemplateMarkupMargin *margin)
936 {
937         glLabel          *label = view->label;
938         glTemplate       *template;
939         gdouble           r, m;
940         GnomeCanvasItem  *item;
941         GnomeCanvasGroup *group;
942
943         gl_debug (DEBUG_VIEW, "START");
944
945         g_return_if_fail (GL_IS_VIEW (view));
946         g_return_if_fail (label != NULL);
947
948         template = gl_label_get_template (label);
949
950         group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
951
952         r = template->label.round.r;
953         m = margin->size;
954
955         /* Margin outline */
956         item = gnome_canvas_item_new (group,
957                                       gnome_canvas_ellipse_get_type (),
958                                       "x1", m,
959                                       "y1", m,
960                                       "x2", 2.0*r - m,
961                                       "y2", 2.0*r - m,
962                                       "width_pixels", 1,
963                                       "outline_color", "light blue", NULL);
964         view->n_bg_items++;
965         view->bg_item_list = g_list_append (view->bg_item_list, item);
966
967         gl_debug (DEBUG_VIEW, "END");
968 }
969
970 /*---------------------------------------------------------------------------*/
971 /* PRIVATE.  Draw CD margins.                                                */
972 /*---------------------------------------------------------------------------*/
973 static void
974 draw_markup_margin_cd (glView                 *view,
975                        glTemplateMarkupMargin *margin)
976 {
977         glLabel          *label = view->label;
978         glTemplate       *template;
979         gdouble           m, r1, r2;
980         GnomeCanvasItem  *item;
981         GnomeCanvasGroup *group;
982
983         gl_debug (DEBUG_VIEW, "START");
984
985         g_return_if_fail (GL_IS_VIEW (view));
986         g_return_if_fail (label != NULL);
987
988         template = gl_label_get_template (label);
989
990         group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
991
992         r1 = template->label.cd.r1;
993         r2 = template->label.cd.r2;
994         m  = margin->size;
995
996         /* outer margin */
997         item = gnome_canvas_item_new (group,
998                                       gnome_canvas_ellipse_get_type (),
999                                       "x1", m,
1000                                       "y1", m,
1001                                       "x2", 2.0*r1 - m,
1002                                       "y2", 2.0*r1 - m,
1003                                       "width_pixels", 1,
1004                                       "outline_color", "light blue", NULL);
1005         view->n_bg_items++;
1006         view->bg_item_list = g_list_append (view->bg_item_list, item);
1007         /* inner margin */
1008         item = gnome_canvas_item_new (group,
1009                                       gnome_canvas_ellipse_get_type (),
1010                                       "x1", r1 - r2 - m,
1011                                       "y1", r1 - r2 - m,
1012                                       "x2", r1 + r2 + m,
1013                                       "y2", r1 + r2 + m,
1014                                       "width_pixels", 1,
1015                                       "outline_color", "light blue",
1016                                       NULL);
1017         view->n_bg_items++;
1018         view->bg_item_list = g_list_append (view->bg_item_list, item);
1019
1020         gl_debug (DEBUG_VIEW, "END");
1021 }
1022
1023 /*****************************************************************************/
1024 /* Raise foreground items to top.                                            */
1025 /*****************************************************************************/
1026 void
1027 gl_view_raise_fg (glView *view)
1028 {
1029         GList *p;
1030
1031         for (p = view->fg_item_list; p != NULL; p = p->next) {
1032                 gnome_canvas_item_raise_to_top (GNOME_CANVAS_ITEM(p->data));
1033         }
1034 }
1035
1036 /*****************************************************************************/
1037 /* Set arrow mode.                                                           */
1038 /*****************************************************************************/
1039 void
1040 gl_view_arrow_mode (glView *view)
1041 {
1042         static GdkCursor *cursor = NULL;
1043
1044         gl_debug (DEBUG_VIEW, "START");
1045
1046         g_return_if_fail (GL_IS_VIEW (view));
1047
1048         if (!cursor) {
1049                 cursor = gdk_cursor_new (GDK_LEFT_PTR);
1050         }
1051
1052         gdk_window_set_cursor (view->canvas->window, cursor);
1053
1054         view->state = GL_VIEW_STATE_ARROW;
1055
1056         gl_debug (DEBUG_VIEW, "END");
1057 }
1058
1059 /*****************************************************************************/
1060 /* Set create text object mode.                                              */
1061 /*****************************************************************************/
1062 void
1063 gl_view_object_create_mode (glView            *view,
1064                             glLabelObjectType type)
1065 {
1066         GdkCursor *cursor;
1067
1068         gl_debug (DEBUG_VIEW, "START");
1069
1070         g_return_if_fail (GL_IS_VIEW (view));
1071
1072         switch (type) {
1073         case GL_LABEL_OBJECT_BOX:
1074                 cursor = gl_view_box_get_create_cursor ();
1075                 break;
1076         case GL_LABEL_OBJECT_ELLIPSE:
1077                 cursor = gl_view_ellipse_get_create_cursor ();
1078                 break;
1079         case GL_LABEL_OBJECT_LINE:
1080                 cursor = gl_view_line_get_create_cursor ();
1081                 break;
1082         case GL_LABEL_OBJECT_IMAGE:
1083                 cursor = gl_view_image_get_create_cursor ();
1084                 break;
1085         case GL_LABEL_OBJECT_TEXT:
1086                 cursor = gl_view_text_get_create_cursor ();
1087                 break;
1088         case GL_LABEL_OBJECT_BARCODE:
1089                 cursor = gl_view_barcode_get_create_cursor ();
1090                 break;
1091         default:
1092                 g_warning ("Invalid label object type.");/*Should not happen!*/
1093                 break;
1094         }
1095
1096         gdk_window_set_cursor (view->canvas->window, cursor);
1097
1098         view->state = GL_VIEW_STATE_OBJECT_CREATE;
1099         view->create_type = type;
1100
1101         gl_debug (DEBUG_VIEW, "END");
1102 }
1103
1104 /*****************************************************************************/
1105 /* Select given object (adding to current selection).                        */
1106 /*****************************************************************************/
1107 void
1108 gl_view_select_object (glView       *view,
1109                        glViewObject *view_object)
1110 {
1111         gl_debug (DEBUG_VIEW, "START");
1112
1113         select_object_real (view, view_object);
1114
1115         g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1116
1117         gl_debug (DEBUG_VIEW, "END");
1118 }
1119
1120 /*****************************************************************************/
1121 /* Unselect given object (removing from current selection).                  */
1122 /*****************************************************************************/
1123 void
1124 gl_view_unselect_object (glView       *view,
1125                          glViewObject *view_object)
1126 {
1127         gl_debug (DEBUG_VIEW, "START");
1128
1129         unselect_object_real (view, view_object);
1130
1131         g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1132
1133         gl_debug (DEBUG_VIEW, "END");
1134 }
1135
1136 /*****************************************************************************/
1137 /* Select all items.                                                         */
1138 /*****************************************************************************/
1139 void
1140 gl_view_select_all (glView *view)
1141 {
1142         GList *p, *p_next;
1143
1144         gl_debug (DEBUG_VIEW, "START");
1145
1146         g_return_if_fail (GL_IS_VIEW (view));
1147
1148         /* 1st unselect anything already selected. */
1149         for (p = view->selected_object_list; p != NULL; p = p_next) {
1150                 p_next = p->next;
1151                 unselect_object_real (view, GL_VIEW_OBJECT (p->data));
1152         }
1153
1154         /* Finally select all objects. */
1155         for (p = view->object_list; p != NULL; p = p->next) {
1156                 select_object_real (view, GL_VIEW_OBJECT (p->data));
1157         }
1158
1159         g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1160
1161         gl_debug (DEBUG_VIEW, "END");
1162 }
1163
1164 /*****************************************************************************/
1165 /* Remove all selections                                                     */
1166 /*****************************************************************************/
1167 void
1168 gl_view_unselect_all (glView *view)
1169 {
1170         GList *p, *p_next;
1171
1172         gl_debug (DEBUG_VIEW, "START");
1173
1174         g_return_if_fail (GL_IS_VIEW (view));
1175
1176         for (p = view->selected_object_list; p != NULL; p = p_next) {
1177                 p_next = p->next;
1178                 unselect_object_real (view, GL_VIEW_OBJECT (p->data));
1179         }
1180
1181         g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1182
1183         gl_debug (DEBUG_VIEW, "END");
1184 }
1185
1186 /*****************************************************************************/
1187 /* Select all objects within given rectangular region (adding to selection). */
1188 /*****************************************************************************/
1189 void
1190 gl_view_select_region (glView  *view,
1191                        gdouble  x1,
1192                        gdouble  y1,
1193                        gdouble  x2,
1194                        gdouble  y2)
1195 {
1196         GList *p;
1197         glViewObject *view_object;
1198         glLabelObject *object;
1199         gdouble i_x1, i_y1, i_x2, i_y2, w, h;
1200
1201         gl_debug (DEBUG_VIEW, "START");
1202
1203         g_return_if_fail (GL_IS_VIEW (view));
1204         g_return_if_fail ((x1 <= x2) && (y1 <= y2));
1205
1206         for (p = view->object_list; p != NULL; p = p->next) {
1207                 view_object = GL_VIEW_OBJECT(p->data);
1208                 if (!is_object_selected (view, view_object)) {
1209
1210                         object = gl_view_object_get_object (view_object);
1211
1212                         gl_label_object_get_position (object, &i_x1, &i_y1);
1213                         gl_label_object_get_size (object, &w, &h);
1214                         i_x2 = i_x1 + w;
1215                         i_y2 = i_y1 + h;
1216                         if ((i_x1 >= x1) && (i_x2 <= x2) && (i_y1 >= y1)
1217                             && (i_y2 <= y2)) {
1218                                 select_object_real (view, view_object);
1219                         }
1220
1221                 }
1222         }
1223
1224         g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1225
1226         gl_debug (DEBUG_VIEW, "END");
1227 }
1228
1229 /*---------------------------------------------------------------------------*/
1230 /* PRIVATE. Select an object.                                                */
1231 /*---------------------------------------------------------------------------*/
1232 static void
1233 select_object_real (glView       *view,
1234                     glViewObject *view_object)
1235 {
1236         gl_debug (DEBUG_VIEW, "START");
1237
1238         g_return_if_fail (GL_IS_VIEW (view));
1239         g_return_if_fail (GL_IS_VIEW_OBJECT (view_object));
1240
1241         if (!is_object_selected (view, view_object)) {
1242                 view->selected_object_list =
1243                     g_list_prepend (view->selected_object_list, view_object);
1244         }
1245         gl_view_object_show_highlight (view_object);
1246         gtk_widget_grab_focus (GTK_WIDGET (view->canvas));
1247
1248         gl_debug (DEBUG_VIEW, "END");
1249 }
1250
1251 /*---------------------------------------------------------------------------*/
1252 /* PRIVATE.  Un-select object.                                               */
1253 /*---------------------------------------------------------------------------*/
1254 static void
1255 unselect_object_real (glView       *view,
1256                       glViewObject *view_object)
1257 {
1258         gl_debug (DEBUG_VIEW, "START");
1259
1260         g_return_if_fail (GL_IS_VIEW (view));
1261         g_return_if_fail (GL_IS_VIEW_OBJECT (view_object));
1262
1263         gl_view_object_hide_highlight (view_object);
1264
1265         view->selected_object_list =
1266             g_list_remove (view->selected_object_list, view_object);
1267
1268         gl_debug (DEBUG_VIEW, "END");
1269 }
1270
1271 /*---------------------------------------------------------------------------*/
1272 /* PRIVATE. Return object at (x,y).                                          */
1273 /*---------------------------------------------------------------------------*/
1274 static gboolean
1275 object_at (glView  *view,
1276            gdouble  x,
1277            gdouble  y)
1278 {
1279         GnomeCanvasItem *item, *p_item;
1280         GList *p;
1281
1282         gl_debug (DEBUG_VIEW, "");
1283
1284         g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
1285
1286         item = gnome_canvas_get_item_at (GNOME_CANVAS (view->canvas), x, y);
1287
1288         /* No item is at x, y */
1289         if (item == NULL)
1290                 return FALSE;
1291
1292         /* ignore our background items */
1293         if (g_list_find (view->bg_item_list, item) != NULL)
1294                 return FALSE;
1295
1296         return TRUE;
1297 }
1298
1299 /*---------------------------------------------------------------------------*/
1300 /* PRIVATE.  Is the object in our current selection?                         */
1301 /*---------------------------------------------------------------------------*/
1302 static gboolean
1303 is_object_selected (glView       *view,
1304                     glViewObject *view_object)
1305 {
1306         gl_debug (DEBUG_VIEW, "");
1307
1308         g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
1309         g_return_val_if_fail (GL_IS_VIEW_OBJECT (view_object), FALSE);
1310
1311         if (g_list_find (view->selected_object_list, view_object) == NULL) {
1312                 return FALSE;
1313         }
1314         return TRUE;
1315 }
1316
1317 /*****************************************************************************/
1318 /* Is our current selection empty?                                           */
1319 /*****************************************************************************/
1320 gboolean
1321 gl_view_is_selection_empty (glView *view)
1322 {
1323         gl_debug (DEBUG_VIEW, "");
1324
1325         g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
1326
1327         if (view->selected_object_list == NULL) {
1328                 return TRUE;
1329         } else {
1330                 return FALSE;
1331         }
1332 }
1333
1334 /*****************************************************************************/
1335 /* Is our current selection atomic?  I.e. only one item selected.            */
1336 /*****************************************************************************/
1337 gboolean
1338 gl_view_is_selection_atomic (glView *view)
1339 {
1340         gl_debug (DEBUG_VIEW, "");
1341
1342         g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
1343
1344         if (view->selected_object_list == NULL)
1345                 return FALSE;
1346         if (view->selected_object_list->next == NULL)
1347                 return TRUE;
1348         return FALSE;
1349 }
1350
1351 /*****************************************************************************/
1352 /* Delete selected objects. (Bypass clipboard)                               */
1353 /*****************************************************************************/
1354 void
1355 gl_view_delete_selection (glView *view)
1356 {
1357         GList *p, *p_next;
1358
1359         gl_debug (DEBUG_VIEW, "START");
1360
1361         g_return_if_fail (GL_IS_VIEW (view));
1362
1363         for (p = view->selected_object_list; p != NULL; p = p_next) {
1364                 p_next = p->next;
1365                 g_object_unref (G_OBJECT (p->data));
1366         }
1367
1368         g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1369
1370         gl_debug (DEBUG_VIEW, "END");
1371 }
1372
1373 /*****************************************************************************/
1374 /* Edit properties of selected object.                                       */
1375 /*****************************************************************************/
1376 void
1377 gl_view_edit_object_props (glView *view)
1378 {
1379         glViewObject *view_object;
1380
1381         gl_debug (DEBUG_VIEW, "START");
1382
1383         g_return_if_fail (GL_IS_VIEW (view));
1384
1385         if (gl_view_is_selection_atomic (view)) {
1386
1387                 view_object = GL_VIEW_OBJECT(view->selected_object_list->data);
1388                 gl_view_object_show_dialog (view_object);
1389
1390         }
1391
1392         gl_debug (DEBUG_VIEW, "END");
1393 }
1394
1395 /*****************************************************************************/
1396 /* Raise selected items to top.                                              */
1397 /*****************************************************************************/
1398 void
1399 gl_view_raise_selection (glView *view)
1400 {
1401         GList *p;
1402         glViewObject *view_object;
1403         glLabelObject *label_object;
1404
1405         gl_debug (DEBUG_VIEW, "START");
1406
1407         g_return_if_fail (GL_IS_VIEW (view));
1408
1409         for (p = view->selected_object_list; p != NULL; p = p->next) {
1410                 view_object = GL_VIEW_OBJECT (p->data);
1411                 label_object = gl_view_object_get_object (view_object);
1412                 gl_label_object_raise_to_top (label_object);
1413         }
1414
1415         gl_debug (DEBUG_VIEW, "END");
1416 }
1417
1418 /*****************************************************************************/
1419 /* Lower selected items to bottom.                                           */
1420 /*****************************************************************************/
1421 void
1422 gl_view_lower_selection (glView *view)
1423 {
1424         GList *p;
1425         glViewObject *view_object;
1426         glLabelObject *label_object;
1427
1428         gl_debug (DEBUG_VIEW, "START");
1429
1430         g_return_if_fail (GL_IS_VIEW (view));
1431
1432         for (p = view->selected_object_list; p != NULL; p = p->next) {
1433                 view_object = GL_VIEW_OBJECT (p->data);
1434                 label_object = gl_view_object_get_object (view_object);
1435                 gl_label_object_lower_to_bottom (label_object);
1436         }
1437
1438         gl_debug (DEBUG_VIEW, "END");
1439 }
1440
1441 /*****************************************************************************/
1442 /* "Cut" selected items and place in clipboard selections.                   */
1443 /*****************************************************************************/
1444 void
1445 gl_view_cut (glView *view)
1446 {
1447         gl_debug (DEBUG_VIEW, "START");
1448
1449         g_return_if_fail (GL_IS_VIEW (view));
1450
1451         gl_view_copy (view);
1452         gl_view_delete_selection (view);
1453
1454         gl_debug (DEBUG_VIEW, "END");
1455 }
1456
1457 /*****************************************************************************/
1458 /* "Copy" selected items to clipboard selections.                            */
1459 /*****************************************************************************/
1460 void
1461 gl_view_copy (glView *view)
1462 {
1463         GList *p;
1464         glViewObject *view_object;
1465         glLabelObject *object;
1466         glTemplate *template;
1467         gboolean rotate_flag;
1468
1469         gl_debug (DEBUG_VIEW, "START");
1470
1471         g_return_if_fail (GL_IS_VIEW (view));
1472
1473         if (view->selected_object_list) {
1474
1475                 if ( view->selection_data ) {
1476                         g_object_unref (view->selection_data);
1477                 }
1478                 template = gl_label_get_template (view->label);
1479                 rotate_flag = gl_label_get_rotate_flag (view->label);
1480                 view->selection_data = GL_LABEL(gl_label_new ());
1481                 gl_label_set_template (view->selection_data, template);
1482                 gl_label_set_rotate_flag (view->selection_data, rotate_flag);
1483                 gl_template_free (&template);
1484
1485                 for (p = view->selected_object_list; p != NULL; p = p->next) {
1486
1487                         view_object = GL_VIEW_OBJECT (p->data);
1488                         object = gl_view_object_get_object (view_object);
1489
1490                         gl_debug (DEBUG_VIEW, "Object copied");
1491
1492                         if (GL_IS_LABEL_BOX (object)) {
1493                                 gl_label_box_dup (GL_LABEL_BOX(object),
1494                                                   view->selection_data);
1495                         } else if (GL_IS_LABEL_ELLIPSE (object)) {
1496                                 gl_label_ellipse_dup (GL_LABEL_ELLIPSE(object),
1497                                                       view->selection_data);
1498                         } else if (GL_IS_LABEL_LINE (object)) {
1499                                 gl_label_line_dup (GL_LABEL_LINE(object),
1500                                                    view->selection_data);
1501                         } else if (GL_IS_LABEL_IMAGE (object)) {
1502                                 gl_label_image_dup (GL_LABEL_IMAGE(object),
1503                                                     view->selection_data);
1504                         } else if (GL_IS_LABEL_TEXT (object)) {
1505                                 gl_label_text_dup (GL_LABEL_TEXT(object),
1506                                                    view->selection_data);
1507                         } else if (GL_IS_LABEL_BARCODE (object)) {
1508                                 gl_label_barcode_dup (GL_LABEL_BARCODE(object),
1509                                                       view->selection_data);
1510                         } else {
1511                                 /* Should not happen! */
1512                                 g_warning ("Invalid label object type.");
1513                         }
1514
1515
1516                 }
1517
1518                 gtk_selection_owner_set (view->invisible,
1519                                          clipboard_atom, GDK_CURRENT_TIME);
1520                 view->have_selection = TRUE;
1521
1522         }
1523
1524         gl_debug (DEBUG_VIEW, "END");
1525 }
1526
1527 /*****************************************************************************/
1528 /* "Paste" from private clipboard selection.                                 */
1529 /*****************************************************************************/
1530 void
1531 gl_view_paste (glView *view)
1532 {
1533         gl_debug (DEBUG_VIEW, "START");
1534
1535         g_return_if_fail (GL_IS_VIEW (view));
1536
1537         gtk_selection_convert (GTK_WIDGET (view->invisible),
1538                                clipboard_atom, GDK_SELECTION_TYPE_STRING,
1539                                GDK_CURRENT_TIME);
1540
1541         gl_debug (DEBUG_VIEW, "END");
1542 }
1543
1544 /*---------------------------------------------------------------------------*/
1545 /* PRIVATE.  move selected objects                                           */
1546 /*---------------------------------------------------------------------------*/
1547 static void
1548 move_selection (glView  *view,
1549                 gdouble  dx,
1550                 gdouble  dy)
1551 {
1552         GList *p;
1553         glLabelObject *object;
1554
1555         gl_debug (DEBUG_VIEW, "START");
1556
1557         g_return_if_fail (GL_IS_VIEW (view));
1558
1559         for (p = view->selected_object_list; p != NULL; p = p->next) {
1560
1561                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
1562                 gl_label_object_set_position_relative (object, dx, dy);
1563
1564         }
1565
1566         gl_debug (DEBUG_VIEW, "END");
1567 }
1568
1569 /*****************************************************************************/
1570 /* Zoom in one "notch"                                                       */
1571 /*****************************************************************************/
1572 void
1573 gl_view_zoom_in (glView *view)
1574 {
1575         gint i, i_min;
1576         gdouble dist, dist_min;
1577
1578         gl_debug (DEBUG_VIEW, "START");
1579
1580         g_return_if_fail (GL_IS_VIEW (view));
1581
1582         /* Find index of current scale (or best match) */
1583         i_min = 1;              /* start with 2nd largest scale */
1584         dist_min = fabs (scales[1] - view->scale);
1585         for (i = 2; scales[i] != 0.0; i++) {
1586                 dist = fabs (scales[i] - view->scale);
1587                 if (dist < dist_min) {
1588                         i_min = i;
1589                         dist_min = dist;
1590                 }
1591         }
1592
1593         /* zoom in one "notch" */
1594         i = MAX (0, i_min - 1);
1595         gl_view_set_zoom (view, scales[i] / HOME_SCALE);
1596
1597         gl_debug (DEBUG_VIEW, "END");
1598 }
1599
1600 /*****************************************************************************/
1601 /* Zoom out one "notch"                                                      */
1602 /*****************************************************************************/
1603 void
1604 gl_view_zoom_out (glView *view)
1605 {
1606         gint i, i_min;
1607         gdouble dist, dist_min;
1608
1609         gl_debug (DEBUG_VIEW, "START");
1610
1611         g_return_if_fail (GL_IS_VIEW (view));
1612
1613         /* Find index of current scale (or best match) */
1614         i_min = 0;              /* start with largest scale */
1615         dist_min = fabs (scales[0] - view->scale);
1616         for (i = 1; scales[i] != 0.0; i++) {
1617                 dist = fabs (scales[i] - view->scale);
1618                 if (dist < dist_min) {
1619                         i_min = i;
1620                         dist_min = dist;
1621                 }
1622         }
1623
1624         /* zoom out one "notch" */
1625         if (scales[i_min] == 0.0)
1626                 return;
1627         i = i_min + 1;
1628         if (scales[i] == 0.0)
1629                 return;
1630         gl_view_set_zoom (view, scales[i] / HOME_SCALE);
1631
1632         gl_debug (DEBUG_VIEW, "END");
1633 }
1634
1635 /*****************************************************************************/
1636 /* Set current zoom factor to explicit value.                                */
1637 /*****************************************************************************/
1638 void
1639 gl_view_set_zoom (glView  *view,
1640                   gdouble scale)
1641 {
1642         gl_debug (DEBUG_VIEW, "START");
1643
1644         g_return_if_fail (GL_IS_VIEW (view));
1645         g_return_if_fail (scale > 0.0);
1646
1647         view->scale = scale * HOME_SCALE;
1648         gnome_canvas_set_pixels_per_unit (GNOME_CANVAS (view->canvas),
1649                                           scale * HOME_SCALE);
1650
1651         gl_debug (DEBUG_VIEW, "END");
1652 }
1653
1654 /*****************************************************************************/
1655 /* Get current zoom factor.                                                  */
1656 /*****************************************************************************/
1657 gdouble
1658 gl_view_get_zoom (glView *view)
1659 {
1660         gl_debug (DEBUG_VIEW, "");
1661
1662         g_return_val_if_fail (GL_IS_VIEW (view), 1.0);
1663
1664         return view->scale / HOME_SCALE;
1665 }
1666
1667 /*---------------------------------------------------------------------------*/
1668 /* PRIVATE.  Canvas event handler.                                           */
1669 /*---------------------------------------------------------------------------*/
1670 static int
1671 canvas_event (GnomeCanvas *canvas,
1672               GdkEvent    *event,
1673               glView      *view)
1674 {
1675         gl_debug (DEBUG_VIEW, "");
1676
1677         switch (view->state) {
1678
1679         case GL_VIEW_STATE_ARROW:
1680                 return canvas_event_arrow_mode (canvas, event, view);
1681
1682         case GL_VIEW_STATE_OBJECT_CREATE:
1683                 switch (view->create_type) {
1684                 case GL_LABEL_OBJECT_BOX:
1685                         return gl_view_box_create_event_handler (canvas,
1686                                                                  event,
1687                                                                  view);
1688                         break;
1689                 case GL_LABEL_OBJECT_ELLIPSE:
1690                         return gl_view_ellipse_create_event_handler (canvas,
1691                                                                      event,
1692                                                                      view);
1693                         break;
1694                 case GL_LABEL_OBJECT_LINE:
1695                         return gl_view_line_create_event_handler (canvas,
1696                                                                   event,
1697                                                                   view);
1698                         break;
1699                 case GL_LABEL_OBJECT_IMAGE:
1700                         return gl_view_image_create_event_handler (canvas,
1701                                                                    event,
1702                                                                    view);
1703                         break;
1704                 case GL_LABEL_OBJECT_TEXT:
1705                         return gl_view_text_create_event_handler (canvas,
1706                                                                   event,
1707                                                                   view);
1708                         break;
1709                 case GL_LABEL_OBJECT_BARCODE:
1710                         return gl_view_barcode_create_event_handler (canvas,
1711                                                                      event,
1712                                                                      view);
1713                         break;
1714                 default:
1715                         /*Should not happen!*/
1716                         g_warning ("Invalid label object type.");
1717                         return FALSE;
1718         }
1719
1720         default:
1721                 g_warning ("Invalid view state.");      /*Should not happen!*/
1722                 return FALSE;
1723
1724         }
1725 }
1726
1727 /*---------------------------------------------------------------------------*/
1728 /* PRIVATE.  Canvas event handler (arrow mode)                               */
1729 /*---------------------------------------------------------------------------*/
1730 static int
1731 canvas_event_arrow_mode (GnomeCanvas *canvas,
1732                          GdkEvent    *event,
1733                          glView      *view)
1734 {
1735         static gdouble x0, y0;
1736         static gboolean dragging = FALSE;
1737         static GnomeCanvasItem *item;
1738         gdouble x, y, x1, y1, x2, y2;
1739         GnomeCanvasGroup *group;
1740         GdkCursor *cursor;
1741
1742         gl_debug (DEBUG_VIEW, "");
1743
1744         switch (event->type) {
1745
1746         case GDK_BUTTON_PRESS:
1747                 gl_debug (DEBUG_VIEW, "BUTTON_PRESS");
1748                 switch (event->button.button) {
1749                 case 1:
1750                         gnome_canvas_window_to_world (canvas,
1751                                                       event->button.x,
1752                                                       event->button.y, &x, &y);
1753
1754                         if (!object_at (view, x, y)) {
1755                                 if (!(event->button.state & GDK_CONTROL_MASK)) {
1756                                         gl_view_unselect_all (view);
1757                                 }
1758
1759                                 dragging = TRUE;
1760                                 gdk_pointer_grab (GTK_WIDGET (view->canvas)->
1761                                                   window, FALSE,
1762                                                   GDK_POINTER_MOTION_MASK |
1763                                                   GDK_BUTTON_RELEASE_MASK |
1764                                                   GDK_BUTTON_PRESS_MASK, NULL,
1765                                                   NULL, event->button.time);
1766                                 group =
1767                                     gnome_canvas_root (GNOME_CANVAS
1768                                                        (view->canvas));
1769                                 item =
1770                                     gnome_canvas_item_new (group,
1771                                                            gnome_canvas_rect_get_type (),
1772                                                            "x1", x, "y1", y,
1773                                                            "x2", x, "y2", y,
1774                                                            "width_pixels", 2,
1775                                                            "outline_color_rgba",
1776                                                            SEL_LINE_COLOR,
1777                                                            "fill_color_rgba",
1778                                                            SEL_FILL_COLOR,
1779                                                            NULL);
1780                                 x0 = x;
1781                                 y0 = y;
1782
1783                         }
1784                         return FALSE;
1785
1786                 default:
1787                         return FALSE;
1788                 }
1789
1790         case GDK_BUTTON_RELEASE:
1791                 gl_debug (DEBUG_VIEW, "BUTTON_RELEASE");
1792                 switch (event->button.button) {
1793                 case 1:
1794                         if (dragging) {
1795                                 dragging = FALSE;
1796                                 gdk_pointer_ungrab (event->button.time);
1797                                 gnome_canvas_window_to_world (canvas,
1798                                                               event->button.x,
1799                                                               event->button.y,
1800                                                               &x, &y);
1801                                 x1 = MIN (x, x0);
1802                                 y1 = MIN (y, y0);
1803                                 x2 = MAX (x, x0);
1804                                 y2 = MAX (y, y0);
1805                                 gl_view_select_region (view, x1, y1, x2, y2);
1806                                 gtk_object_destroy (GTK_OBJECT (item));
1807                                 return TRUE;
1808                         }
1809                         return FALSE;
1810
1811                 default:
1812                         return FALSE;
1813                 }
1814
1815         case GDK_MOTION_NOTIFY:
1816                 gl_debug (DEBUG_VIEW, "MOTION_NOTIFY");
1817                 if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
1818                         gnome_canvas_window_to_world (canvas,
1819                                                       event->button.x,
1820                                                       event->button.y, &x, &y);
1821
1822                         gnome_canvas_item_set (item,
1823                                                "x1", MIN (x, x0),
1824                                                "y1", MIN (y, y0),
1825                                                "x2", MAX (x, x0),
1826                                                "y2", MAX (y, y0), NULL);
1827                         return TRUE;
1828                 } else {
1829                         return FALSE;
1830                 }
1831
1832         case GDK_KEY_PRESS:
1833                 gl_debug (DEBUG_VIEW, "KEY_PRESS");
1834                 if (!dragging) {
1835                         switch (event->key.keyval) {
1836                         case GDK_Left:
1837                         case GDK_KP_Left:
1838                                 move_selection (view,
1839                                                 -1.0 / (view->scale), 0.0);
1840                                 break;
1841                         case GDK_Up:
1842                         case GDK_KP_Up:
1843                                 move_selection (view,
1844                                                 0.0, -1.0 / (view->scale));
1845                                 break;
1846                         case GDK_Right:
1847                         case GDK_KP_Right:
1848                                 move_selection (view,
1849                                                 1.0 / (view->scale), 0.0);
1850                                 break;
1851                         case GDK_Down:
1852                         case GDK_KP_Down:
1853                                 move_selection (view,
1854                                                 0.0, 1.0 / (view->scale));
1855                                 break;
1856                         case GDK_Delete:
1857                         case GDK_KP_Delete:
1858                                 gl_view_delete_selection (view);
1859                                 cursor = gdk_cursor_new (GDK_LEFT_PTR);
1860                                 gdk_window_set_cursor (view->canvas->window,
1861                                                        cursor);
1862                                 gdk_cursor_unref (cursor);
1863                                 break;
1864                         default:
1865                                 return FALSE;
1866                         }
1867                 }
1868                 return TRUE;    /* We handled this or we were dragging. */
1869
1870         default:
1871                 gl_debug (DEBUG_VIEW, "default");
1872                 return FALSE;
1873         }
1874
1875 }
1876
1877 /*****************************************************************************/
1878 /* Item event handler.                                                       */
1879 /*****************************************************************************/
1880 gint
1881 gl_view_item_event_handler (GnomeCanvasItem *item,
1882                             GdkEvent        *event,
1883                             glViewObject    *view_object)
1884 {
1885         glView *view;
1886
1887         gl_debug (DEBUG_VIEW, "");
1888
1889         view = gl_view_object_get_view(view_object);
1890         switch (view->state) {
1891
1892         case GL_VIEW_STATE_ARROW:
1893                 return item_event_arrow_mode (item, event, view_object);
1894
1895         default:
1896                 return FALSE;
1897
1898         }
1899
1900 }
1901
1902 /*---------------------------------------------------------------------------*/
1903 /* PRIVATE.  Item event handler (arrow mode)                                 */
1904 /*---------------------------------------------------------------------------*/
1905 static int
1906 item_event_arrow_mode (GnomeCanvasItem *item,
1907                        GdkEvent        *event,
1908                        glViewObject    *view_object)
1909 {
1910         static gdouble x, y;
1911         static gboolean dragging = FALSE;
1912         glView *view;
1913         GdkCursor *cursor;
1914         gdouble item_x, item_y;
1915         gdouble new_x, new_y;
1916         gboolean control_key_pressed;
1917
1918         gl_debug (DEBUG_VIEW, "");
1919
1920         item_x = event->button.x;
1921         item_y = event->button.y;
1922         gnome_canvas_item_w2i (item->parent, &item_x, &item_y);
1923
1924         view = gl_view_object_get_view(view_object);
1925
1926         switch (event->type) {
1927
1928         case GDK_BUTTON_PRESS:
1929                 gl_debug (DEBUG_VIEW, "BUTTON_PRESS");
1930                 control_key_pressed = event->button.state & GDK_CONTROL_MASK;
1931                 switch (event->button.button) {
1932                 case 1:
1933                         if (control_key_pressed) {
1934                                 if (is_object_selected (view, view_object)) {
1935                                         /* Un-selecting a selected item */
1936                                         gl_view_unselect_object (view,
1937                                                                  view_object);
1938                                         return TRUE;
1939                                 } else {
1940                                         /* Add to current selection */
1941                                         gl_view_select_object (view,
1942                                                                view_object);
1943                                 }
1944                         } else {
1945                                 if (!is_object_selected (view, view_object)) {
1946                                         /* No control, key so remove any selections before adding */
1947                                         gl_view_unselect_all (view);
1948                                         /* Add to current selection */
1949                                         gl_view_select_object (view,
1950                                                                view_object);
1951                                 }
1952                         }
1953                         /* Go into dragging mode while button remains pressed. */
1954                         x = item_x;
1955                         y = item_y;
1956                         cursor = gdk_cursor_new (GDK_FLEUR);
1957                         gnome_canvas_item_grab (item,
1958                                                 GDK_POINTER_MOTION_MASK |
1959                                                 GDK_BUTTON_RELEASE_MASK |
1960                                                 GDK_BUTTON_PRESS_MASK,
1961                                                 cursor, event->button.time);
1962                         gdk_cursor_unref (cursor);
1963                         dragging = TRUE;
1964                         return TRUE;
1965
1966                 case 3:
1967                         if (!is_object_selected (view, view_object)) {
1968                                 if (!control_key_pressed) {
1969                                         /* No control, key so remove any selections before adding */
1970                                         gl_view_unselect_all (view);
1971                                 }
1972                         }
1973                         /* Add to current selection */
1974                         gl_view_select_object (view, view_object);
1975                         /* bring up apropriate menu for selection. */
1976                         popup_selection_menu (view, view_object, event);
1977                         return TRUE;
1978
1979                 default:
1980                         return FALSE;
1981                 }
1982
1983         case GDK_BUTTON_RELEASE:
1984                 gl_debug (DEBUG_VIEW, "BUTTON_RELEASE");
1985                 switch (event->button.button) {
1986                 case 1:
1987                         /* Exit dragging mode */
1988                         gnome_canvas_item_ungrab (item, event->button.time);
1989                         dragging = FALSE;
1990                         return TRUE;
1991
1992                 default:
1993                         return FALSE;
1994                 }
1995
1996         case GDK_MOTION_NOTIFY:
1997                 gl_debug (DEBUG_VIEW, "MOTION_NOTIFY");
1998                 if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
1999                         /* Dragging mode, move selection */
2000                         new_x = item_x;
2001                         new_y = item_y;
2002                         move_selection (view, (new_x - x), (new_y - y));
2003                         x = new_x;
2004                         y = new_y;
2005                         return TRUE;
2006                 } else {
2007                         return FALSE;
2008                 }
2009
2010         case GDK_2BUTTON_PRESS:
2011                 gl_debug (DEBUG_VIEW, "2BUTTON_PRESS");
2012                 switch (event->button.button) {
2013                 case 1:
2014                         /* Also exit dragging mode w/ double-click, run dlg */
2015                         gnome_canvas_item_ungrab (item, event->button.time);
2016                         dragging = FALSE;
2017                         gl_view_select_object (view, view_object);
2018                         gl_view_object_show_dialog (view_object);
2019                         return TRUE;
2020
2021                 default:
2022                         return FALSE;
2023                 }
2024
2025         case GDK_ENTER_NOTIFY:
2026                 gl_debug (DEBUG_VIEW, "ENTER_NOTIFY");
2027                 cursor = gdk_cursor_new (GDK_FLEUR);
2028                 gdk_window_set_cursor (view->canvas->window, cursor);
2029                 gdk_cursor_unref (cursor);
2030                 return TRUE;
2031
2032         case GDK_LEAVE_NOTIFY:
2033                 gl_debug (DEBUG_VIEW, "LEAVE_NOTIFY");
2034                 cursor = gdk_cursor_new (GDK_LEFT_PTR);
2035                 gdk_window_set_cursor (view->canvas->window, cursor);
2036                 gdk_cursor_unref (cursor);
2037                 return TRUE;
2038
2039         default:
2040                 gl_debug (DEBUG_VIEW, "default");
2041                 return FALSE;
2042         }
2043
2044 }
2045
2046 /*---------------------------------------------------------------------------*/
2047 /* PRIVATE.  create menu for multiple selections.                            */
2048 /*---------------------------------------------------------------------------*/
2049 GtkWidget *
2050 new_selection_menu (glView *view)
2051 {
2052         GtkWidget *menu, *menuitem;
2053
2054         gl_debug (DEBUG_VIEW, "START");
2055
2056         g_return_val_if_fail (GL_IS_VIEW (view), NULL);
2057
2058         menu = gtk_menu_new ();
2059
2060         menuitem = gtk_menu_item_new_with_label (_("Delete"));
2061         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
2062         gtk_widget_show (menuitem);
2063         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
2064                                   G_CALLBACK (gl_view_delete_selection), view);
2065
2066         menuitem = gtk_menu_item_new ();
2067         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
2068         gtk_widget_show (menuitem);
2069
2070         menuitem = gtk_menu_item_new_with_label (_("Bring to front"));
2071         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
2072         gtk_widget_show (menuitem);
2073         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
2074                                   G_CALLBACK (gl_view_raise_selection), view);
2075
2076         menuitem = gtk_menu_item_new_with_label (_("Send to back"));
2077         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
2078         gtk_widget_show (menuitem);
2079         g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
2080                                   G_CALLBACK (gl_view_lower_selection), view);
2081
2082         gl_debug (DEBUG_VIEW, "END");
2083
2084         return menu;
2085 }
2086
2087 /*---------------------------------------------------------------------------*/
2088 /* PRIVATE.  popup menu for given item.                                      */
2089 /*---------------------------------------------------------------------------*/
2090 static void
2091 popup_selection_menu (glView       *view,
2092                       glViewObject *view_object,
2093                       GdkEvent     *event)
2094 {
2095         GtkMenu *menu;
2096
2097         gl_debug (DEBUG_VIEW, "START");
2098
2099         g_return_if_fail (GL_IS_VIEW (view));
2100         g_return_if_fail (GL_IS_VIEW_OBJECT (view_object));
2101
2102         if (gl_view_is_selection_atomic (view)) {
2103
2104                 menu = gl_view_object_get_menu (view_object);
2105                 if (menu != NULL) {
2106                         gtk_menu_popup (GTK_MENU (menu),
2107                                         NULL, NULL, NULL, NULL,
2108                                         event->button.button,
2109                                         event->button.time);
2110                 }
2111
2112         } else {
2113
2114                 if (view->menu != NULL) {
2115                         gtk_menu_popup (GTK_MENU (view->menu),
2116                                         NULL, NULL, NULL, NULL,
2117                                         event->button.button,
2118                                         event->button.time);
2119                 }
2120
2121         }
2122
2123         gl_debug (DEBUG_VIEW, "END");
2124 }
2125
2126 /*---------------------------------------------------------------------------*/
2127 /* PRIVATE.  Handle "selection-clear" signal.                                */
2128 /*---------------------------------------------------------------------------*/
2129 static void
2130 selection_clear_cb (GtkWidget         *widget,
2131                     GdkEventSelection *event,
2132                     gpointer          data)
2133 {
2134         glView *view = GL_VIEW (data);
2135
2136         gl_debug (DEBUG_VIEW, "START");
2137
2138         g_return_if_fail (GL_IS_VIEW (view));
2139
2140         view->have_selection = FALSE;
2141         g_object_unref (view->selection_data);
2142         view->selection_data = NULL;
2143
2144         gl_debug (DEBUG_VIEW, "END");
2145 }
2146
2147 /*---------------------------------------------------------------------------*/
2148 /* PRIVATE.  Handle "selection-get" signal.                                  */
2149 /*---------------------------------------------------------------------------*/
2150 static void
2151 selection_get_cb (GtkWidget        *widget,
2152                   GtkSelectionData *selection_data,
2153                   guint            info,
2154                   guint            time,
2155                   gpointer         data)
2156 {
2157         glView *view = GL_VIEW (data);
2158         gchar *buffer;
2159         glXMLLabelStatus status;
2160
2161         gl_debug (DEBUG_VIEW, "START");
2162
2163         g_return_if_fail (GL_IS_VIEW (view));
2164
2165         if (view->have_selection) {
2166
2167                 buffer = gl_xml_label_save_buffer (view->selection_data,
2168                                                    &status);
2169                 gtk_selection_data_set (selection_data,
2170                                         GDK_SELECTION_TYPE_STRING, 8, buffer,
2171                                         strlen (buffer));
2172                 g_free (buffer);
2173         }
2174
2175         gl_debug (DEBUG_VIEW, "END");
2176 }
2177
2178 /*---------------------------------------------------------------------------*/
2179 /* PRIVATE.  Handle "selection-received" signal.  (Result of Paste)          */
2180 /*---------------------------------------------------------------------------*/
2181 static void
2182 selection_received_cb (GtkWidget        *widget,
2183                        GtkSelectionData *selection_data,
2184                        guint            time,
2185                        gpointer         data)
2186 {
2187         glView *view = GL_VIEW (data);
2188         glLabel *label = NULL;
2189         glXMLLabelStatus status;
2190         GList *p, *p_next;
2191         glLabelObject *object, *newobject;
2192         glViewObject *view_object;
2193
2194         gl_debug (DEBUG_VIEW, "START");
2195
2196         g_return_if_fail (GL_IS_VIEW (view));
2197
2198         if (selection_data->length < 0) {
2199                 return;
2200         }
2201         if (selection_data->type != GDK_SELECTION_TYPE_STRING) {
2202                 return;
2203         }
2204
2205         gl_view_unselect_all (view);
2206
2207         label = gl_xml_label_open_buffer (selection_data->data, &status);
2208         for (p = label->objects; p != NULL; p = p_next) {
2209                 p_next = p->next;
2210
2211                 object = (glLabelObject *) p->data;
2212                 gl_label_object_set_parent (object, view->label);
2213
2214                 gl_debug (DEBUG_VIEW, "object pasted");
2215
2216                 if (GL_IS_LABEL_BOX (object)) {
2217                         view_object = gl_view_box_new (GL_LABEL_BOX(object),
2218                                                        view);
2219                 } else if (GL_IS_LABEL_ELLIPSE (object)) {
2220                         view_object = gl_view_ellipse_new (GL_LABEL_ELLIPSE(object),
2221                                                            view);
2222                 } else if (GL_IS_LABEL_LINE (object)) {
2223                         view_object = gl_view_line_new (GL_LABEL_LINE(object),
2224                                                         view);
2225                 } else if (GL_IS_LABEL_IMAGE (object)) {
2226                         view_object = gl_view_image_new (GL_LABEL_IMAGE(object),
2227                                                          view);
2228                 } else if (GL_IS_LABEL_TEXT (object)) {
2229                         view_object = gl_view_text_new (GL_LABEL_TEXT(object),
2230                                                         view);
2231                 } else if (GL_IS_LABEL_BARCODE (object)) {
2232                         view_object = gl_view_barcode_new (GL_LABEL_BARCODE(object),
2233                                                            view);
2234                 } else {
2235                         /* Should not happen! */
2236                         view_object = NULL;
2237                         g_warning ("Invalid label object type.");
2238                 }
2239                 gl_view_select_object (view, view_object);
2240         }
2241         g_object_unref (label);
2242
2243         gl_debug (DEBUG_VIEW, "END");
2244 }
2245