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