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