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