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