]> git.sur5r.net Git - glabels/blob - glabels2/src/view.c
2007-09-14 Jim Evins <evins@snaught.com>
[glabels] / glabels2 / src / view.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
2
3 /*
4  *  (GLABELS) Label and Business Card Creation program for GNOME
5  *
6  *  view.c:  GLabels View module
7  *
8  *  Copyright (C) 2001-2007  Jim Evins <evins@snaught.com>.
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
23  */
24
25 #include <config.h>
26
27 #include "view.h"
28
29 #include <glib/gi18n.h>
30 #include <gtk/gtkscrolledwindow.h>
31 #include <gtk/gtklayout.h>
32 #include <gtk/gtkselection.h>
33 #include <gtk/gtkinvisible.h>
34 #include <gdk/gdkkeysyms.h>
35 #include <string.h>
36 #include <math.h>
37
38 #include "label.h"
39 #include "cairo-label-path.h"
40 #include "cairo-markup-path.h"
41 #include "view-object.h"
42 #include "view-box.h"
43 #include "view-ellipse.h"
44 #include "view-line.h"
45 #include "view-image.h"
46 #include "view-text.h"
47 #include "view-barcode.h"
48 #include "xml-label.h"
49 #include "color.h"
50 #include "prefs.h"
51 #include "marshal.h"
52
53 #include "debug.h"
54
55 /*==========================================================================*/
56 /* Private macros and constants.                                            */
57 /*==========================================================================*/
58
59 #define BG_COLOR        GL_COLOR (192, 192, 192)
60
61 #define PAPER_RGB_ARGS          1.0,   1.0,   1.0
62 #define GRID_RGB_ARGS           0.753, 0.753, 0.753
63 #define MARKUP_RGB_ARGS         0.94,  0.39,  0.39
64 #define OUTLINE_RGB_ARGS        0.68,  0.85,  0.90
65 #define SELECT_LINE_RGBA_ARGS   0.0,   0.0,   1.0,   0.5
66 #define SELECT_FILL_RGBA_ARGS   0.75,  0.75,  1.0,   0.5
67
68 #define GRID_LINE_WIDTH_PIXELS    1.0
69 #define MARKUP_LINE_WIDTH_PIXELS  1.0
70 #define OUTLINE_WIDTH_PIXELS      3.0
71 #define SELECT_LINE_WIDTH_PIXELS  3.0
72
73 #define ZOOMTOFIT_PAD   16
74
75 #define POINTS_PER_MM    2.83464566929
76
77 /*==========================================================================*/
78 /* Private types.                                                           */
79 /*==========================================================================*/
80
81 enum {
82         SELECTION_CHANGED,
83         CONTEXT_MENU_ACTIVATE,
84         ZOOM_CHANGED,
85         POINTER_MOVED,
86         POINTER_EXIT,
87         MODE_CHANGED,
88         LAST_SIGNAL
89 };
90
91
92 /*==========================================================================*/
93 /* Private globals                                                          */
94 /*==========================================================================*/
95
96 static guint signals[LAST_SIGNAL] = {0};
97
98 /* "CLIPBOARD" selection */
99 static GdkAtom clipboard_atom = GDK_NONE;
100
101 static gdouble zooms[] = {
102         8.00,
103         6.00,
104         4.00,
105         3.00,
106         2.00,
107         1.50,
108         1.00,
109         0.75,
110         0.67,
111         0.50,
112         0.33,
113         0.25,
114         0.20,
115         0.15,
116         0.10,
117 };
118 #define N_ZOOMS G_N_ELEMENTS(zooms)
119
120
121 /*==========================================================================*/
122 /* Local function prototypes                                                */
123 /*==========================================================================*/
124
125 static void       gl_view_finalize                (GObject        *object);
126
127 static void       gl_view_construct               (glView         *view,
128                                                    glLabel        *label);
129
130 static gdouble    get_home_scale                  (glView         *view);
131
132 static gboolean   expose_cb                       (glView         *view,
133                                                    GdkEventExpose *event);
134
135 static void       realize_cb                      (glView         *view);
136
137 static void       size_allocate_cb                (glView         *view,
138                                                    GtkAllocation  *allocation);
139
140 static void       screen_changed_cb               (glView         *view);
141
142 static void       label_changed_cb                (glView         *view);
143
144 static void       label_resized_cb                (glView         *view);
145
146 static void       label_object_added_cb           (glView         *view,
147                                                    glLabelObject  *object);
148
149 static void       draw_layers                     (glView         *view,
150                                                    cairo_t        *cr);
151
152 static void       draw_bg_layer                   (glView         *view,
153                                                    cairo_t        *cr);
154 static void       draw_grid_layer                 (glView         *view,
155                                                    cairo_t        *cr);
156 static void       draw_markup_layer               (glView         *view,
157                                                    cairo_t        *cr);
158 static void       draw_objects_layer              (glView         *view,
159                                                    cairo_t        *cr);
160 static void       draw_fg_layer                   (glView         *view,
161                                                    cairo_t        *cr);
162 static void       draw_highlight_layer            (glView         *view,
163                                                    cairo_t        *cr);
164 static void       draw_select_region_layer        (glView         *view,
165                                                    cairo_t        *cr);
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 glViewObject *view_view_object_at          (glView         *view,
173                                                    cairo_t        *cr,
174                                                    gdouble         x,
175                                                    gdouble         y);
176
177 static void       set_zoom_real                   (glView         *view,
178                                                    gdouble         zoom,
179                                                    gboolean        scale_to_fit_flag);
180
181 static void       selection_clear_cb              (GtkWidget         *widget,
182                                                    GdkEventSelection *event,
183                                                    glView            *view);
184
185 static void       selection_get_cb                (GtkWidget         *widget,
186                                                    GtkSelectionData  *selection_data,
187                                                    guint              info,
188                                                    guint              time,
189                                                    glView            *view);
190
191 static void       selection_received_cb           (GtkWidget         *widget,
192                                                    GtkSelectionData  *selection_data,
193                                                    guint              time,
194                                                    glView            *view);
195
196 static gboolean   focus_in_event_cb               (glView            *view,
197                                                    GdkEventFocus     *event);
198
199 static gboolean   focus_out_event_cb              (glView            *view,
200                                                    GdkEventFocus     *event);
201
202 static gboolean   enter_notify_event_cb           (glView            *view,
203                                                    GdkEventCrossing  *event);
204
205 static gboolean   leave_notify_event_cb           (glView            *view,
206                                                    GdkEventCrossing  *event);
207
208 static gboolean   motion_notify_event_cb          (glView            *view,
209                                                    GdkEventMotion    *event);
210
211 static gboolean   button_press_event_cb           (glView            *view,
212                                                    GdkEventButton    *event);
213
214 static gboolean   button_release_event_cb         (glView            *view,
215                                                    GdkEventButton    *event);
216
217 static gboolean   key_press_event_cb              (glView            *view,
218                                                    GdkEventKey       *event);
219
220 \f
221 /****************************************************************************/
222 /* Boilerplate Object stuff.                                                */
223 /****************************************************************************/
224 G_DEFINE_TYPE (glView, gl_view, GTK_TYPE_VBOX);
225
226 static void
227 gl_view_class_init (glViewClass *class)
228 {
229         GObjectClass *object_class = G_OBJECT_CLASS (class);
230
231         gl_debug (DEBUG_VIEW, "START");
232
233         gl_view_parent_class = g_type_class_peek_parent (class);
234
235         object_class->finalize = gl_view_finalize;
236
237         signals[SELECTION_CHANGED] =
238                 g_signal_new ("selection_changed",
239                               G_OBJECT_CLASS_TYPE (object_class),
240                               G_SIGNAL_RUN_LAST,
241                               G_STRUCT_OFFSET (glViewClass, selection_changed),
242                               NULL, NULL,
243                               gl_marshal_VOID__VOID,
244                               G_TYPE_NONE,
245                               0);
246
247         signals[CONTEXT_MENU_ACTIVATE] =
248                 g_signal_new ("context_menu_activate",
249                               G_OBJECT_CLASS_TYPE (object_class),
250                               G_SIGNAL_RUN_LAST,
251                               G_STRUCT_OFFSET (glViewClass, context_menu_activate),
252                               NULL, NULL,
253                               gl_marshal_VOID__INT_UINT,
254                               G_TYPE_NONE,
255                               2, G_TYPE_INT, G_TYPE_UINT);
256
257         signals[ZOOM_CHANGED] =
258                 g_signal_new ("zoom_changed",
259                               G_OBJECT_CLASS_TYPE (object_class),
260                               G_SIGNAL_RUN_LAST,
261                               G_STRUCT_OFFSET (glViewClass, zoom_changed),
262                               NULL, NULL,
263                               gl_marshal_VOID__DOUBLE,
264                               G_TYPE_NONE,
265                               1, G_TYPE_DOUBLE);
266
267         signals[POINTER_MOVED] =
268                 g_signal_new ("pointer_moved",
269                               G_OBJECT_CLASS_TYPE (object_class),
270                               G_SIGNAL_RUN_LAST,
271                               G_STRUCT_OFFSET (glViewClass, pointer_moved),
272                               NULL, NULL,
273                               gl_marshal_VOID__DOUBLE_DOUBLE,
274                               G_TYPE_NONE,
275                               2, G_TYPE_DOUBLE, G_TYPE_DOUBLE);
276
277         signals[POINTER_EXIT] =
278                 g_signal_new ("pointer_exit",
279                               G_OBJECT_CLASS_TYPE (object_class),
280                               G_SIGNAL_RUN_LAST,
281                               G_STRUCT_OFFSET (glViewClass, pointer_exit),
282                               NULL, NULL,
283                               gl_marshal_VOID__VOID,
284                               G_TYPE_NONE,
285                               0);
286
287         signals[MODE_CHANGED] =
288                 g_signal_new ("mode_changed",
289                               G_OBJECT_CLASS_TYPE (object_class),
290                               G_SIGNAL_RUN_LAST,
291                               G_STRUCT_OFFSET (glViewClass, mode_changed),
292                               NULL, NULL,
293                               gl_marshal_VOID__VOID,
294                               G_TYPE_NONE,
295                               0);
296
297         gl_debug (DEBUG_VIEW, "END");
298 }
299
300 static void
301 gl_view_init (glView *view)
302 {
303         GtkWidget *wscroll;
304         GdkColor  *bg_color;
305
306         gl_debug (DEBUG_VIEW, "START");
307
308         view->label                = NULL;
309         view->grid_visible         = TRUE;
310         view->grid_spacing         = 9;
311         view->markup_visible       = TRUE;
312         view->default_font_family  = NULL;
313         view->mode                 = GL_VIEW_MODE_ARROW;
314         view->object_list          = NULL;
315         view->selected_object_list = NULL;
316         view->zoom                 = 1.0;
317         view->home_scale           = get_home_scale (view);
318
319         /*
320          * Canvas
321          */
322         view->canvas = gtk_layout_new (NULL, NULL);
323         wscroll = gtk_scrolled_window_new (NULL, NULL);
324         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (wscroll),
325                                         GTK_POLICY_AUTOMATIC,
326                                         GTK_POLICY_AUTOMATIC);
327         gtk_box_pack_start (GTK_BOX (view), wscroll, TRUE, TRUE, 0);
328         gtk_container_add (GTK_CONTAINER (wscroll), view->canvas);
329
330         bg_color = gl_color_to_gdk_color (BG_COLOR);
331         gtk_widget_modify_bg (GTK_WIDGET (view->canvas), GTK_STATE_NORMAL, bg_color);
332         g_free (bg_color);
333
334         GTK_WIDGET_SET_FLAGS (GTK_WIDGET (view->canvas), GTK_CAN_FOCUS);
335
336         gtk_widget_add_events (GTK_WIDGET (view->canvas),
337                                (GDK_FOCUS_CHANGE_MASK   |
338                                 GDK_ENTER_NOTIFY_MASK   |
339                                 GDK_LEAVE_NOTIFY_MASK   |
340                                 GDK_POINTER_MOTION_MASK |
341                                 GDK_BUTTON_PRESS_MASK   |
342                                 GDK_BUTTON_RELEASE_MASK |
343                                 GDK_KEY_PRESS_MASK));
344
345         g_signal_connect_swapped (G_OBJECT (view->canvas), "expose-event",
346                                   G_CALLBACK (expose_cb), view);
347         g_signal_connect_swapped (G_OBJECT (view->canvas), "realize",
348                                   G_CALLBACK (realize_cb), view);
349         g_signal_connect_swapped (G_OBJECT (view->canvas), "size-allocate",
350                                   G_CALLBACK (size_allocate_cb), view);
351         g_signal_connect_swapped (G_OBJECT (view->canvas), "screen-changed",
352                                   G_CALLBACK (screen_changed_cb), view);
353         g_signal_connect_swapped (G_OBJECT (view->canvas), "focus-in-event",
354                                   G_CALLBACK (focus_in_event_cb), view);
355         g_signal_connect_swapped (G_OBJECT (view->canvas), "focus-out-event",
356                                   G_CALLBACK (focus_out_event_cb), view);
357         g_signal_connect_swapped (G_OBJECT (view->canvas), "enter-notify-event",
358                                   G_CALLBACK (enter_notify_event_cb), view);
359         g_signal_connect_swapped (G_OBJECT (view->canvas), "leave-notify-event",
360                                   G_CALLBACK (leave_notify_event_cb), view);
361         g_signal_connect_swapped (G_OBJECT (view->canvas), "motion-notify-event",
362                                   G_CALLBACK (motion_notify_event_cb), view);
363         g_signal_connect_swapped (G_OBJECT (view->canvas), "button-press-event",
364                                   G_CALLBACK (button_press_event_cb), view);
365         g_signal_connect_swapped (G_OBJECT (view->canvas), "button-release-event",
366                                   G_CALLBACK (button_release_event_cb), view);
367         g_signal_connect_swapped (G_OBJECT (view->canvas), "key-press-event",
368                                   G_CALLBACK (key_press_event_cb), view);
369
370         /*
371          * Clipboard
372          */
373         view->have_selection       = FALSE;
374         view->selection_data       = NULL;
375         view->invisible            = gtk_invisible_new ();
376         if (!clipboard_atom) {
377                 clipboard_atom = gdk_atom_intern ("GLABELS_CLIPBOARD", FALSE);
378         }
379         gtk_selection_add_target (view->invisible,
380                                   clipboard_atom, GDK_SELECTION_TYPE_STRING, 1);
381         g_signal_connect (G_OBJECT (view->invisible),
382                           "selection_clear_event",
383                           G_CALLBACK (selection_clear_cb), view);
384         g_signal_connect (G_OBJECT (view->invisible), "selection_get",
385                           G_CALLBACK (selection_get_cb), view);
386         g_signal_connect (G_OBJECT (view->invisible),
387                           "selection_received",
388                           G_CALLBACK (selection_received_cb), view);
389
390         /*
391          * Defaults from preferences
392          */
393         gl_view_set_default_font_family       (view, gl_prefs->default_font_family);
394         gl_view_set_default_font_size         (view, gl_prefs->default_font_size);
395         gl_view_set_default_font_weight       (view, gl_prefs->default_font_weight);
396         gl_view_set_default_font_italic_flag  (view, gl_prefs->default_font_italic_flag);
397         gl_view_set_default_text_color        (view, gl_prefs->default_text_color);
398         gl_view_set_default_text_alignment    (view, gl_prefs->default_text_alignment);
399         gl_view_set_default_text_line_spacing (view, gl_prefs->default_text_line_spacing);
400         gl_view_set_default_line_width        (view, gl_prefs->default_line_width);
401         gl_view_set_default_line_color        (view, gl_prefs->default_line_color);
402         gl_view_set_default_fill_color        (view, gl_prefs->default_fill_color);
403
404         gl_debug (DEBUG_VIEW, "END");
405 }
406
407 static void
408 gl_view_finalize (GObject *object)
409 {
410         glView *view = GL_VIEW (object);
411
412         gl_debug (DEBUG_VIEW, "START");
413
414         g_return_if_fail (object != NULL);
415         g_return_if_fail (GL_IS_VIEW (object));
416
417         if (view->default_font_family) {
418                 g_free (view->default_font_family);
419         }
420
421         G_OBJECT_CLASS (gl_view_parent_class)->finalize (object);
422
423         gl_debug (DEBUG_VIEW, "END");
424 }
425
426 /****************************************************************************/
427 /* NEW view object.                                                         */
428 /****************************************************************************/
429 GtkWidget *
430 gl_view_new (glLabel *label)
431 {
432         glView *view;
433
434         gl_debug (DEBUG_VIEW, "START");
435
436         g_return_val_if_fail (label && GL_IS_LABEL (label), NULL);
437
438         view = g_object_new (GL_TYPE_VIEW, NULL);
439
440         gl_view_construct (view, label);
441
442         gl_debug (DEBUG_VIEW, "END");
443
444         return GTK_WIDGET (view);
445 }
446
447 /*---------------------------------------------------------------------------*/
448 /* PRIVATE.  Construct composite widget.                                     */
449 /*---------------------------------------------------------------------------*/
450 static void
451 gl_view_construct (glView  *view,
452                    glLabel *label)
453 {
454         GList            *p_obj;
455         glLabelObject    *object;
456
457         gl_debug (DEBUG_VIEW, "START");
458
459         g_return_if_fail (GL_IS_VIEW (view));
460
461         view->label = label;
462
463         for (p_obj = label->objects; p_obj != NULL; p_obj = p_obj->next)
464         {
465                 object = GL_LABEL_OBJECT (p_obj->data);
466
467                 if (GL_IS_LABEL_BOX (object)) {
468                         gl_view_box_new (GL_LABEL_BOX(object), view);
469                 } else if (GL_IS_LABEL_ELLIPSE (object)) {
470                         gl_view_ellipse_new (GL_LABEL_ELLIPSE(object), view);
471                 } else if (GL_IS_LABEL_LINE (object)) {
472                         gl_view_line_new (GL_LABEL_LINE(object), view);
473                 } else if (GL_IS_LABEL_IMAGE (object)) {
474                         gl_view_image_new (GL_LABEL_IMAGE(object), view);
475                 } else if (GL_IS_LABEL_TEXT (object)) {
476                         gl_view_text_new (GL_LABEL_TEXT(object), view);
477                 } else if (GL_IS_LABEL_BARCODE (object)) {
478                         gl_view_barcode_new (GL_LABEL_BARCODE(object), view);
479                 } else {
480                         /* Should not happen! */
481                         g_message ("Invalid label object type.");
482                 }
483         }
484
485         g_signal_connect_swapped (G_OBJECT (view->label), "changed",
486                                   G_CALLBACK (label_changed_cb), view);
487         g_signal_connect_swapped (G_OBJECT (view->label), "size_changed",
488                                   G_CALLBACK (label_resized_cb), view);
489         g_signal_connect_swapped (G_OBJECT (view->label), "object_added",
490                                   G_CALLBACK (label_object_added_cb), view);
491
492         gl_debug (DEBUG_VIEW, "END");
493 }
494
495 /*---------------------------------------------------------------------------*/
496 /* PRIAVTE.  Calculate 1:1 scale for screen.                                 */
497 /*---------------------------------------------------------------------------*/
498 static gdouble
499 get_home_scale (glView *view)
500 {
501         GdkScreen *screen;
502         gdouble    screen_width_pixels;
503         gdouble    screen_width_mm;
504         gdouble    screen_height_pixels;
505         gdouble    screen_height_mm;
506         gdouble    x_pixels_per_mm;
507         gdouble    y_pixels_per_mm;
508         gdouble    scale;
509
510         if (view->canvas == NULL) return 1.0;
511
512         if (!gtk_widget_has_screen (GTK_WIDGET (view->canvas))) return 1.0;
513
514         screen = gtk_widget_get_screen (GTK_WIDGET (view->canvas));
515
516         gl_debug (DEBUG_VIEW, "Screen = %p", screen);
517
518         screen_width_pixels  = gdk_screen_get_width (screen);
519         screen_width_mm      = gdk_screen_get_width_mm (screen);
520         screen_height_pixels = gdk_screen_get_height (screen);
521         screen_height_mm     = gdk_screen_get_height_mm (screen);
522
523         x_pixels_per_mm      = screen_width_pixels / screen_width_mm;
524         y_pixels_per_mm      = screen_height_pixels / screen_height_mm;
525
526         gl_debug (DEBUG_VIEW, "Horizontal dot pitch: %g pixels/mm (%g dpi)",
527                   x_pixels_per_mm, x_pixels_per_mm * 25.4);
528         gl_debug (DEBUG_VIEW, "Vertical dot pitch: %g pixels/mm (%g dpi)",
529                   y_pixels_per_mm, y_pixels_per_mm * 25.4);
530
531         scale = (x_pixels_per_mm + y_pixels_per_mm) / 2.0;
532
533         gl_debug (DEBUG_VIEW, "Average dot pitch: %g pixels/mm (%g dpi)",
534                   scale, scale * 25.4);
535
536         scale /= POINTS_PER_MM;
537
538         gl_debug (DEBUG_VIEW, "Scale = %g pixels/point", scale);
539
540         /* Make sure scale is somewhat sane. */
541         if ( (scale < 0.25) || (scale > 4.0) ) return 1.0;
542
543         return scale;
544 }
545
546 /*---------------------------------------------------------------------------*/
547 /* Schedule canvas update.                                                   */
548 /*---------------------------------------------------------------------------*/
549 void
550 gl_view_update (glView  *view)
551 {
552         GtkWidget *widget;
553         GdkRegion *region;
554         
555         gl_debug (DEBUG_VIEW, "START");
556
557         widget = GTK_WIDGET (view->canvas);
558
559         if (!widget->window) return;
560
561         if ( !view->update_scheduled_flag )
562         {
563                 view->update_scheduled_flag = TRUE;
564
565                 region = gdk_drawable_get_clip_region (widget->window);
566                 /* redraw the cairo canvas completely by exposing it */
567                 gdk_window_invalidate_region (widget->window, region, TRUE);
568                 gdk_region_destroy (region);
569         }
570
571         gl_debug (DEBUG_VIEW, "END");
572 }
573
574 /*---------------------------------------------------------------------------*/
575 /* Schedule canvas region update.                                            */
576 /*---------------------------------------------------------------------------*/
577 void
578 gl_view_update_region (glView        *view,
579                        cairo_t       *cr,
580                        glLabelRegion *region)
581 {
582         GtkWidget    *widget;
583         GdkRectangle  rect;
584         gdouble       x, y, w, h;
585
586         gl_debug (DEBUG_VIEW, "START");
587
588         widget = GTK_WIDGET (view->canvas);
589
590         if (!widget->window) return;
591
592         x = MIN (region->x1, region->x2);
593         y = MIN (region->y1, region->y2);
594         w = fabs (region->x2 - region->x1);
595         h = fabs (region->y2 - region->y1);
596
597         cairo_user_to_device (cr, &x, &y);
598         cairo_user_to_device_distance (cr, &w, &h);
599
600         rect.x      = x - 3;
601         rect.y      = y - 3;
602         rect.width  = w + 6;
603         rect.height = h + 6;
604
605         gdk_window_invalidate_rect (widget->window, &rect, TRUE);
606
607         gl_debug (DEBUG_VIEW, "END");
608 }
609
610 /*---------------------------------------------------------------------------*/
611 /* PRIVATE.  Expose handler.                                                 */
612 /*---------------------------------------------------------------------------*/
613 static gboolean
614 expose_cb (glView         *view,
615            GdkEventExpose *event)
616 {
617         cairo_t *cr;
618
619         gl_debug (DEBUG_VIEW, "START");
620
621         view->update_scheduled_flag = FALSE;
622
623         /* get a cairo_t */
624         cr = gdk_cairo_create (GTK_LAYOUT (view->canvas)->bin_window);
625
626         cairo_rectangle (cr,
627                         event->area.x, event->area.y,
628                         event->area.width, event->area.height);
629         cairo_clip (cr);
630         
631         draw_layers (view, cr);
632
633         cairo_destroy (cr);
634
635         gl_debug (DEBUG_VIEW, "END");
636
637         return FALSE;
638 }
639
640 /*---------------------------------------------------------------------------*/
641 /* PRIVATE.  Realize handler.                                                */
642 /*---------------------------------------------------------------------------*/
643 static void
644 realize_cb (glView  *view)
645 {
646         g_return_if_fail (view && GL_IS_VIEW (view));
647
648         gl_debug (DEBUG_VIEW, "START");
649
650         gl_debug (DEBUG_VIEW, "END");
651 }
652
653 /*---------------------------------------------------------------------------*/
654 /* PRIVATE. Size allocation changed callback.                                */
655 /*---------------------------------------------------------------------------*/
656 static void
657 size_allocate_cb (glView         *view,
658                   GtkAllocation  *allocation)
659 {
660         gl_debug (DEBUG_VIEW, "START");
661
662         GTK_LAYOUT (view->canvas)->hadjustment->page_size = allocation->width;
663         GTK_LAYOUT (view->canvas)->hadjustment->page_increment = allocation->width / 2;
664  
665         GTK_LAYOUT (view->canvas)->vadjustment->page_size = allocation->height;
666         GTK_LAYOUT (view->canvas)->vadjustment->page_increment = allocation->height / 2;
667
668         g_signal_emit_by_name (GTK_LAYOUT (view->canvas)->hadjustment, "changed");
669         g_signal_emit_by_name (GTK_LAYOUT (view->canvas)->vadjustment, "changed");
670
671         if (view->zoom_to_fit_flag) {
672                 /* Maintain best fit zoom */
673                 gl_view_zoom_to_fit (view);
674         }
675
676         gl_debug (DEBUG_VIEW, "END");
677 }
678
679
680
681 /*---------------------------------------------------------------------------*/
682 /* PRIVATE. Screen changed callback.                                         */
683 /*---------------------------------------------------------------------------*/
684 static void
685 screen_changed_cb (glView *view)
686 {
687         gl_debug (DEBUG_VIEW, "START");
688
689         if (gtk_widget_has_screen (GTK_WIDGET (view->canvas))) {
690
691                 view->home_scale = get_home_scale (view);
692
693                 if (view->zoom_to_fit_flag) {
694                         /* Maintain best fit zoom */
695                         gl_view_zoom_to_fit (view);
696                 }
697         }
698
699         gl_debug (DEBUG_VIEW, "END");
700 }
701
702 /*---------------------------------------------------------------------------*/
703 /* PRIVATE.  Handle label changed event.                                     */
704 /*---------------------------------------------------------------------------*/
705 static void
706 label_changed_cb (glView  *view)
707 {
708         g_return_if_fail (view && GL_IS_VIEW (view));
709
710         gl_debug (DEBUG_VIEW, "START");
711
712         gl_view_update (view);
713
714         gl_debug (DEBUG_VIEW, "END");
715 }
716
717
718 /*---------------------------------------------------------------------------*/
719 /* PRIVATE.  Handle label resize event.                                      */
720 /*---------------------------------------------------------------------------*/
721 static void
722 label_resized_cb (glView  *view)
723 {
724         g_return_if_fail (view && GL_IS_VIEW (view));
725
726         gl_debug (DEBUG_VIEW, "START");
727
728         g_signal_emit_by_name (GTK_LAYOUT (view->canvas)->hadjustment, "changed");
729         g_signal_emit_by_name (GTK_LAYOUT (view->canvas)->vadjustment, "changed");
730
731         gl_view_update (view);
732
733         gl_debug (DEBUG_VIEW, "END");
734 }
735
736
737 /*---------------------------------------------------------------------------*/
738 /* PRIVATE.  Handle new label object.                                        */
739 /*---------------------------------------------------------------------------*/
740 static void
741 label_object_added_cb (glView         *view,
742                        glLabelObject  *object)
743 {
744         glViewObject *view_object;
745
746         g_return_if_fail (view && GL_IS_VIEW (view));
747         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
748
749         if (GL_IS_LABEL_BOX (object)) {
750                 view_object = gl_view_box_new (GL_LABEL_BOX(object), view);
751         } else if (GL_IS_LABEL_ELLIPSE (object)) {
752                 view_object = gl_view_ellipse_new (GL_LABEL_ELLIPSE(object), view);
753         } else if (GL_IS_LABEL_LINE (object)) {
754                 view_object = gl_view_line_new (GL_LABEL_LINE(object), view);
755         } else if (GL_IS_LABEL_IMAGE (object)) {
756                 view_object = gl_view_image_new (GL_LABEL_IMAGE(object), view);
757         } else if (GL_IS_LABEL_TEXT (object)) {
758                 view_object = gl_view_text_new (GL_LABEL_TEXT(object), view);
759         } else if (GL_IS_LABEL_BARCODE (object)) {
760                 view_object = gl_view_barcode_new (GL_LABEL_BARCODE(object), view);
761         } else {
762                 /* Should not happen! */
763                 view_object = NULL;
764                 g_message ("Invalid label object type.");
765         }
766
767         gl_view_select_object (view, view_object);
768 }
769
770 /*---------------------------------------------------------------------------*/
771 /* PRIVATE.  Create, draw and order layers.                                  */
772 /*---------------------------------------------------------------------------*/
773 static void
774 draw_layers (glView  *view,
775              cairo_t *cr)
776 {
777         gdouble                    scale;
778         gdouble                    w, h;
779         gint                       canvas_w, canvas_h;
780
781         g_return_if_fail (view && GL_IS_VIEW (view));
782         g_return_if_fail (view->label && GL_IS_LABEL (view->label));
783
784         gl_debug (DEBUG_VIEW, "START");
785
786         scale = view->zoom * view->home_scale;
787
788         gl_label_get_size (view->label, &w, &h);
789
790         scale = view->home_scale * view->zoom;
791         gtk_layout_set_size (GTK_LAYOUT (view->canvas), w*scale+8, h*scale+8);
792
793         gdk_drawable_get_size (GTK_LAYOUT (view->canvas)->bin_window, &canvas_w, &canvas_h);
794
795         view->x0 = (canvas_w/scale - w) / 2.0;
796         view->y0 = (canvas_h/scale - h) / 2.0;
797         view->w  = w;
798         view->h  = h;
799
800         cairo_save (cr);
801
802         cairo_scale (cr, scale, scale);
803         cairo_translate (cr, view->x0, view->y0);
804
805         draw_bg_layer (view, cr);
806         draw_grid_layer (view, cr);
807         draw_markup_layer (view, cr);
808         draw_objects_layer (view, cr);
809         draw_fg_layer (view, cr);
810         draw_highlight_layer (view, cr);
811         draw_select_region_layer (view, cr);
812
813         cairo_restore (cr);
814
815         gl_debug (DEBUG_VIEW, "END");
816
817 }
818
819 /*---------------------------------------------------------------------------*/
820 /* PRIVATE.  Draw background                                                 */
821 /*---------------------------------------------------------------------------*/
822 static void
823 draw_bg_layer (glView  *view,
824                cairo_t *cr)
825 {
826         g_return_if_fail (view && GL_IS_VIEW (view));
827         g_return_if_fail (view->label && GL_IS_LABEL (view->label));
828
829         gl_cairo_label_path (cr, view->label->template, view->label->rotate_flag, FALSE);
830
831         cairo_set_source_rgb (cr, PAPER_RGB_ARGS);
832         cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
833         cairo_fill (cr);
834 }
835
836 /*---------------------------------------------------------------------------*/
837 /* PRIVATE.  Draw grid lines.                                                */
838 /*---------------------------------------------------------------------------*/
839 static void
840 draw_grid_layer (glView  *view,
841                  cairo_t *cr)
842 {
843         gdouble                    w, h;
844         gdouble                    x, y;
845         gdouble                    x0, y0;
846         const glTemplateLabelType *label_type;
847
848         gl_debug (DEBUG_VIEW, "START");
849
850         g_return_if_fail (view && GL_IS_VIEW (view));
851         g_return_if_fail (view->label && GL_IS_LABEL(view->label));
852
853         if (view->grid_visible)
854         {
855
856                 label_type = gl_template_get_first_label_type (view->label->template);
857
858                 gl_label_get_size (view->label, &w, &h);
859         
860                 if (label_type->shape == GL_TEMPLATE_SHAPE_RECT) {
861                         x0 = 0.0;
862                         y0 = 0.0;
863                 } else {
864                         /* round labels, adjust grid to line up with center of label. */
865                         x0 = fmod (w/2.0, view->grid_spacing);
866                         y0 = fmod (h/2.0, view->grid_spacing);
867                 }
868
869
870                 cairo_save (cr);
871
872                 cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
873                 cairo_set_line_width (cr, GRID_LINE_WIDTH_PIXELS/(view->home_scale * view->zoom));
874                 cairo_set_source_rgb (cr, GRID_RGB_ARGS);
875
876                 for ( x=x0+view->grid_spacing; x < w; x += view->grid_spacing )
877                 {
878                         cairo_move_to (cr, x, 0);
879                         cairo_line_to (cr, x, h);
880                         cairo_stroke (cr);
881                 }
882
883                 for ( y=y0+view->grid_spacing; y < h; y += view->grid_spacing )
884                 {
885                         cairo_move_to (cr, 0, y);
886                         cairo_line_to (cr, w, y);
887                         cairo_stroke (cr);
888                 }
889
890                 cairo_restore (cr);
891
892         }
893
894         gl_debug (DEBUG_VIEW, "END");
895 }
896
897 /*---------------------------------------------------------------------------*/
898 /* PRIVATE.  Draw markup layer.                                              */
899 /*---------------------------------------------------------------------------*/
900 static void
901 draw_markup_layer (glView  *view,
902                    cairo_t *cr)
903 {
904         glLabel                   *label;
905         const glTemplateLabelType *label_type;
906         GList                     *p;
907         glTemplateMarkup          *markup;
908
909         g_return_if_fail (view && GL_IS_VIEW (view));
910         g_return_if_fail (view->label && GL_IS_LABEL (view->label));
911
912         if (view->markup_visible)
913         {
914
915                 label      = view->label;
916                 label_type = gl_template_get_first_label_type (label->template);
917
918                 cairo_save (cr);
919
920                 cairo_set_line_width (cr, MARKUP_LINE_WIDTH_PIXELS/(view->home_scale * view->zoom));
921                 cairo_set_source_rgb (cr, MARKUP_RGB_ARGS);
922
923                 for ( p=label_type->markups; p != NULL; p=p->next )
924                 {
925                         markup = (glTemplateMarkup *)p->data;
926
927                         gl_cairo_markup_path (cr, markup, label);
928
929                         cairo_stroke (cr);
930                 }
931
932                 cairo_restore (cr);
933         }
934
935 }
936
937 /*---------------------------------------------------------------------------*/
938 /* PRIVATE.  Draw objects layer.                                             */
939 /*---------------------------------------------------------------------------*/
940 static void
941 draw_objects_layer (glView  *view,
942                     cairo_t *cr)
943 {
944         gl_label_draw (view->label, cr, TRUE, NULL);
945 }
946
947 /*---------------------------------------------------------------------------*/
948 /* PRIVATE.  Draw foreground                                                 */
949 /*---------------------------------------------------------------------------*/
950 static void
951 draw_fg_layer (glView  *view,
952                cairo_t *cr)
953 {
954         g_return_if_fail (view && GL_IS_VIEW (view));
955         g_return_if_fail (view->label && GL_IS_LABEL (view->label));
956
957         gl_cairo_label_path (cr, view->label->template, view->label->rotate_flag, FALSE);
958
959         cairo_set_line_width (cr, OUTLINE_WIDTH_PIXELS/(view->home_scale * view->zoom));
960         cairo_set_source_rgb (cr, OUTLINE_RGB_ARGS);
961         cairo_stroke (cr);
962 }
963
964 /*---------------------------------------------------------------------------*/
965 /* PRIVATE.  Create highlight layer.                                         */
966 /*---------------------------------------------------------------------------*/
967 static void
968 draw_highlight_layer (glView  *view,
969                       cairo_t *cr)
970 {
971         GList            *p_obj;
972         glViewObject     *view_object;
973
974         g_return_if_fail (view && GL_IS_VIEW (view));
975
976         cairo_save (cr);
977
978         cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
979
980         for (p_obj = view->selected_object_list; p_obj != NULL; p_obj = p_obj->next)
981         {
982                 view_object = GL_VIEW_OBJECT (p_obj->data);
983
984                 gl_view_object_draw_handles (view_object, cr);
985         }
986
987         cairo_restore (cr);
988 }
989
990 /*---------------------------------------------------------------------------*/
991 /* PRIVATE.  Draw select region layer.                                       */
992 /*---------------------------------------------------------------------------*/
993 static void
994 draw_select_region_layer (glView  *view,
995                           cairo_t *cr)
996 {
997         gdouble x1, y1;
998         gdouble w, h;
999
1000         g_return_if_fail (view && GL_IS_VIEW (view));
1001
1002         if (view->select_region_visible)
1003         {
1004                 x1 = MIN (view->select_region.x1, view->select_region.x2);
1005                 y1 = MIN (view->select_region.y1, view->select_region.y2);
1006                 w  = fabs (view->select_region.x2 - view->select_region.x1);
1007                 h  = fabs (view->select_region.y2 - view->select_region.y1);
1008
1009                 cairo_save (cr);
1010
1011                 cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
1012
1013                 cairo_rectangle (cr, x1, y1, w, h);
1014
1015                 cairo_set_source_rgba (cr, SELECT_FILL_RGBA_ARGS);
1016                 cairo_fill_preserve (cr);
1017
1018                 cairo_set_line_width (cr, SELECT_LINE_WIDTH_PIXELS/(view->home_scale * view->zoom));
1019                 cairo_set_source_rgba (cr, SELECT_LINE_RGBA_ARGS);
1020                 cairo_stroke (cr);
1021
1022                 cairo_restore (cr);
1023         }
1024 }
1025
1026 /*****************************************************************************/
1027 /* Show grid.                                                                */
1028 /*****************************************************************************/
1029 void
1030 gl_view_show_grid (glView *view)
1031 {
1032         g_return_if_fail (view && GL_IS_VIEW (view));
1033
1034         view->grid_visible = TRUE;
1035         gl_view_update (view);
1036 }
1037
1038 /*****************************************************************************/
1039 /* Hide grid.                                                                */
1040 /*****************************************************************************/
1041 void
1042 gl_view_hide_grid (glView *view)
1043 {
1044         g_return_if_fail (view && GL_IS_VIEW (view));
1045
1046         view->grid_visible = FALSE;
1047         gl_view_update (view);
1048 }
1049
1050 /*****************************************************************************/
1051 /* Set grid spacing.                                                         */
1052 /*****************************************************************************/
1053 void
1054 gl_view_set_grid_spacing (glView  *view,
1055                           gdouble  spacing)
1056 {
1057         g_return_if_fail (view && GL_IS_VIEW (view));
1058
1059         view->grid_spacing = spacing;
1060         gl_view_update (view);
1061 }
1062
1063 /*****************************************************************************/
1064 /* Show markup.                                                              */
1065 /*****************************************************************************/
1066 void
1067 gl_view_show_markup (glView *view)
1068 {
1069         g_return_if_fail (view && GL_IS_VIEW (view));
1070
1071         view->markup_visible = TRUE;
1072         gl_view_update (view);
1073 }
1074
1075 /*****************************************************************************/
1076 /* Hide markup.                                                              */
1077 /*****************************************************************************/
1078 void
1079 gl_view_hide_markup (glView *view)
1080 {
1081         g_return_if_fail (view && GL_IS_VIEW (view));
1082
1083         view->markup_visible = FALSE;
1084         gl_view_update (view);
1085 }
1086
1087 /*****************************************************************************/
1088 /* Set arrow mode.                                                           */
1089 /*****************************************************************************/
1090 void
1091 gl_view_arrow_mode (glView *view)
1092 {
1093         GdkCursor *cursor;
1094
1095         gl_debug (DEBUG_VIEW, "START");
1096
1097         g_return_if_fail (view && GL_IS_VIEW (view));
1098
1099         cursor = gdk_cursor_new (GDK_LEFT_PTR);
1100         gdk_window_set_cursor (view->canvas->window, cursor);
1101         gdk_cursor_unref (cursor);
1102
1103         view->mode = GL_VIEW_MODE_ARROW;
1104         view->state = GL_VIEW_IDLE;
1105
1106         gl_debug (DEBUG_VIEW, "END");
1107 }
1108
1109 /*****************************************************************************/
1110 /* Set create text object mode.                                              */
1111 /*****************************************************************************/
1112 void
1113 gl_view_object_create_mode (glView            *view,
1114                             glLabelObjectType  type)
1115 {
1116         GdkCursor *cursor = NULL;
1117
1118         gl_debug (DEBUG_VIEW, "START");
1119
1120         g_return_if_fail (view && GL_IS_VIEW (view));
1121
1122         switch (type)
1123         {
1124         case GL_LABEL_OBJECT_BOX:
1125                 cursor = gl_view_box_get_create_cursor ();
1126                 break;
1127         case GL_LABEL_OBJECT_ELLIPSE:
1128                 cursor = gl_view_ellipse_get_create_cursor ();
1129                 break;
1130         case GL_LABEL_OBJECT_LINE:
1131                 cursor = gl_view_line_get_create_cursor ();
1132                 break;
1133         case GL_LABEL_OBJECT_IMAGE:
1134                 cursor = gl_view_image_get_create_cursor ();
1135                 break;
1136         case GL_LABEL_OBJECT_TEXT:
1137                 cursor = gl_view_text_get_create_cursor ();
1138                 break;
1139         case GL_LABEL_OBJECT_BARCODE:
1140                 cursor = gl_view_barcode_get_create_cursor ();
1141                 break;
1142         default:
1143                 g_message ("Invalid label object type.");/*Should not happen!*/
1144                 break;
1145         }
1146
1147         gdk_window_set_cursor (view->canvas->window, cursor);
1148         gdk_cursor_unref (cursor);
1149
1150         view->mode = GL_VIEW_MODE_OBJECT_CREATE;
1151         view->state = GL_VIEW_IDLE;
1152         view->create_type = type;
1153
1154         gl_debug (DEBUG_VIEW, "END");
1155 }
1156
1157 /*****************************************************************************/
1158 /* Select given object (adding to current selection).                        */
1159 /*****************************************************************************/
1160 void
1161 gl_view_select_object (glView       *view,
1162                        glViewObject *view_object)
1163 {
1164         gl_debug (DEBUG_VIEW, "START");
1165
1166         g_return_if_fail (view && GL_IS_VIEW (view));
1167
1168         select_object_real (view, view_object);
1169
1170         g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1171
1172         gl_debug (DEBUG_VIEW, "END");
1173 }
1174
1175 /*****************************************************************************/
1176 /* Unselect given object (removing from current selection).                  */
1177 /*****************************************************************************/
1178 void
1179 gl_view_unselect_object (glView       *view,
1180                          glViewObject *view_object)
1181 {
1182         gl_debug (DEBUG_VIEW, "START");
1183
1184         g_return_if_fail (view && GL_IS_VIEW (view));
1185
1186         unselect_object_real (view, view_object);
1187
1188         g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1189
1190         gl_debug (DEBUG_VIEW, "END");
1191 }
1192
1193 /*****************************************************************************/
1194 /* Select all items.                                                         */
1195 /*****************************************************************************/
1196 void
1197 gl_view_select_all (glView *view)
1198 {
1199         GList *p, *p_next;
1200
1201         gl_debug (DEBUG_VIEW, "START");
1202
1203         g_return_if_fail (view && GL_IS_VIEW (view));
1204
1205         /* 1st unselect anything already selected. */
1206         for (p = view->selected_object_list; p != NULL; p = p_next) {
1207                 p_next = p->next;
1208                 unselect_object_real (view, GL_VIEW_OBJECT (p->data));
1209         }
1210
1211         /* Finally select all objects. */
1212         for (p = view->object_list; p != NULL; p = p->next) {
1213                 select_object_real (view, GL_VIEW_OBJECT (p->data));
1214         }
1215
1216         g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1217
1218         gl_debug (DEBUG_VIEW, "END");
1219 }
1220
1221 /*****************************************************************************/
1222 /* Remove all selections                                                     */
1223 /*****************************************************************************/
1224 void
1225 gl_view_unselect_all (glView *view)
1226 {
1227         GList *p;
1228         GList *p_next;
1229
1230         gl_debug (DEBUG_VIEW, "START");
1231
1232         g_return_if_fail (view && GL_IS_VIEW (view));
1233
1234         for (p = view->selected_object_list; p != NULL; p = p_next) {
1235                 p_next = p->next;
1236                 unselect_object_real (view, GL_VIEW_OBJECT (p->data));
1237         }
1238
1239         g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1240
1241         gl_debug (DEBUG_VIEW, "END");
1242 }
1243
1244 /*****************************************************************************/
1245 /* Select all objects within given rectangular region (adding to selection). */
1246 /*****************************************************************************/
1247 void
1248 gl_view_select_region (glView        *view,
1249                        glLabelRegion *region)
1250 {
1251         GList         *p;
1252         glViewObject  *view_object;
1253         glLabelObject *object;
1254         gdouble        r_x1, r_y1;
1255         gdouble        r_x2, r_y2;
1256         glLabelRegion  obj_extent;
1257
1258         gl_debug (DEBUG_VIEW, "START");
1259
1260         g_return_if_fail (view && GL_IS_VIEW (view));
1261
1262         r_x1 = MIN (region->x1, region->x2);
1263         r_y1 = MIN (region->y1, region->y2);
1264         r_x2 = MAX (region->x1, region->x2);
1265         r_y2 = MAX (region->y1, region->y2);
1266
1267         for (p = view->object_list; p != NULL; p = p->next)
1268         {
1269                 view_object = GL_VIEW_OBJECT(p->data);
1270                 if (!gl_view_is_object_selected (view, view_object))
1271                 {
1272
1273                         object = gl_view_object_get_object (view_object);
1274
1275                         gl_label_object_get_extent (object, &obj_extent);
1276                         if ((obj_extent.x1 >= r_x1) &&
1277                             (obj_extent.x2 <= r_x2) &&
1278                             (obj_extent.y1 >= r_y1) &&
1279                             (obj_extent.y2 <= r_y2))
1280                         {
1281                                 select_object_real (view, view_object);
1282                         }
1283
1284                 }
1285         }
1286
1287         g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1288
1289         gl_debug (DEBUG_VIEW, "END");
1290 }
1291
1292 /*---------------------------------------------------------------------------*/
1293 /* PRIVATE. Select an object.                                                */
1294 /*---------------------------------------------------------------------------*/
1295 static void
1296 select_object_real (glView       *view,
1297                     glViewObject *view_object)
1298 {
1299         gl_debug (DEBUG_VIEW, "START");
1300
1301         g_return_if_fail (view && GL_IS_VIEW (view));
1302         g_return_if_fail (GL_IS_VIEW_OBJECT (view_object));
1303
1304         if (!gl_view_is_object_selected (view, view_object)) {
1305                 view->selected_object_list =
1306                     g_list_append (view->selected_object_list, view_object);
1307         }
1308         gtk_widget_grab_focus (GTK_WIDGET (view->canvas));
1309
1310         gl_view_update (view);
1311
1312         gl_debug (DEBUG_VIEW, "END");
1313 }
1314
1315 /*---------------------------------------------------------------------------*/
1316 /* PRIVATE.  Un-select object.                                               */
1317 /*---------------------------------------------------------------------------*/
1318 static void
1319 unselect_object_real (glView       *view,
1320                       glViewObject *view_object)
1321 {
1322         gl_debug (DEBUG_VIEW, "START");
1323
1324         g_return_if_fail (view && GL_IS_VIEW (view));
1325         g_return_if_fail (GL_IS_VIEW_OBJECT (view_object));
1326
1327         view->selected_object_list =
1328             g_list_remove (view->selected_object_list, view_object);
1329
1330         gl_view_update (view);
1331
1332         gl_debug (DEBUG_VIEW, "END");
1333 }
1334
1335 /*---------------------------------------------------------------------------*/
1336 /* PRIVATE. Return object at (x,y).                                          */
1337 /*---------------------------------------------------------------------------*/
1338 static glViewObject *
1339 view_view_object_at (glView  *view,
1340                      cairo_t *cr,
1341                      gdouble  x,
1342                      gdouble  y)
1343 {
1344         GList            *p_obj;
1345         glViewObject     *view_object;
1346
1347         g_return_val_if_fail (view && GL_IS_VIEW (view), NULL);
1348
1349         for (p_obj = g_list_last (view->object_list); p_obj != NULL; p_obj = p_obj->prev)
1350         {
1351
1352                 view_object = GL_VIEW_OBJECT (p_obj->data);
1353
1354                 if (gl_view_object_at (view_object, cr, x, y))
1355                 {
1356                         return view_object;
1357                 }
1358
1359         }
1360
1361         return NULL;
1362 }
1363
1364 /*---------------------------------------------------------------------------*/
1365 /* PRIVATE. Return object handle at (x,y).                                   */
1366 /*---------------------------------------------------------------------------*/
1367 static glViewObject *
1368 view_handle_at (glView             *view,
1369                 cairo_t            *cr,
1370                 gdouble             x,
1371                 gdouble             y,
1372                 glViewObjectHandle *handle)
1373 {
1374         GList            *p_obj;
1375         glViewObject     *view_object;
1376
1377         g_return_val_if_fail (view && GL_IS_VIEW (view), NULL);
1378
1379         for (p_obj = g_list_last (view->selected_object_list); p_obj != NULL; p_obj = p_obj->prev)
1380         {
1381
1382                 view_object = GL_VIEW_OBJECT (p_obj->data);
1383
1384                 if ((*handle = gl_view_object_handle_at (view_object, cr, x, y)))
1385                 {
1386                         return view_object;
1387                 }
1388
1389         }
1390
1391         return NULL;
1392 }
1393
1394 /*****************************************************************************/
1395 /* Is the object in our current selection?                                   */
1396 /*****************************************************************************/
1397 gboolean
1398 gl_view_is_object_selected (glView       *view,
1399                             glViewObject *view_object)
1400 {
1401         gl_debug (DEBUG_VIEW, "");
1402
1403         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
1404         g_return_val_if_fail (GL_IS_VIEW_OBJECT (view_object), FALSE);
1405
1406         if (g_list_find (view->selected_object_list, view_object) == NULL) {
1407                 return FALSE;
1408         }
1409         return TRUE;
1410 }
1411
1412 /*****************************************************************************/
1413 /* Is our current selection empty?                                           */
1414 /*****************************************************************************/
1415 gboolean
1416 gl_view_is_selection_empty (glView *view)
1417 {
1418         gl_debug (DEBUG_VIEW, "");
1419
1420         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
1421
1422         if (view->selected_object_list == NULL) {
1423                 return TRUE;
1424         } else {
1425                 return FALSE;
1426         }
1427 }
1428
1429 /*****************************************************************************/
1430 /* Is our current selection atomic?  I.e. only one item selected.            */
1431 /*****************************************************************************/
1432 gboolean
1433 gl_view_is_selection_atomic (glView *view)
1434 {
1435         gl_debug (DEBUG_VIEW, "");
1436
1437         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
1438
1439         if (view->selected_object_list == NULL)
1440                 return FALSE;
1441         if (view->selected_object_list->next == NULL)
1442                 return TRUE;
1443         return FALSE;
1444 }
1445
1446 /*****************************************************************************/
1447 /* Delete selected objects. (Bypass clipboard)                               */
1448 /*****************************************************************************/
1449 void
1450 gl_view_delete_selection (glView *view)
1451 {
1452         GList         *object_list;
1453         GList         *p;
1454         GList         *p_next;
1455         glViewObject  *view_object;
1456         glLabelObject *object;
1457
1458         gl_debug (DEBUG_VIEW, "START");
1459
1460         g_return_if_fail (view && GL_IS_VIEW (view));
1461
1462         object_list = view->selected_object_list;
1463         view->selected_object_list = NULL;
1464         g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1465
1466         for (p = object_list; p != NULL; p = p_next) {
1467                 p_next = p->next;
1468                 view_object = GL_VIEW_OBJECT (p->data);
1469                 object = gl_view_object_get_object (view_object);
1470                 gl_label_object_remove (object);
1471         }
1472
1473         g_list_free (object_list);
1474
1475         gl_debug (DEBUG_VIEW, "END");
1476 }
1477
1478 /*****************************************************************************/
1479 /* Get object property editor of first selected object.                      */
1480 /*****************************************************************************/
1481 GtkWidget *
1482 gl_view_get_editor (glView *view)
1483 {
1484         glViewObject *view_object;
1485         GtkWidget    *editor = NULL;
1486
1487         gl_debug (DEBUG_VIEW, "START");
1488
1489         g_return_val_if_fail (view && GL_IS_VIEW (view), NULL);
1490
1491         if (!gl_view_is_selection_empty (view)) {
1492
1493                 view_object = GL_VIEW_OBJECT(view->selected_object_list->data);
1494                 editor = gl_view_object_get_editor (view_object);
1495
1496         }
1497
1498         gl_debug (DEBUG_VIEW, "END");
1499
1500         return editor;
1501 }
1502
1503 /*****************************************************************************/
1504 /* Raise selected items to top.                                              */
1505 /*****************************************************************************/
1506 void
1507 gl_view_raise_selection (glView *view)
1508 {
1509         GList         *p;
1510         glViewObject  *view_object;
1511         glLabelObject *object;
1512
1513         gl_debug (DEBUG_VIEW, "START");
1514
1515         g_return_if_fail (view && GL_IS_VIEW (view));
1516
1517         for (p = view->selected_object_list; p != NULL; p = p->next) {
1518                 view_object = GL_VIEW_OBJECT (p->data);
1519                 object = gl_view_object_get_object (view_object);
1520                 gl_label_object_raise_to_top (object);
1521         }
1522
1523         gl_debug (DEBUG_VIEW, "END");
1524 }
1525
1526 /*****************************************************************************/
1527 /* Lower selected items to bottom.                                           */
1528 /*****************************************************************************/
1529 void
1530 gl_view_lower_selection (glView *view)
1531 {
1532         GList         *p;
1533         glViewObject  *view_object;
1534         glLabelObject *object;
1535
1536         gl_debug (DEBUG_VIEW, "START");
1537
1538         g_return_if_fail (view && GL_IS_VIEW (view));
1539
1540         for (p = view->selected_object_list; p != NULL; p = p->next) {
1541                 view_object = GL_VIEW_OBJECT (p->data);
1542                 object = gl_view_object_get_object (view_object);
1543                 gl_label_object_lower_to_bottom (object);
1544         }
1545
1546         gl_debug (DEBUG_VIEW, "END");
1547 }
1548
1549 /*****************************************************************************/
1550 /* Rotate selected objects by given angle.                                   */
1551 /*****************************************************************************/
1552 void
1553 gl_view_rotate_selection (glView *view,
1554                           gdouble theta_degs)
1555 {
1556         GList         *p;
1557         glViewObject  *view_object;
1558         glLabelObject *object;
1559
1560         gl_debug (DEBUG_VIEW, "START");
1561
1562         g_return_if_fail (view && GL_IS_VIEW (view));
1563
1564         for (p = view->selected_object_list; p != NULL; p = p->next) {
1565                 view_object = GL_VIEW_OBJECT (p->data);
1566                 object = gl_view_object_get_object (view_object);
1567                 gl_label_object_rotate (object, theta_degs);
1568         }
1569
1570         gl_debug (DEBUG_VIEW, "END");
1571 }
1572
1573 /*****************************************************************************/
1574 /* Rotate selected objects 90 degrees left.                                  */
1575 /*****************************************************************************/
1576 void
1577 gl_view_rotate_selection_left (glView *view)
1578 {
1579         GList         *p;
1580         glViewObject  *view_object;
1581         glLabelObject *object;
1582
1583         gl_debug (DEBUG_VIEW, "START");
1584
1585         g_return_if_fail (view && GL_IS_VIEW (view));
1586
1587         for (p = view->selected_object_list; p != NULL; p = p->next) {
1588                 view_object = GL_VIEW_OBJECT (p->data);
1589                 object = gl_view_object_get_object (view_object);
1590                 gl_label_object_rotate (object, -90.0);
1591         }
1592
1593         gl_debug (DEBUG_VIEW, "END");
1594 }
1595
1596 /*****************************************************************************/
1597 /* Rotate selected objects 90 degrees right.                                 */
1598 /*****************************************************************************/
1599 void
1600 gl_view_rotate_selection_right (glView *view)
1601 {
1602         GList         *p;
1603         glViewObject  *view_object;
1604         glLabelObject *object;
1605
1606         gl_debug (DEBUG_VIEW, "START");
1607
1608         g_return_if_fail (view && GL_IS_VIEW (view));
1609
1610         for (p = view->selected_object_list; p != NULL; p = p->next) {
1611                 view_object = GL_VIEW_OBJECT (p->data);
1612                 object = gl_view_object_get_object (view_object);
1613                 gl_label_object_rotate (object, 90.0);
1614         }
1615
1616         gl_debug (DEBUG_VIEW, "END");
1617 }
1618
1619 /*****************************************************************************/
1620 /* Flip selected objects horizontally.                                       */
1621 /*****************************************************************************/
1622 void
1623 gl_view_flip_selection_horiz (glView *view)
1624 {
1625         GList         *p;
1626         glViewObject  *view_object;
1627         glLabelObject *object;
1628
1629         gl_debug (DEBUG_VIEW, "START");
1630
1631         g_return_if_fail (view && GL_IS_VIEW (view));
1632
1633         for (p = view->selected_object_list; p != NULL; p = p->next) {
1634                 view_object = GL_VIEW_OBJECT (p->data);
1635                 object = gl_view_object_get_object (view_object);
1636                 gl_label_object_flip_horiz (object);
1637         }
1638
1639         gl_debug (DEBUG_VIEW, "END");
1640 }
1641
1642 /*****************************************************************************/
1643 /* Flip selected objects vertically.                                         */
1644 /*****************************************************************************/
1645 void
1646 gl_view_flip_selection_vert (glView *view)
1647 {
1648         GList         *p;
1649         glViewObject  *view_object;
1650         glLabelObject *object;
1651
1652         gl_debug (DEBUG_VIEW, "START");
1653
1654         g_return_if_fail (view && GL_IS_VIEW (view));
1655
1656         for (p = view->selected_object_list; p != NULL; p = p->next) {
1657                 view_object = GL_VIEW_OBJECT (p->data);
1658                 object = gl_view_object_get_object (view_object);
1659                 gl_label_object_flip_vert (object);
1660         }
1661
1662         gl_debug (DEBUG_VIEW, "END");
1663 }
1664
1665 /*****************************************************************************/
1666 /* Align selected objects to left most edge.                                 */
1667 /*****************************************************************************/
1668 void
1669 gl_view_align_selection_left (glView *view)
1670 {
1671         GList         *p;
1672         glViewObject  *view_object;
1673         glLabelObject *object;
1674         gdouble        dx, x1_min;
1675         glLabelRegion  obj_extent;
1676
1677         gl_debug (DEBUG_VIEW, "START");
1678
1679         g_return_if_fail (view && GL_IS_VIEW (view));
1680
1681         g_return_if_fail (!gl_view_is_selection_empty (view) &&
1682                           !gl_view_is_selection_atomic (view));
1683
1684         /* find left most edge */
1685         p = view->selected_object_list;
1686         view_object = GL_VIEW_OBJECT (p->data);
1687         object = gl_view_object_get_object (view_object);
1688         gl_label_object_get_extent (object, &obj_extent);
1689         x1_min = obj_extent.x1;
1690         for (p = p->next; p != NULL; p = p->next)
1691         {
1692                 view_object = GL_VIEW_OBJECT (p->data);
1693                 object = gl_view_object_get_object (view_object);
1694                 gl_label_object_get_extent (object, &obj_extent);
1695                 if ( obj_extent.x1 < x1_min ) x1_min = obj_extent.x1;
1696         }
1697
1698         /* now adjust the object positions to line up the left edges */
1699         for (p = view->selected_object_list; p != NULL; p = p->next)
1700         {
1701                 view_object = GL_VIEW_OBJECT (p->data);
1702                 object = gl_view_object_get_object (view_object);
1703                 gl_label_object_get_extent (object, &obj_extent);
1704                 dx = x1_min - obj_extent.x1;
1705                 gl_label_object_set_position_relative (object, dx, 0.0);
1706         }
1707
1708         gl_debug (DEBUG_VIEW, "END");
1709 }
1710
1711
1712 /*****************************************************************************/
1713 /* Align selected objects to right most edge.                                */
1714 /*****************************************************************************/
1715 void
1716 gl_view_align_selection_right (glView *view)
1717 {
1718         GList         *p;
1719         glViewObject  *view_object;
1720         glLabelObject *object;
1721         gdouble        dx, x2_max;
1722         glLabelRegion  obj_extent;
1723
1724         gl_debug (DEBUG_VIEW, "START");
1725
1726         g_return_if_fail (view && GL_IS_VIEW (view));
1727
1728         g_return_if_fail (!gl_view_is_selection_empty (view) &&
1729                           !gl_view_is_selection_atomic (view));
1730
1731         /* find right most edge */
1732         p = view->selected_object_list;
1733         view_object = GL_VIEW_OBJECT (p->data);
1734         object = gl_view_object_get_object (view_object);
1735         gl_label_object_get_extent (object, &obj_extent);
1736         x2_max = obj_extent.x2;
1737         for (p = p->next; p != NULL; p = p->next)
1738         {
1739                 view_object = GL_VIEW_OBJECT (p->data);
1740                 object = gl_view_object_get_object (view_object);
1741                 gl_label_object_get_extent (object, &obj_extent);
1742                 if ( obj_extent.x2 > x2_max ) x2_max = obj_extent.x2;
1743         }
1744
1745         /* now adjust the object positions to line up the right edges */
1746         for (p = view->selected_object_list; p != NULL; p = p->next)
1747         {
1748                 view_object = GL_VIEW_OBJECT (p->data);
1749                 object = gl_view_object_get_object (view_object);
1750                 gl_label_object_get_extent (object, &obj_extent);
1751                 dx = x2_max - obj_extent.x2;
1752                 gl_label_object_set_position_relative (object, dx, 0.0);
1753         }
1754
1755         gl_debug (DEBUG_VIEW, "END");
1756 }
1757
1758 /*****************************************************************************/
1759 /* Align selected objects to horizontal center of objects.                   */
1760 /*****************************************************************************/
1761 void
1762 gl_view_align_selection_hcenter (glView *view)
1763 {
1764         GList         *p;
1765         glViewObject  *view_object;
1766         glLabelObject *object;
1767         gdouble        dx;
1768         gdouble        dxmin;
1769         gdouble        xsum, xavg;
1770         glLabelRegion  obj_extent;
1771         gdouble        xcenter;
1772         gint           n;
1773
1774         gl_debug (DEBUG_VIEW, "START");
1775
1776         g_return_if_fail (view && GL_IS_VIEW (view));
1777
1778         g_return_if_fail (!gl_view_is_selection_empty (view) &&
1779                           !gl_view_is_selection_atomic (view));
1780
1781         /* find average center of objects */
1782         xsum = 0.0;
1783         n = 0;
1784         for (p = view->selected_object_list; p != NULL; p = p->next)
1785         {
1786                 view_object = GL_VIEW_OBJECT (p->data);
1787                 object = gl_view_object_get_object (view_object);
1788                 gl_label_object_get_extent (object, &obj_extent);
1789                 xsum += (obj_extent.x1 + obj_extent.x2) / 2.0;
1790                 n++;
1791         }
1792         xavg = xsum / n;
1793
1794         /* find center of object closest to average center */
1795         p = view->selected_object_list;
1796         view_object = GL_VIEW_OBJECT (p->data);
1797         object = gl_view_object_get_object (view_object);
1798         gl_label_object_get_extent (object, &obj_extent);
1799         dxmin = fabs (xavg - (obj_extent.x1 + obj_extent.x2)/2.0);
1800         xcenter = (obj_extent.x1 + obj_extent.x2)/2.0;
1801         for (p = p->next; p != NULL; p = p->next)
1802         {
1803                 view_object = GL_VIEW_OBJECT (p->data);
1804                 object = gl_view_object_get_object (view_object);
1805                 gl_label_object_get_extent (object, &obj_extent);
1806                 dx = fabs (xavg - (obj_extent.x1 + obj_extent.x2)/2.0);
1807                 if ( dx < dxmin )
1808                 {
1809                         dxmin = dx;
1810                         xcenter = (obj_extent.x1 + obj_extent.x2)/2.0;
1811                 }
1812         }
1813
1814         /* now adjust the object positions to line up this center */
1815         for (p = view->selected_object_list; p != NULL; p = p->next) {
1816                 view_object = GL_VIEW_OBJECT (p->data);
1817                 object = gl_view_object_get_object (view_object);
1818                 gl_label_object_get_extent (object, &obj_extent);
1819                 dx = xcenter - (obj_extent.x1 + obj_extent.x2)/2.0;
1820                 gl_label_object_set_position_relative (object, dx, 0.0);
1821         }
1822
1823         gl_debug (DEBUG_VIEW, "END");
1824 }
1825
1826 /*****************************************************************************/
1827 /* Align selected objects to top most edge.                                  */
1828 /*****************************************************************************/
1829 void
1830 gl_view_align_selection_top (glView *view)
1831 {
1832         GList         *p;
1833         glViewObject  *view_object;
1834         glLabelObject *object;
1835         gdouble        dy, y1_min;
1836         glLabelRegion  obj_extent;
1837
1838         gl_debug (DEBUG_VIEW, "START");
1839
1840         g_return_if_fail (view && GL_IS_VIEW (view));
1841
1842         g_return_if_fail (!gl_view_is_selection_empty (view) &&
1843                           !gl_view_is_selection_atomic (view));
1844
1845         /* find top most edge */
1846         p = view->selected_object_list;
1847         view_object = GL_VIEW_OBJECT (p->data);
1848         object = gl_view_object_get_object (view_object);
1849         gl_label_object_get_extent (object, &obj_extent);
1850         y1_min = obj_extent.y1;
1851         for (p = p->next; p != NULL; p = p->next)
1852         {
1853                 view_object = GL_VIEW_OBJECT (p->data);
1854                 object = gl_view_object_get_object (view_object);
1855                 gl_label_object_get_extent (object, &obj_extent);
1856                 if ( obj_extent.y1 < y1_min ) y1_min = obj_extent.y1;
1857         }
1858
1859         /* now adjust the object positions to line up the top edges */
1860         for (p = view->selected_object_list; p != NULL; p = p->next)
1861         {
1862                 view_object = GL_VIEW_OBJECT (p->data);
1863                 object = gl_view_object_get_object (view_object);
1864                 gl_label_object_get_extent (object, &obj_extent);
1865                 dy = y1_min - obj_extent.y1;
1866                 gl_label_object_set_position_relative (object, 0.0, dy);
1867         }
1868
1869         gl_debug (DEBUG_VIEW, "END");
1870 }
1871
1872 /*****************************************************************************/
1873 /* Align selected objects to bottom most edge.                               */
1874 /*****************************************************************************/
1875 void
1876 gl_view_align_selection_bottom (glView *view)
1877 {
1878         GList         *p;
1879         glViewObject  *view_object;
1880         glLabelObject *object;
1881         gdouble        dy, y2_max;
1882         glLabelRegion  obj_extent;
1883
1884         gl_debug (DEBUG_VIEW, "START");
1885
1886         g_return_if_fail (view && GL_IS_VIEW (view));
1887
1888         g_return_if_fail (!gl_view_is_selection_empty (view) &&
1889                           !gl_view_is_selection_atomic (view));
1890
1891         /* find bottom most edge */
1892         p = view->selected_object_list;
1893         view_object = GL_VIEW_OBJECT (p->data);
1894         object = gl_view_object_get_object (view_object);
1895         gl_label_object_get_extent (object, &obj_extent);
1896         y2_max = obj_extent.y2;
1897         for (p = p->next; p != NULL; p = p->next)
1898         {
1899                 view_object = GL_VIEW_OBJECT (p->data);
1900                 object = gl_view_object_get_object (view_object);
1901                 gl_label_object_get_extent (object, &obj_extent);
1902                 if ( obj_extent.y2 > y2_max ) y2_max = obj_extent.y2;
1903         }
1904
1905         /* now adjust the object positions to line up the bottom edges */
1906         for (p = view->selected_object_list; p != NULL; p = p->next)
1907         {
1908                 view_object = GL_VIEW_OBJECT (p->data);
1909                 object = gl_view_object_get_object (view_object);
1910                 gl_label_object_get_extent (object, &obj_extent);
1911                 dy = y2_max - obj_extent.y2;
1912                 gl_label_object_set_position_relative (object, 0.0, dy);
1913         }
1914
1915         gl_debug (DEBUG_VIEW, "END");
1916 }
1917
1918 /*****************************************************************************/
1919 /* Align selected objects to viertical center of objects.                    */
1920 /*****************************************************************************/
1921 void
1922 gl_view_align_selection_vcenter (glView *view)
1923 {
1924         GList         *p;
1925         glViewObject  *view_object;
1926         glLabelObject *object;
1927         gdouble        dy;
1928         gdouble        dymin;
1929         gdouble        ysum, yavg;
1930         glLabelRegion  obj_extent;
1931         gdouble        ycenter;
1932         gint           n;
1933
1934         gl_debug (DEBUG_VIEW, "START");
1935
1936         g_return_if_fail (view && GL_IS_VIEW (view));
1937
1938         g_return_if_fail (!gl_view_is_selection_empty (view) &&
1939                           !gl_view_is_selection_atomic (view));
1940
1941         /* find average center of objects */
1942         ysum = 0.0;
1943         n = 0;
1944         for (p = view->selected_object_list; p != NULL; p = p->next)
1945         {
1946                 view_object = GL_VIEW_OBJECT (p->data);
1947                 object = gl_view_object_get_object (view_object);
1948                 gl_label_object_get_extent (object, &obj_extent);
1949                 ysum += (obj_extent.y1 + obj_extent.y2) / 2.0;
1950                 n++;
1951         }
1952         yavg = ysum / n;
1953
1954         /* find center of object closest to average center */
1955         p = view->selected_object_list;
1956         view_object = GL_VIEW_OBJECT (p->data);
1957         object = gl_view_object_get_object (view_object);
1958         gl_label_object_get_extent (object, &obj_extent);
1959         dymin = fabs (yavg - (obj_extent.y1 + obj_extent.y2)/2.0);
1960         ycenter = (obj_extent.y1 + obj_extent.y2)/2.0;
1961         for (p = p->next; p != NULL; p = p->next)
1962         {
1963                 view_object = GL_VIEW_OBJECT (p->data);
1964                 object = gl_view_object_get_object (view_object);
1965                 gl_label_object_get_extent (object, &obj_extent);
1966                 dy = fabs (yavg - (obj_extent.y1 + obj_extent.y2)/2.0);
1967                 if ( dy < dymin )
1968                 {
1969                         dymin = dy;
1970                         ycenter = (obj_extent.y1 + obj_extent.y2)/2.0;
1971                 }
1972         }
1973
1974         /* now adjust the object positions to line up this center */
1975         for (p = view->selected_object_list; p != NULL; p = p->next)
1976         {
1977                 view_object = GL_VIEW_OBJECT (p->data);
1978                 object = gl_view_object_get_object (view_object);
1979                 gl_label_object_get_extent (object, &obj_extent);
1980                 dy = ycenter - (obj_extent.y1 + obj_extent.y2)/2.0;
1981                 gl_label_object_set_position_relative (object, 0.0, dy);
1982         }
1983
1984         gl_debug (DEBUG_VIEW, "END");
1985 }
1986
1987 /*****************************************************************************/
1988 /* Center selected objects to in center of label.                            */
1989 /*****************************************************************************/
1990 void
1991 gl_view_center_selection_horiz (glView *view)
1992 {
1993         GList         *p;
1994         glViewObject  *view_object;
1995         glLabelObject *object;
1996         gdouble        dx;
1997         gdouble        x_label_center;
1998         gdouble        x_obj_center;
1999         glLabelRegion  obj_extent;
2000         gdouble        w, h;
2001
2002         gl_debug (DEBUG_VIEW, "START");
2003
2004         g_return_if_fail (view && GL_IS_VIEW (view));
2005
2006         g_return_if_fail (!gl_view_is_selection_empty (view));
2007
2008         gl_label_get_size (view->label, &w, &h);
2009         x_label_center = w / 2.0;
2010
2011         /* adjust the object positions */
2012         for (p = view->selected_object_list; p != NULL; p = p->next)
2013         {
2014                 view_object = GL_VIEW_OBJECT (p->data);
2015                 object = gl_view_object_get_object (view_object);
2016                 gl_label_object_get_extent (object, &obj_extent);
2017                 x_obj_center = (obj_extent.x1 + obj_extent.x2) / 2.0;
2018                 dx = x_label_center - x_obj_center;
2019                 gl_label_object_set_position_relative (object, dx, 0.0);
2020         }
2021
2022         gl_debug (DEBUG_VIEW, "END");
2023 }
2024
2025
2026 /*****************************************************************************/
2027 /* Center selected objects to in center of label.                            */
2028 /*****************************************************************************/
2029 void
2030 gl_view_center_selection_vert (glView *view)
2031 {
2032         GList         *p;
2033         glViewObject  *view_object;
2034         glLabelObject *object;
2035         gdouble        dy;
2036         gdouble        y_label_center;
2037         gdouble        y_obj_center;
2038         glLabelRegion  obj_extent;
2039         gdouble        w, h;
2040
2041         gl_debug (DEBUG_VIEW, "START");
2042
2043         g_return_if_fail (view && GL_IS_VIEW (view));
2044
2045         g_return_if_fail (!gl_view_is_selection_empty (view));
2046
2047         gl_label_get_size (view->label, &w, &h);
2048         y_label_center = h / 2.0;
2049
2050         /* adjust the object positions */
2051         for (p = view->selected_object_list; p != NULL; p = p->next)
2052         {
2053                 view_object = GL_VIEW_OBJECT (p->data);
2054                 object = gl_view_object_get_object (view_object);
2055                 gl_label_object_get_extent (object, &obj_extent);
2056                 y_obj_center = (obj_extent.y1 + obj_extent.y2) / 2.0;
2057                 dy = y_label_center - y_obj_center;
2058                 gl_label_object_set_position_relative (object, 0.0, dy);
2059         }
2060
2061         gl_debug (DEBUG_VIEW, "END");
2062 }
2063
2064
2065 /*****************************************************************************/
2066 /* Move selected objects                                                     */
2067 /*****************************************************************************/
2068 void
2069 gl_view_move_selection (glView  *view,
2070                         gdouble  dx,
2071                         gdouble  dy)
2072 {
2073         GList         *p;
2074         glLabelObject *object;
2075
2076         gl_debug (DEBUG_VIEW, "START");
2077
2078         g_return_if_fail (view && GL_IS_VIEW (view));
2079
2080         for (p = view->selected_object_list; p != NULL; p = p->next)
2081         {
2082
2083                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2084                 gl_label_object_set_position_relative (object, dx, dy);
2085
2086         }
2087
2088         gl_debug (DEBUG_VIEW, "END");
2089 }
2090
2091 /*****************************************************************************/
2092 /* Can text properties be set for selection?                                 */
2093 /*****************************************************************************/
2094 gboolean
2095 gl_view_can_selection_text (glView *view)
2096 {
2097         GList         *p;
2098         glLabelObject *object;
2099
2100         gl_debug (DEBUG_VIEW, "");
2101
2102         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
2103
2104         for (p = view->selected_object_list; p != NULL; p = p->next)
2105         {
2106
2107                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2108                 if (gl_label_object_can_text (object))
2109                 {
2110                         return TRUE;
2111                 }
2112
2113         }
2114
2115         return FALSE;
2116 }
2117
2118 /*****************************************************************************/
2119 /* Set font family for all text contained in selected objects.               */
2120 /*****************************************************************************/
2121 void
2122 gl_view_set_selection_font_family (glView      *view,
2123                                    const gchar *font_family)
2124 {
2125         GList         *p;
2126         glLabelObject *object;
2127
2128         gl_debug (DEBUG_VIEW, "START");
2129
2130         g_return_if_fail (view && GL_IS_VIEW (view));
2131
2132         for (p = view->selected_object_list; p != NULL; p = p->next) {
2133
2134                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2135                 gl_label_object_set_font_family (object, font_family);
2136
2137         }
2138
2139         gl_debug (DEBUG_VIEW, "END");
2140 }
2141
2142 /*****************************************************************************/
2143 /* Set font size for all text contained in selected objects.                 */
2144 /*****************************************************************************/
2145 void
2146 gl_view_set_selection_font_size (glView  *view,
2147                                  gdouble  font_size)
2148 {
2149         GList         *p;
2150         glLabelObject *object;
2151
2152         gl_debug (DEBUG_VIEW, "START");
2153
2154         g_return_if_fail (view && GL_IS_VIEW (view));
2155
2156         for (p = view->selected_object_list; p != NULL; p = p->next) {
2157
2158                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2159                 gl_label_object_set_font_size (object, font_size);
2160
2161         }
2162
2163         gl_debug (DEBUG_VIEW, "END");
2164 }
2165
2166 /*****************************************************************************/
2167 /* Set font weight for all text contained in selected objects.               */
2168 /*****************************************************************************/
2169 void
2170 gl_view_set_selection_font_weight (glView      *view,
2171                                    PangoWeight  font_weight)
2172 {
2173         GList         *p;
2174         glLabelObject *object;
2175
2176         gl_debug (DEBUG_VIEW, "START");
2177
2178         g_return_if_fail (view && GL_IS_VIEW (view));
2179
2180         for (p = view->selected_object_list; p != NULL; p = p->next) {
2181
2182                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2183                 gl_label_object_set_font_weight (object, font_weight);
2184
2185         }
2186
2187         gl_debug (DEBUG_VIEW, "END");
2188 }
2189
2190 /*****************************************************************************/
2191 /* Set font italic flag for all text contained in selected objects.          */
2192 /*****************************************************************************/
2193 void
2194 gl_view_set_selection_font_italic_flag (glView   *view,
2195                                         gboolean  font_italic_flag)
2196 {
2197         GList         *p;
2198         glLabelObject *object;
2199
2200         gl_debug (DEBUG_VIEW, "START");
2201
2202         g_return_if_fail (view && GL_IS_VIEW (view));
2203
2204         for (p = view->selected_object_list; p != NULL; p = p->next) {
2205
2206                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2207                 gl_label_object_set_font_italic_flag (object, font_italic_flag);
2208
2209         }
2210
2211         gl_debug (DEBUG_VIEW, "END");
2212 }
2213
2214 /*****************************************************************************/
2215 /* Set text alignment for all text contained in selected objects.            */
2216 /*****************************************************************************/
2217 void
2218 gl_view_set_selection_text_alignment (glView            *view,
2219                                       PangoAlignment     text_alignment)
2220 {
2221         GList         *p;
2222         glLabelObject *object;
2223
2224         gl_debug (DEBUG_VIEW, "START");
2225
2226         g_return_if_fail (view && GL_IS_VIEW (view));
2227
2228         for (p = view->selected_object_list; p != NULL; p = p->next) {
2229
2230                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2231                 gl_label_object_set_text_alignment (object, text_alignment);
2232
2233         }
2234
2235         gl_debug (DEBUG_VIEW, "END");
2236 }
2237
2238 /*****************************************************************************/
2239 /* Set text line spacing for all text contained in selected objects.         */
2240 /*****************************************************************************/
2241 void
2242 gl_view_set_selection_text_line_spacing (glView  *view,
2243                                          gdouble  text_line_spacing)
2244 {
2245         GList         *p;
2246         glLabelObject *object;
2247
2248         gl_debug (DEBUG_VIEW, "START");
2249
2250         g_return_if_fail (view && GL_IS_VIEW (view));
2251
2252         for (p = view->selected_object_list; p != NULL; p = p->next) {
2253
2254                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2255                 gl_label_object_set_text_line_spacing (object, text_line_spacing);
2256
2257         }
2258
2259         gl_debug (DEBUG_VIEW, "END");
2260 }
2261 /*****************************************************************************/
2262 /* Set text color for all text contained in selected objects.                */
2263 /*****************************************************************************/
2264 void
2265 gl_view_set_selection_text_color (glView      *view,
2266                                   glColorNode *text_color_node)
2267 {
2268         GList         *p;
2269         glLabelObject *object;
2270
2271         gl_debug (DEBUG_VIEW, "START");
2272
2273         g_return_if_fail (view && GL_IS_VIEW (view));
2274
2275         for (p = view->selected_object_list; p != NULL; p = p->next) {
2276
2277                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2278                 gl_label_object_set_text_color (object, text_color_node);
2279
2280         }
2281
2282         gl_debug (DEBUG_VIEW, "END");
2283 }
2284
2285 /*****************************************************************************/
2286 /* Can fill properties be set for selection?                                 */
2287 /*****************************************************************************/
2288 gboolean
2289 gl_view_can_selection_fill (glView *view)
2290 {
2291         GList         *p;
2292         glLabelObject *object;
2293
2294         gl_debug (DEBUG_VIEW, "");
2295
2296         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
2297
2298         for (p = view->selected_object_list; p != NULL; p = p->next) {
2299
2300                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2301                 if (gl_label_object_can_fill (object)) {
2302                         return TRUE;
2303                 }
2304
2305         }
2306
2307         return FALSE;
2308 }
2309
2310 /*****************************************************************************/
2311 /* Set fill color for all selected objects.                                  */
2312 /*****************************************************************************/
2313 void
2314 gl_view_set_selection_fill_color (glView      *view,
2315                                   glColorNode *fill_color_node)
2316 {
2317         GList         *p;
2318         glLabelObject *object;
2319
2320         gl_debug (DEBUG_VIEW, "START");
2321
2322         g_return_if_fail (view && GL_IS_VIEW (view));
2323
2324         for (p = view->selected_object_list; p != NULL; p = p->next) {
2325
2326                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2327                 gl_label_object_set_fill_color (object, fill_color_node);
2328
2329         }
2330
2331         gl_debug (DEBUG_VIEW, "END");
2332 }
2333
2334 /*****************************************************************************/
2335 /* Can line color properties be set for selection?                           */
2336 /*****************************************************************************/
2337 gboolean
2338 gl_view_can_selection_line_color (glView *view)
2339 {
2340         GList         *p;
2341         glLabelObject *object;
2342
2343         gl_debug (DEBUG_VIEW, "");
2344
2345         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
2346
2347         for (p = view->selected_object_list; p != NULL; p = p->next) {
2348
2349                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2350                 if (gl_label_object_can_line_color (object)) {
2351                         return TRUE;
2352                 }
2353
2354         }
2355
2356         return FALSE;
2357 }
2358
2359 /*****************************************************************************/
2360 /* Set line color for all selected objects.                                  */
2361 /*****************************************************************************/
2362 void
2363 gl_view_set_selection_line_color (glView      *view,
2364                                   glColorNode *line_color_node)
2365 {
2366         GList         *p;
2367         glLabelObject *object;
2368
2369         gl_debug (DEBUG_VIEW, "START");
2370
2371         g_return_if_fail (view && GL_IS_VIEW (view));
2372
2373         for (p = view->selected_object_list; p != NULL; p = p->next) {
2374
2375                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2376                 gl_label_object_set_line_color (object, line_color_node);
2377
2378         }
2379
2380         gl_debug (DEBUG_VIEW, "END");
2381 }
2382
2383 /*****************************************************************************/
2384 /* Can line width properties be set for selection?                           */
2385 /*****************************************************************************/
2386 gboolean
2387 gl_view_can_selection_line_width (glView *view)
2388 {
2389         GList         *p;
2390         glLabelObject *object;
2391
2392         gl_debug (DEBUG_VIEW, "");
2393
2394         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
2395
2396         for (p = view->selected_object_list; p != NULL; p = p->next) {
2397
2398                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2399                 if (gl_label_object_can_line_width (object)) {
2400                         return TRUE;
2401                 }
2402
2403         }
2404
2405         return FALSE;
2406 }
2407
2408 /*****************************************************************************/
2409 /* Set line width for all selected objects.                                  */
2410 /*****************************************************************************/
2411 void
2412 gl_view_set_selection_line_width (glView  *view,
2413                                   gdouble  line_width)
2414 {
2415         GList         *p;
2416         glLabelObject *object;
2417
2418         gl_debug (DEBUG_VIEW, "START");
2419
2420         g_return_if_fail (view && GL_IS_VIEW (view));
2421
2422         for (p = view->selected_object_list; p != NULL; p = p->next) {
2423
2424                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2425                 gl_label_object_set_line_width (object, line_width);
2426
2427         }
2428
2429         gl_debug (DEBUG_VIEW, "END");
2430 }
2431
2432 /*****************************************************************************/
2433 /* "Cut" selected items and place in clipboard selections.                   */
2434 /*****************************************************************************/
2435 void
2436 gl_view_cut (glView *view)
2437 {
2438         gl_debug (DEBUG_VIEW, "START");
2439
2440         g_return_if_fail (view && GL_IS_VIEW (view));
2441
2442         gl_view_copy (view);
2443         gl_view_delete_selection (view);
2444
2445         gl_debug (DEBUG_VIEW, "END");
2446 }
2447
2448 /*****************************************************************************/
2449 /* "Copy" selected items to clipboard selections.                            */
2450 /*****************************************************************************/
2451 void
2452 gl_view_copy (glView *view)
2453 {
2454         GList         *p;
2455         glViewObject  *view_object;
2456         glLabelObject *object;
2457
2458         gl_debug (DEBUG_VIEW, "START");
2459
2460         g_return_if_fail (view && GL_IS_VIEW (view));
2461
2462         if (view->selected_object_list) {
2463
2464                 if ( view->selection_data ) {
2465                         g_object_unref (view->selection_data);
2466                 }
2467                 view->selection_data = GL_LABEL(gl_label_new ());
2468                 gl_label_set_template (view->selection_data, view->label->template);
2469                 gl_label_set_rotate_flag (view->selection_data, view->label->rotate_flag);
2470
2471                 for (p = view->selected_object_list; p != NULL; p = p->next) {
2472
2473                         view_object = GL_VIEW_OBJECT (p->data);
2474                         object = gl_view_object_get_object (view_object);
2475
2476                         gl_label_object_dup (object, view->selection_data);
2477
2478                 }
2479
2480                 gtk_selection_owner_set (view->invisible,
2481                                          clipboard_atom, GDK_CURRENT_TIME);
2482                 view->have_selection = TRUE;
2483
2484         }
2485
2486         gl_debug (DEBUG_VIEW, "END");
2487 }
2488
2489 /*****************************************************************************/
2490 /* "Paste" from private clipboard selection.                                 */
2491 /*****************************************************************************/
2492 void
2493 gl_view_paste (glView *view)
2494 {
2495         gl_debug (DEBUG_VIEW, "START");
2496
2497         g_return_if_fail (view && GL_IS_VIEW (view));
2498
2499         gtk_selection_convert (GTK_WIDGET (view->invisible),
2500                                clipboard_atom, GDK_SELECTION_TYPE_STRING,
2501                                GDK_CURRENT_TIME);
2502
2503         gl_debug (DEBUG_VIEW, "END");
2504 }
2505
2506 /*****************************************************************************/
2507 /* Zoom in one "notch"                                                       */
2508 /*****************************************************************************/
2509 void
2510 gl_view_zoom_in (glView *view)
2511 {
2512         gint    i, i_min;
2513         gdouble dist, dist_min;
2514
2515         gl_debug (DEBUG_VIEW, "START");
2516
2517         g_return_if_fail (view && GL_IS_VIEW (view));
2518
2519         /* Find index of current scale (or best match) */
2520         i_min = 1;              /* start with 2nd largest scale */
2521         dist_min = fabs (zooms[1] - view->zoom);
2522         for (i = 2; i < N_ZOOMS; i++) {
2523                 dist = fabs (zooms[i] - view->zoom);
2524                 if (dist < dist_min) {
2525                         i_min = i;
2526                         dist_min = dist;
2527                 }
2528         }
2529
2530         /* zoom in one "notch" */
2531         i = MAX (0, i_min - 1);
2532         gl_debug (DEBUG_VIEW, "zoom[%d] = %g", i, zooms[i]);
2533         set_zoom_real (view, zooms[i], FALSE);
2534
2535         gl_debug (DEBUG_VIEW, "END");
2536 }
2537
2538 /*****************************************************************************/
2539 /* Zoom out one "notch"                                                      */
2540 /*****************************************************************************/
2541 void
2542 gl_view_zoom_out (glView *view)
2543 {
2544         gint    i, i_min;
2545         gdouble dist, dist_min;
2546
2547         gl_debug (DEBUG_VIEW, "START");
2548
2549         g_return_if_fail (view && GL_IS_VIEW (view));
2550
2551         /* Find index of current scale (or best match) */
2552         i_min = 0;              /* start with largest scale */
2553         dist_min = fabs (zooms[0] - view->zoom);
2554         for (i = 1; i < N_ZOOMS; i++) {
2555                 dist = fabs (zooms[i] - view->zoom);
2556                 if (dist < dist_min) {
2557                         i_min = i;
2558                         dist_min = dist;
2559                 }
2560         }
2561
2562         /* zoom out one "notch" */
2563         if (i_min >= N_ZOOMS)
2564                 return;
2565         i = i_min + 1;
2566         if (i >= N_ZOOMS)
2567                 return;
2568         set_zoom_real (view, zooms[i], FALSE);
2569
2570         gl_debug (DEBUG_VIEW, "END");
2571 }
2572
2573 /*****************************************************************************/
2574 /* Set zoom to best fit.                                                     */
2575 /*****************************************************************************/
2576 void
2577 gl_view_zoom_to_fit (glView *view)
2578 {
2579         gint    w_view, h_view;
2580         gdouble w_label, h_label;
2581         gdouble x_scale, y_scale, scale;
2582
2583         gl_debug (DEBUG_VIEW, "");
2584
2585         if ( ! GTK_WIDGET_VISIBLE(view)) {
2586                 set_zoom_real (view, 1.0, TRUE);
2587                 return;
2588         }
2589
2590         w_view = GTK_WIDGET(view)->allocation.width;
2591         h_view = GTK_WIDGET(view)->allocation.height;
2592
2593         gl_label_get_size (GL_LABEL(view->label), &w_label, &h_label);
2594
2595         gl_debug (DEBUG_VIEW, "View size: %d, %d", w_view, h_view);
2596         gl_debug (DEBUG_VIEW, "Label size: %g, %g", w_label, h_label);
2597
2598         /* Calculate best scale */
2599         x_scale = (double)(w_view - ZOOMTOFIT_PAD) / w_label;
2600         y_scale = (double)(h_view - ZOOMTOFIT_PAD) / h_label;
2601         scale = MIN (x_scale, y_scale);
2602         gl_debug (DEBUG_VIEW, "Candidate zooms: %g, %g => %g", x_scale, y_scale, scale);
2603
2604         /* Limit */
2605         gl_debug (DEBUG_VIEW, "Scale: %g", scale);
2606         scale = MIN (scale, zooms[0]*view->home_scale);
2607         scale = MAX (scale, zooms[N_ZOOMS-1]*view->home_scale);
2608         gl_debug (DEBUG_VIEW, "Limitted scale: %g", scale);
2609
2610         set_zoom_real (view, scale/view->home_scale, TRUE);
2611 }
2612
2613 /*****************************************************************************/
2614 /* Set current zoom factor to explicit value.                                */
2615 /*****************************************************************************/
2616 void
2617 gl_view_set_zoom (glView  *view,
2618                   gdouble  zoom)
2619 {
2620         gl_debug (DEBUG_VIEW, "START");
2621
2622         set_zoom_real (view, zoom, FALSE);
2623
2624         gl_debug (DEBUG_VIEW, "END");
2625 }
2626
2627 /*---------------------------------------------------------------------------*/
2628 /* PRIVATE.  Set canvas scale.                                               */
2629 /*---------------------------------------------------------------------------*/
2630 static void
2631 set_zoom_real (glView   *view,
2632                gdouble   zoom,
2633                gboolean  zoom_to_fit_flag)
2634 {
2635         gl_debug (DEBUG_VIEW, "START");
2636
2637         g_return_if_fail (view && GL_IS_VIEW (view));
2638         g_return_if_fail (zoom > 0.0);
2639
2640         /* Limit, if needed */
2641         gl_debug (DEBUG_VIEW, "Zoom requested: %g", zoom);
2642         zoom = MIN (zoom, zooms[0]);
2643         zoom = MAX (zoom, zooms[N_ZOOMS-1]);
2644         gl_debug (DEBUG_VIEW, "Limitted zoom: %g", zoom);
2645
2646         if ( zoom != view->zoom ) {
2647
2648                 view->zoom = zoom;
2649                 view->zoom_to_fit_flag = zoom_to_fit_flag;
2650
2651                 gl_view_update (view);
2652
2653                 g_signal_emit (G_OBJECT(view), signals[ZOOM_CHANGED], 0, zoom);
2654
2655         }
2656
2657         gl_debug (DEBUG_VIEW, "END");
2658
2659 }
2660
2661
2662 /*****************************************************************************/
2663 /* Get current zoom factor.                                                  */
2664 /*****************************************************************************/
2665 gdouble
2666 gl_view_get_zoom (glView *view)
2667 {
2668         gl_debug (DEBUG_VIEW, "");
2669
2670         g_return_val_if_fail (view && GL_IS_VIEW (view), 1.0);
2671
2672         return view->zoom;
2673 }
2674
2675 /*****************************************************************************/
2676 /* Is this the maximum zoom level.                                           */
2677 /*****************************************************************************/
2678 gboolean
2679 gl_view_is_zoom_max (glView *view)
2680 {
2681         gl_debug (DEBUG_VIEW, "");
2682
2683         g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
2684
2685         return view->zoom >= zooms[0];
2686 }
2687
2688 /*****************************************************************************/
2689 /* Is this the minimum zoom level.                                           */
2690 /*****************************************************************************/
2691 gboolean
2692 gl_view_is_zoom_min (glView *view)
2693 {
2694         gl_debug (DEBUG_VIEW, "");
2695
2696         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
2697
2698         return view->zoom <= zooms[N_ZOOMS-1];
2699 }
2700
2701 /*---------------------------------------------------------------------------*/
2702 /* PRIVATE.  Handle "selection-clear" signal.                                */
2703 /*---------------------------------------------------------------------------*/
2704 static void
2705 selection_clear_cb (GtkWidget         *widget,
2706                     GdkEventSelection *event,
2707                     glView            *view)
2708 {
2709         gl_debug (DEBUG_VIEW, "START");
2710
2711         g_return_if_fail (view && GL_IS_VIEW (view));
2712
2713         view->have_selection = FALSE;
2714         g_object_unref (view->selection_data);
2715         view->selection_data = NULL;
2716
2717         gl_debug (DEBUG_VIEW, "END");
2718 }
2719
2720 /*---------------------------------------------------------------------------*/
2721 /* PRIVATE.  Handle "selection-get" signal.                                  */
2722 /*---------------------------------------------------------------------------*/
2723 static void
2724 selection_get_cb (GtkWidget        *widget,
2725                   GtkSelectionData *selection_data,
2726                   guint             info,
2727                   guint             time,
2728                   glView           *view)
2729 {
2730         gchar            *buffer;
2731         glXMLLabelStatus  status;
2732
2733         gl_debug (DEBUG_VIEW, "START");
2734
2735         g_return_if_fail (view && GL_IS_VIEW (view));
2736
2737         if (view->have_selection) {
2738
2739                 buffer = gl_xml_label_save_buffer (view->selection_data,
2740                                                    &status);
2741                 gtk_selection_data_set (selection_data,
2742                                         GDK_SELECTION_TYPE_STRING, 8,
2743                                         (guchar *)buffer, strlen (buffer));
2744                 g_free (buffer);
2745         }
2746
2747         gl_debug (DEBUG_VIEW, "END");
2748 }
2749
2750 /*---------------------------------------------------------------------------*/
2751 /* PRIVATE.  Handle "selection-received" signal.  (Result of Paste)          */
2752 /*---------------------------------------------------------------------------*/
2753 static void
2754 selection_received_cb (GtkWidget        *widget,
2755                        GtkSelectionData *selection_data,
2756                        guint             time,
2757                        glView           *view)
2758 {
2759         glLabel          *label = NULL;
2760         glXMLLabelStatus  status;
2761         GList            *p, *p_next;
2762         glLabelObject    *object, *newobject;
2763         glViewObject     *view_object;
2764
2765         gl_debug (DEBUG_VIEW, "START");
2766
2767         g_return_if_fail (view && GL_IS_VIEW (view));
2768
2769         if (selection_data->length < 0) {
2770                 return;
2771         }
2772         if (selection_data->type != GDK_SELECTION_TYPE_STRING) {
2773                 return;
2774         }
2775
2776         gl_view_unselect_all (view);
2777
2778         label = gl_xml_label_open_buffer ((gchar *)selection_data->data, &status);
2779         for (p = label->objects; p != NULL; p = p_next) {
2780                 p_next = p->next;
2781
2782                 object = (glLabelObject *) p->data;
2783                 newobject = gl_label_object_dup (object, view->label);
2784
2785                 gl_debug (DEBUG_VIEW, "object pasted");
2786
2787                 if (GL_IS_LABEL_BOX (newobject)) {
2788                         view_object = gl_view_box_new (GL_LABEL_BOX(newobject),
2789                                                        view);
2790                 } else if (GL_IS_LABEL_ELLIPSE (newobject)) {
2791                         view_object = gl_view_ellipse_new (GL_LABEL_ELLIPSE(newobject),
2792                                                            view);
2793                 } else if (GL_IS_LABEL_LINE (newobject)) {
2794                         view_object = gl_view_line_new (GL_LABEL_LINE(newobject),
2795                                                         view);
2796                 } else if (GL_IS_LABEL_IMAGE (newobject)) {
2797                         view_object = gl_view_image_new (GL_LABEL_IMAGE(newobject),
2798                                                          view);
2799                 } else if (GL_IS_LABEL_TEXT (newobject)) {
2800                         view_object = gl_view_text_new (GL_LABEL_TEXT(newobject),
2801                                                         view);
2802                 } else if (GL_IS_LABEL_BARCODE (newobject)) {
2803                         view_object = gl_view_barcode_new (GL_LABEL_BARCODE(newobject),
2804                                                            view);
2805                 } else {
2806                         /* Should not happen! */
2807                         view_object = NULL;
2808                         g_message ("Invalid label object type.");
2809                 }
2810                 gl_view_select_object (view, view_object);
2811         }
2812         g_object_unref (label);
2813
2814         gl_debug (DEBUG_VIEW, "END");
2815 }
2816
2817 /****************************************************************************/
2818 /* Set default font family.                                                 */
2819 /****************************************************************************/
2820 void
2821 gl_view_set_default_font_family (glView      *view,
2822                                  const gchar *font_family)
2823 {
2824         gl_debug (DEBUG_VIEW, "START");
2825
2826         g_return_if_fail (view && GL_IS_VIEW (view));
2827
2828         if (view->default_font_family) {
2829                 g_free (view->default_font_family);
2830         }
2831         view->default_font_family = g_strdup (font_family);
2832
2833         gl_debug (DEBUG_VIEW, "END");
2834 }
2835
2836
2837 /****************************************************************************/
2838 /* Set default font size.                                                   */
2839 /****************************************************************************/
2840 void
2841 gl_view_set_default_font_size (glView  *view,
2842                                gdouble  font_size)
2843 {
2844         gl_debug (DEBUG_VIEW, "START");
2845
2846         g_return_if_fail (view && GL_IS_VIEW (view));
2847
2848         view->default_font_size = font_size;
2849
2850         gl_debug (DEBUG_VIEW, "END");
2851 }
2852
2853
2854 /****************************************************************************/
2855 /* Set default font weight.                                                 */
2856 /****************************************************************************/
2857 void
2858 gl_view_set_default_font_weight (glView      *view,
2859                                  PangoWeight  font_weight)
2860 {
2861         gl_debug (DEBUG_VIEW, "START");
2862
2863         g_return_if_fail (view && GL_IS_VIEW (view));
2864
2865         view->default_font_weight = font_weight;
2866
2867         gl_debug (DEBUG_VIEW, "END");
2868 }
2869
2870
2871 /****************************************************************************/
2872 /* Set default font italic flag.                                            */
2873 /****************************************************************************/
2874 void
2875 gl_view_set_default_font_italic_flag (glView   *view,
2876                                       gboolean  font_italic_flag)
2877 {
2878         gl_debug (DEBUG_VIEW, "START");
2879
2880         g_return_if_fail (view && GL_IS_VIEW (view));
2881
2882         view->default_font_italic_flag = font_italic_flag;
2883
2884         gl_debug (DEBUG_VIEW, "END");
2885 }
2886
2887
2888 /****************************************************************************/
2889 /* Set default text color.                                                  */
2890 /****************************************************************************/
2891 void
2892 gl_view_set_default_text_color (glView *view,
2893                                 guint   text_color)
2894 {
2895         gl_debug (DEBUG_VIEW, "START");
2896
2897         g_return_if_fail (view && GL_IS_VIEW (view));
2898
2899         view->default_text_color = text_color;
2900
2901         gl_debug (DEBUG_VIEW, "END");
2902 }
2903
2904
2905 /****************************************************************************/
2906 /* Set default text alignment.                                              */
2907 /****************************************************************************/
2908 void
2909 gl_view_set_default_text_alignment (glView           *view,
2910                                     PangoAlignment    text_alignment)
2911 {
2912         gl_debug (DEBUG_VIEW, "START");
2913
2914         g_return_if_fail (view && GL_IS_VIEW (view));
2915
2916         view->default_text_alignment = text_alignment;
2917         gl_debug (DEBUG_VIEW, "END");
2918 }
2919
2920 /****************************************************************************/
2921 /* Set default text line spacing.                                           */
2922 /****************************************************************************/
2923 void
2924 gl_view_set_default_text_line_spacing (glView  *view,
2925                                        gdouble  text_line_spacing)
2926 {
2927         gl_debug (DEBUG_VIEW, "START");
2928
2929         g_return_if_fail (view && GL_IS_VIEW (view));
2930
2931         view->default_text_line_spacing = text_line_spacing;
2932
2933         gl_debug (DEBUG_VIEW, "END");
2934 }
2935
2936
2937 /****************************************************************************/
2938 /* Set default line width.                                                  */
2939 /****************************************************************************/
2940 void
2941 gl_view_set_default_line_width (glView  *view,
2942                                 gdouble  line_width)
2943 {
2944         gl_debug (DEBUG_VIEW, "START");
2945
2946         g_return_if_fail (view && GL_IS_VIEW (view));
2947
2948         view->default_line_width = line_width;
2949
2950         gl_debug (DEBUG_VIEW, "END");
2951 }
2952
2953
2954 /****************************************************************************/
2955 /* Set default line color.                                                  */
2956 /****************************************************************************/
2957 void
2958 gl_view_set_default_line_color (glView *view,
2959                                 guint   line_color)
2960 {
2961         gl_debug (DEBUG_VIEW, "START");
2962
2963         g_return_if_fail (view && GL_IS_VIEW (view));
2964
2965         view->default_line_color = line_color;
2966
2967         gl_debug (DEBUG_VIEW, "END");
2968 }
2969
2970
2971 /****************************************************************************/
2972 /* Set default fill color.                                                  */
2973 /****************************************************************************/
2974 void
2975 gl_view_set_default_fill_color (glView *view,
2976                                 guint   fill_color)
2977 {
2978         gl_debug (DEBUG_VIEW, "START");
2979
2980         g_return_if_fail (view && GL_IS_VIEW (view));
2981
2982         view->default_fill_color = fill_color;
2983
2984         gl_debug (DEBUG_VIEW, "END");
2985 }
2986
2987
2988
2989 /****************************************************************************/
2990 /* Get default font family.                                                 */
2991 /****************************************************************************/
2992 gchar *
2993 gl_view_get_default_font_family (glView *view)
2994 {
2995         gl_debug (DEBUG_VIEW, "START");
2996
2997         g_return_val_if_fail (view && GL_IS_VIEW (view), NULL);
2998
2999         gl_debug (DEBUG_VIEW, "END");
3000
3001         return g_strdup (view->default_font_family);
3002 }
3003
3004
3005 /****************************************************************************/
3006 /* Get default font size.                                                   */
3007 /****************************************************************************/
3008 gdouble
3009 gl_view_get_default_font_size (glView *view)
3010 {
3011         gl_debug (DEBUG_VIEW, "START");
3012
3013         g_return_val_if_fail (view && GL_IS_VIEW (view), 12.0);
3014
3015         gl_debug (DEBUG_VIEW, "END");
3016
3017         return view->default_font_size;
3018 }
3019
3020
3021 /****************************************************************************/
3022 /* Get default font weight.                                                 */
3023 /****************************************************************************/
3024 PangoWeight
3025 gl_view_get_default_font_weight (glView *view)
3026 {
3027         gl_debug (DEBUG_VIEW, "START");
3028
3029         g_return_val_if_fail (view && GL_IS_VIEW (view), PANGO_WEIGHT_NORMAL);
3030
3031         gl_debug (DEBUG_VIEW, "END");
3032
3033         return view->default_font_weight;
3034 }
3035
3036
3037 /****************************************************************************/
3038 /* Get default font italic flag.                                            */
3039 /****************************************************************************/
3040 gboolean
3041 gl_view_get_default_font_italic_flag (glView *view)
3042 {
3043         gl_debug (DEBUG_VIEW, "START");
3044
3045         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
3046
3047         gl_debug (DEBUG_VIEW, "END");
3048
3049         return view->default_font_italic_flag;
3050 }
3051
3052
3053 /****************************************************************************/
3054 /* Get default text color.                                                  */
3055 /****************************************************************************/
3056 guint
3057 gl_view_get_default_text_color (glView *view)
3058 {
3059         gl_debug (DEBUG_VIEW, "START");
3060
3061         g_return_val_if_fail (view && GL_IS_VIEW (view), 0);
3062
3063         gl_debug (DEBUG_VIEW, "END");
3064
3065         return view->default_text_color;
3066 }
3067
3068
3069 /****************************************************************************/
3070 /* Get default text alignment.                                              */
3071 /****************************************************************************/
3072 PangoAlignment
3073 gl_view_get_default_text_alignment (glView *view)
3074 {
3075         gl_debug (DEBUG_VIEW, "START");
3076
3077         g_return_val_if_fail (view && GL_IS_VIEW (view), PANGO_ALIGN_LEFT);
3078
3079         gl_debug (DEBUG_VIEW, "END");
3080
3081         return view->default_text_alignment;
3082 }
3083
3084 /****************************************************************************/
3085 /* Get default text line spacing.                                           */
3086 /****************************************************************************/
3087 gdouble
3088 gl_view_get_default_text_line_spacing (glView *view)
3089 {
3090         gl_debug (DEBUG_VIEW, "START");
3091
3092         g_return_val_if_fail (view && GL_IS_VIEW (view), 1.0);
3093
3094         gl_debug (DEBUG_VIEW, "END");
3095
3096         return view->default_text_line_spacing;
3097 }
3098
3099
3100
3101 /****************************************************************************/
3102 /* Get default line width.                                                  */
3103 /****************************************************************************/
3104 gdouble
3105 gl_view_get_default_line_width (glView *view)
3106 {
3107         gl_debug (DEBUG_VIEW, "START");
3108
3109         g_return_val_if_fail (view && GL_IS_VIEW (view), 1.0);
3110
3111         gl_debug (DEBUG_VIEW, "END");
3112
3113         return view->default_line_width;
3114 }
3115
3116
3117 /****************************************************************************/
3118 /* Get default line color.                                                  */
3119 /****************************************************************************/
3120 guint
3121 gl_view_get_default_line_color (glView *view)
3122 {
3123         gl_debug (DEBUG_VIEW, "START");
3124
3125         g_return_val_if_fail (view && GL_IS_VIEW (view), 0);
3126
3127         gl_debug (DEBUG_VIEW, "END");
3128
3129         return view->default_line_color;
3130 }
3131
3132
3133 /****************************************************************************/
3134 /* Get default fill color.                                                  */
3135 /****************************************************************************/
3136 guint
3137 gl_view_get_default_fill_color (glView *view)
3138 {
3139         gl_debug (DEBUG_VIEW, "START");
3140
3141         g_return_val_if_fail (view && GL_IS_VIEW (view), 0);
3142
3143         gl_debug (DEBUG_VIEW, "END");
3144
3145         return view->default_fill_color;
3146 }
3147
3148 /*---------------------------------------------------------------------------*/
3149 /* PRIVATE.  Focus in event handler.                                         */
3150 /*---------------------------------------------------------------------------*/
3151 static gboolean
3152 focus_in_event_cb (glView            *view,
3153                    GdkEventFocus     *event)
3154 {
3155         GTK_WIDGET_SET_FLAGS (GTK_WIDGET (view->canvas), GTK_HAS_FOCUS);
3156
3157         return FALSE;
3158 }
3159
3160 /*---------------------------------------------------------------------------*/
3161 /* PRIVATE.  Focus out event handler.                                        */
3162 /*---------------------------------------------------------------------------*/
3163 static gboolean
3164 focus_out_event_cb (glView            *view,
3165                     GdkEventFocus     *event)
3166 {
3167         GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (view->canvas), GTK_HAS_FOCUS);
3168
3169         return FALSE;
3170 }
3171
3172 /*---------------------------------------------------------------------------*/
3173 /* PRIVATE.  Enter notify event handler.                                     */
3174 /*---------------------------------------------------------------------------*/
3175 static gboolean
3176 enter_notify_event_cb (glView            *view,
3177                        GdkEventCrossing  *event)
3178 {
3179         gtk_widget_grab_focus(GTK_WIDGET (view->canvas));
3180
3181         return FALSE;
3182 }
3183
3184 /*---------------------------------------------------------------------------*/
3185 /* PRIVATE.  Leave notify event handler.                                     */
3186 /*---------------------------------------------------------------------------*/
3187 static gboolean
3188 leave_notify_event_cb (glView            *view,
3189                        GdkEventCrossing  *event)
3190 {
3191
3192         g_signal_emit (G_OBJECT(view), signals[POINTER_EXIT], 0);
3193
3194         return FALSE;
3195 }
3196
3197 /*---------------------------------------------------------------------------*/
3198 /* PRIVATE.  Motion notify event handler.                                    */
3199 /*---------------------------------------------------------------------------*/
3200 static gboolean
3201 motion_notify_event_cb (glView            *view,
3202                         GdkEventMotion    *event)
3203 {
3204         gboolean            return_value = FALSE;
3205         cairo_t            *cr;
3206         gdouble             scale;
3207         gdouble             x, y;
3208         GdkCursor          *cursor;
3209         glViewObjectHandle  handle;
3210
3211         cr = gdk_cairo_create (GTK_LAYOUT (view->canvas)->bin_window);
3212
3213         /*
3214          * Translate to label coordinates
3215          */
3216         scale = view->zoom * view->home_scale;
3217         cairo_scale (cr, scale, scale);
3218         cairo_translate (cr, view->x0, view->y0);
3219
3220         x = event->x;
3221         y = event->y;
3222         cairo_device_to_user (cr, &x, &y);
3223
3224         /*
3225          * Emit signal regardless of mode
3226          */
3227         g_signal_emit (G_OBJECT(view), signals[POINTER_MOVED], 0, x, y);
3228
3229         /*
3230          * Handle event as appropriate for mode
3231          */
3232         switch (view->mode)
3233         {
3234
3235         case GL_VIEW_MODE_ARROW:
3236                 switch (view->state)
3237                 {
3238
3239                 case GL_VIEW_IDLE:
3240                         if (view_handle_at (view, cr, event->x, event->y, &handle))
3241                         {
3242                                 cursor = gdk_cursor_new (GDK_CROSSHAIR);
3243                         }
3244                         else if (view_view_object_at (view, cr, event->x, event->y))
3245                         {
3246                                 cursor = gdk_cursor_new (GDK_FLEUR);
3247                         }
3248                         else
3249                         {
3250                                 cursor = gdk_cursor_new (GDK_LEFT_PTR);
3251                         }
3252                         gdk_window_set_cursor (view->canvas->window, cursor);
3253                         gdk_cursor_unref (cursor);
3254                         break;
3255
3256                 case GL_VIEW_ARROW_SELECT_REGION:
3257 #ifdef CLIP_UPDATES                                
3258                         gl_view_update_region (view, cr, &view->select_region);
3259 #endif
3260                         view->select_region.x2 = x;
3261                         view->select_region.y2 = y;
3262 #ifdef CLIP_UPDATES                                
3263                         gl_view_update_region (view, cr, &view->select_region);
3264 #else
3265                         gl_view_update (view);
3266 #endif
3267                         break;
3268
3269                 case GL_VIEW_ARROW_MOVE:
3270                         gl_view_move_selection (view,
3271                                                 (x - view->move_last_x),
3272                                                 (y - view->move_last_y));
3273                         view->move_last_x = x;
3274                         view->move_last_y = y;
3275                         break;
3276
3277                 case GL_VIEW_ARROW_RESIZE:
3278                         gl_view_object_resize_event (view->resize_object,
3279                                                      view->resize_handle,
3280                                                      view->resize_honor_aspect,
3281                                                      cr,
3282                                                      event->x,
3283                                                      event->y);
3284                         break;
3285
3286                 default:
3287                         g_message ("Invalid arrow state.");      /*Should not happen!*/
3288                 }
3289                 return_value = TRUE;
3290                 break;
3291
3292
3293         case GL_VIEW_MODE_OBJECT_CREATE:
3294                 if (view->state != GL_VIEW_IDLE)
3295                 {
3296                         switch (view->create_type)
3297                         {
3298                         case GL_LABEL_OBJECT_BOX:
3299                                 gl_view_box_create_motion_event (view, x, y);
3300                                 break;
3301                         case GL_LABEL_OBJECT_ELLIPSE:
3302                                 gl_view_ellipse_create_motion_event (view, x, y);
3303                                 break;
3304                         case GL_LABEL_OBJECT_LINE: 
3305                                 gl_view_line_create_motion_event (view, x, y);
3306                                 break;
3307                         case GL_LABEL_OBJECT_IMAGE:
3308                                 gl_view_image_create_motion_event (view, x, y);
3309                                 break;
3310                         case GL_LABEL_OBJECT_TEXT:
3311                                 gl_view_text_create_motion_event (view, x, y);
3312                                 break;
3313                         case GL_LABEL_OBJECT_BARCODE:
3314                                 gl_view_barcode_create_motion_event (view, x, y);
3315                                 break;
3316                         default:
3317                                 g_message ("Invalid create type.");   /*Should not happen!*/
3318                         }
3319                 }
3320                 break;
3321
3322
3323         default:
3324                 g_message ("Invalid view mode.");      /*Should not happen!*/
3325
3326         }
3327
3328         cairo_destroy (cr);
3329
3330         /*
3331          * FIXME: we re-establish grabs here if the grab has been lost.  We seem to be
3332          *        losing grabs when we emit signals that lead to the manipulation of
3333          *        the GtkUIManager.  Needs more investigation
3334          */
3335         if (view->grabbed_flag && !gdk_pointer_is_grabbed ())
3336         {
3337                 gdk_pointer_grab (GTK_LAYOUT (view->canvas)->bin_window,
3338                                   FALSE,
3339                                   (GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK),
3340                                   NULL,
3341                                   NULL,
3342                                   event->time);
3343         }
3344
3345         return return_value;
3346 }
3347
3348 /*---------------------------------------------------------------------------*/
3349 /* PRIVATE.  Button press event handler.                                     */
3350 /*---------------------------------------------------------------------------*/
3351 static gboolean
3352 button_press_event_cb (glView            *view,
3353                        GdkEventButton    *event)
3354 {
3355         gboolean            return_value = FALSE;
3356         cairo_t            *cr;
3357         gdouble             scale;
3358         gdouble             x, y;
3359         glViewObject       *view_object;
3360         glViewObjectHandle  handle;
3361
3362         cr = gdk_cairo_create (GTK_LAYOUT (view->canvas)->bin_window);
3363
3364         /*
3365          * Translate to label coordinates
3366          */
3367         scale = view->zoom * view->home_scale;
3368         cairo_scale (cr, scale, scale);
3369         cairo_translate (cr, view->x0, view->y0);
3370
3371         x = event->x;
3372         y = event->y;
3373         cairo_device_to_user (cr, &x, &y);
3374
3375         switch (event->button)
3376         {
3377
3378         case 1:
3379                 /*
3380                  * Handle event as appropriate for mode
3381                  */
3382                 switch (view->mode)
3383                 {
3384                 case GL_VIEW_MODE_ARROW:
3385                         if ((view_object = view_handle_at (view, cr, event->x, event->y, &handle)))
3386                         {
3387                                 view->resize_object = view_object;
3388                                 view->resize_handle = handle;
3389                                 view->resize_honor_aspect = event->state & GDK_CONTROL_MASK;
3390
3391                                 view->state = GL_VIEW_ARROW_RESIZE;
3392                         }
3393                         else if ((view_object = view_view_object_at (view, cr, event->x, event->y)))
3394                         {
3395                                 if (event->state & GDK_CONTROL_MASK)
3396                                 {
3397                                         if (gl_view_is_object_selected (view, view_object))
3398                                         {
3399                                                 /* Un-selecting a selected item */
3400                                                 gl_view_unselect_object (view, view_object);
3401                                         } else {
3402                                                 /* Add to current selection */
3403                                                 gl_view_select_object (view, view_object);
3404                                         }
3405                                 }
3406                                 else
3407                                 {
3408                                         if (!gl_view_is_object_selected (view, view_object))
3409                                         {
3410                                                 /* remove any selections before adding */
3411                                                 gl_view_unselect_all (view);
3412                                                 /* Add to current selection */
3413                                                 gl_view_select_object (view, view_object);
3414                                         }
3415                                 }
3416                                 view->move_last_x = x;
3417                                 view->move_last_y = y;
3418
3419                                 view->state = GL_VIEW_ARROW_MOVE;
3420                         }
3421                         else
3422                         {
3423                                 if (!(event->state & GDK_CONTROL_MASK))
3424                                 {
3425                                         gl_view_unselect_all (view);
3426                                 }
3427
3428                                 view->select_region_visible = TRUE;
3429                                 view->select_region.x1 = x;
3430                                 view->select_region.y1 = y;
3431                                 view->select_region.x2 = x;
3432                                 view->select_region.y2 = y;
3433
3434                                 view->state = GL_VIEW_ARROW_SELECT_REGION;
3435                         }
3436
3437
3438                         return_value = TRUE;
3439                         break;
3440
3441                 case GL_VIEW_MODE_OBJECT_CREATE:
3442                         switch (view->create_type)
3443                         {
3444                         case GL_LABEL_OBJECT_BOX:
3445                                 gl_view_box_create_button_press_event (view, x, y);
3446                                 break;
3447                         case GL_LABEL_OBJECT_ELLIPSE:
3448                                 gl_view_ellipse_create_button_press_event (view, x, y);
3449                                 break;
3450                         case GL_LABEL_OBJECT_LINE:
3451                                 gl_view_line_create_button_press_event (view, x, y);
3452                                 break;
3453                         case GL_LABEL_OBJECT_IMAGE:
3454                                 gl_view_image_create_button_press_event (view, x, y);
3455                                 break;
3456                         case GL_LABEL_OBJECT_TEXT:
3457                                 gl_view_text_create_button_press_event (view, x, y);
3458                                 break;
3459                         case GL_LABEL_OBJECT_BARCODE:
3460                                 gl_view_barcode_create_button_press_event (view, x, y);
3461                                 break;
3462                         default:
3463                                 g_message ("Invalid create type.");   /*Should not happen!*/
3464                         }
3465                         view->state = GL_VIEW_CREATE_DRAG;
3466                         return_value = TRUE;
3467                         break;
3468
3469                 default:
3470                         g_message ("Invalid view mode.");      /*Should not happen!*/
3471                 }
3472
3473                 view->grabbed_flag = TRUE;
3474                 gdk_pointer_grab (GTK_LAYOUT (view->canvas)->bin_window,
3475                                   FALSE,
3476                                   (GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK),
3477                                   NULL,
3478                                   NULL,
3479                                   event->time);
3480                 break;
3481
3482         case 3:
3483                 g_signal_emit (G_OBJECT (view),
3484                                signals[CONTEXT_MENU_ACTIVATE], 0,
3485                                event->button, event->time);
3486                 return_value = TRUE;
3487                 break;
3488
3489         }
3490
3491         cairo_destroy (cr);
3492
3493         return return_value;
3494 }
3495
3496 /*---------------------------------------------------------------------------*/
3497 /* PRIVATE.  Button release event handler.                                   */
3498 /*---------------------------------------------------------------------------*/
3499 static gboolean
3500 button_release_event_cb (glView            *view,
3501                          GdkEventButton    *event)
3502 {
3503         gboolean     return_value = FALSE;
3504         cairo_t     *cr;
3505         gdouble      scale;
3506         gdouble      x, y;
3507         GdkCursor   *cursor;
3508
3509         cr = gdk_cairo_create (GTK_LAYOUT (view->canvas)->bin_window);
3510
3511         /*
3512          * Translate to label coordinates
3513          */
3514         scale = view->zoom * view->home_scale;
3515         cairo_scale (cr, scale, scale);
3516         cairo_translate (cr, view->x0, view->y0);
3517
3518         x = event->x;
3519         y = event->y;
3520         cairo_device_to_user (cr, &x, &y);
3521
3522         switch (event->button)
3523         {
3524
3525         case 1:
3526                 view->grabbed_flag = FALSE;
3527                 gdk_pointer_ungrab (event->time);
3528                 /*
3529                  * Handle event as appropriate for mode
3530                  */
3531                 switch (view->mode)
3532                 {
3533                 case GL_VIEW_MODE_ARROW:
3534                         switch (view->state)
3535                         {
3536                         case GL_VIEW_ARROW_RESIZE:
3537                                 view->resize_object = NULL;
3538
3539                                 view->state = GL_VIEW_IDLE;
3540                                 break;
3541
3542                         case GL_VIEW_ARROW_SELECT_REGION:
3543 #ifdef CLIP_UPDATES                                
3544                                 gl_view_update_region (view, cr, &view->select_region);
3545 #else
3546                                 gl_view_update (view);
3547 #endif
3548
3549                                 view->select_region_visible = FALSE;
3550                                 view->select_region.x2 = x;
3551                                 view->select_region.y2 = y;
3552
3553                                 gl_view_select_region (view, &view->select_region);
3554
3555                                 view->state = GL_VIEW_IDLE;
3556                                 break;
3557
3558                         default:
3559                                 view->state = GL_VIEW_IDLE;
3560                                 break;
3561                                 
3562                         }
3563
3564                         return_value = TRUE;
3565                         break;
3566
3567
3568                 case GL_VIEW_MODE_OBJECT_CREATE:
3569                         switch (view->create_type)
3570                         {
3571                         case GL_LABEL_OBJECT_BOX:
3572                                 gl_view_box_create_button_release_event (view, x, y);
3573                                 break;
3574                         case GL_LABEL_OBJECT_ELLIPSE:
3575                                 gl_view_ellipse_create_button_release_event (view, x, y);
3576                                 break;
3577                         case GL_LABEL_OBJECT_LINE:
3578                                 gl_view_line_create_button_release_event (view, x, y);
3579                                 break;
3580                         case GL_LABEL_OBJECT_IMAGE:
3581                                 gl_view_image_create_button_release_event (view, x, y);
3582                                 break;
3583                         case GL_LABEL_OBJECT_TEXT:
3584                                 gl_view_text_create_button_release_event (view, x, y);
3585                                 break;
3586                         case GL_LABEL_OBJECT_BARCODE:
3587                                 gl_view_barcode_create_button_release_event (view, x, y);
3588                                 break;
3589                         default:
3590                                 g_message ("Invalid create type.");   /*Should not happen!*/
3591                         }
3592                         view->mode = GL_VIEW_MODE_ARROW;
3593                         view->state = GL_VIEW_IDLE;
3594                         cursor = gdk_cursor_new (GDK_LEFT_PTR);
3595                         gdk_window_set_cursor (view->canvas->window, cursor);
3596                         gdk_cursor_unref (cursor);
3597                         break;
3598
3599
3600                 default:
3601                         g_message ("Invalid view mode.");      /*Should not happen!*/
3602                 }
3603
3604         }
3605
3606         cairo_destroy (cr);
3607
3608         return return_value;
3609 }
3610
3611 /*---------------------------------------------------------------------------*/
3612 /* PRIVATE.  Key press event handler.                                        */
3613 /*---------------------------------------------------------------------------*/
3614 static gboolean
3615 key_press_event_cb (glView            *view,
3616                     GdkEventKey       *event)
3617 {
3618         GdkCursor *cursor;
3619
3620         gl_debug (DEBUG_VIEW, "");
3621
3622         if ( (view->mode == GL_VIEW_MODE_ARROW) &&
3623              (view->state == GL_VIEW_IDLE) )
3624         {
3625                 switch (event->keyval) {
3626
3627                 case GDK_Left:
3628                 case GDK_KP_Left:
3629                         gl_view_move_selection (view, -1.0 / (view->zoom), 0.0);
3630                         break;
3631                 case GDK_Up:
3632                 case GDK_KP_Up:
3633                         gl_view_move_selection (view, 0.0, -1.0 / (view->zoom));
3634                         break;
3635                 case GDK_Right:
3636                 case GDK_KP_Right:
3637                         gl_view_move_selection (view, 1.0 / (view->zoom), 0.0);
3638                         break;
3639                 case GDK_Down:
3640                 case GDK_KP_Down:
3641                         gl_view_move_selection (view, 0.0, 1.0 / (view->zoom));
3642                         break;
3643                 case GDK_Delete:
3644                 case GDK_KP_Delete:
3645                         gl_view_delete_selection (view);
3646                         cursor = gdk_cursor_new (GDK_LEFT_PTR);
3647                         gdk_window_set_cursor (GTK_WIDGET (view->canvas)->window
3648 , cursor);
3649                         gdk_cursor_unref (cursor);
3650                         break;
3651                 default:
3652                         return FALSE;
3653  
3654                }
3655         }
3656         return TRUE;    /* We handled this or we were dragging. */
3657 }
3658