]> git.sur5r.net Git - glabels/blob - glabels2/src/view.c
a9e7ceeb6cd26b5d9f9b8495e45e11b9df8af649
[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 lglTemplateFrame    *frame;
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                 frame = (lglTemplateFrame *)view->label->template->frames->data;
857
858                 gl_label_get_size (view->label, &w, &h);
859         
860                 if (frame->shape == LGL_TEMPLATE_FRAME_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 lglTemplateFrame    *frame;
906         GList                     *p;
907         lglTemplateMarkup         *markup;
908         gdouble                    width, height;
909
910         g_return_if_fail (view && GL_IS_VIEW (view));
911         g_return_if_fail (view->label && GL_IS_LABEL (view->label));
912
913         if (view->markup_visible)
914         {
915
916                 label      = view->label;
917                 frame = (lglTemplateFrame *)view->label->template->frames->data;
918
919                 cairo_save (cr);
920
921                 if (label->rotate_flag)
922                 {
923                         lgl_template_frame_get_size (frame, &width, &height);
924                         cairo_rotate (cr, -M_PI/2.0);
925                         cairo_translate (cr, -width, 0.0);
926                 }
927
928                 cairo_set_line_width (cr, MARKUP_LINE_WIDTH_PIXELS/(view->home_scale * view->zoom));
929                 cairo_set_source_rgb (cr, MARKUP_RGB_ARGS);
930
931                 for ( p=frame->all.markups; p != NULL; p=p->next )
932                 {
933                         markup = (lglTemplateMarkup *)p->data;
934
935                         gl_cairo_markup_path (cr, markup, label);
936
937                         cairo_stroke (cr);
938                 }
939
940                 cairo_restore (cr);
941         }
942
943 }
944
945 /*---------------------------------------------------------------------------*/
946 /* PRIVATE.  Draw objects layer.                                             */
947 /*---------------------------------------------------------------------------*/
948 static void
949 draw_objects_layer (glView  *view,
950                     cairo_t *cr)
951 {
952         gl_label_draw (view->label, cr, TRUE, NULL);
953 }
954
955 /*---------------------------------------------------------------------------*/
956 /* PRIVATE.  Draw foreground                                                 */
957 /*---------------------------------------------------------------------------*/
958 static void
959 draw_fg_layer (glView  *view,
960                cairo_t *cr)
961 {
962         g_return_if_fail (view && GL_IS_VIEW (view));
963         g_return_if_fail (view->label && GL_IS_LABEL (view->label));
964
965         gl_cairo_label_path (cr, view->label->template, view->label->rotate_flag, FALSE);
966
967         cairo_set_line_width (cr, OUTLINE_WIDTH_PIXELS/(view->home_scale * view->zoom));
968         cairo_set_source_rgb (cr, OUTLINE_RGB_ARGS);
969         cairo_stroke (cr);
970 }
971
972 /*---------------------------------------------------------------------------*/
973 /* PRIVATE.  Create highlight layer.                                         */
974 /*---------------------------------------------------------------------------*/
975 static void
976 draw_highlight_layer (glView  *view,
977                       cairo_t *cr)
978 {
979         GList            *p_obj;
980         glViewObject     *view_object;
981
982         g_return_if_fail (view && GL_IS_VIEW (view));
983
984         cairo_save (cr);
985
986         cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
987
988         for (p_obj = view->selected_object_list; p_obj != NULL; p_obj = p_obj->next)
989         {
990                 view_object = GL_VIEW_OBJECT (p_obj->data);
991
992                 gl_view_object_draw_handles (view_object, cr);
993         }
994
995         cairo_restore (cr);
996 }
997
998 /*---------------------------------------------------------------------------*/
999 /* PRIVATE.  Draw select region layer.                                       */
1000 /*---------------------------------------------------------------------------*/
1001 static void
1002 draw_select_region_layer (glView  *view,
1003                           cairo_t *cr)
1004 {
1005         gdouble x1, y1;
1006         gdouble w, h;
1007
1008         g_return_if_fail (view && GL_IS_VIEW (view));
1009
1010         if (view->select_region_visible)
1011         {
1012                 x1 = MIN (view->select_region.x1, view->select_region.x2);
1013                 y1 = MIN (view->select_region.y1, view->select_region.y2);
1014                 w  = fabs (view->select_region.x2 - view->select_region.x1);
1015                 h  = fabs (view->select_region.y2 - view->select_region.y1);
1016
1017                 cairo_save (cr);
1018
1019                 cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
1020
1021                 cairo_rectangle (cr, x1, y1, w, h);
1022
1023                 cairo_set_source_rgba (cr, SELECT_FILL_RGBA_ARGS);
1024                 cairo_fill_preserve (cr);
1025
1026                 cairo_set_line_width (cr, SELECT_LINE_WIDTH_PIXELS/(view->home_scale * view->zoom));
1027                 cairo_set_source_rgba (cr, SELECT_LINE_RGBA_ARGS);
1028                 cairo_stroke (cr);
1029
1030                 cairo_restore (cr);
1031         }
1032 }
1033
1034 /*****************************************************************************/
1035 /* Show grid.                                                                */
1036 /*****************************************************************************/
1037 void
1038 gl_view_show_grid (glView *view)
1039 {
1040         g_return_if_fail (view && GL_IS_VIEW (view));
1041
1042         view->grid_visible = TRUE;
1043         gl_view_update (view);
1044 }
1045
1046 /*****************************************************************************/
1047 /* Hide grid.                                                                */
1048 /*****************************************************************************/
1049 void
1050 gl_view_hide_grid (glView *view)
1051 {
1052         g_return_if_fail (view && GL_IS_VIEW (view));
1053
1054         view->grid_visible = FALSE;
1055         gl_view_update (view);
1056 }
1057
1058 /*****************************************************************************/
1059 /* Set grid spacing.                                                         */
1060 /*****************************************************************************/
1061 void
1062 gl_view_set_grid_spacing (glView  *view,
1063                           gdouble  spacing)
1064 {
1065         g_return_if_fail (view && GL_IS_VIEW (view));
1066
1067         view->grid_spacing = spacing;
1068         gl_view_update (view);
1069 }
1070
1071 /*****************************************************************************/
1072 /* Show markup.                                                              */
1073 /*****************************************************************************/
1074 void
1075 gl_view_show_markup (glView *view)
1076 {
1077         g_return_if_fail (view && GL_IS_VIEW (view));
1078
1079         view->markup_visible = TRUE;
1080         gl_view_update (view);
1081 }
1082
1083 /*****************************************************************************/
1084 /* Hide markup.                                                              */
1085 /*****************************************************************************/
1086 void
1087 gl_view_hide_markup (glView *view)
1088 {
1089         g_return_if_fail (view && GL_IS_VIEW (view));
1090
1091         view->markup_visible = FALSE;
1092         gl_view_update (view);
1093 }
1094
1095 /*****************************************************************************/
1096 /* Set arrow mode.                                                           */
1097 /*****************************************************************************/
1098 void
1099 gl_view_arrow_mode (glView *view)
1100 {
1101         GdkCursor *cursor;
1102
1103         gl_debug (DEBUG_VIEW, "START");
1104
1105         g_return_if_fail (view && GL_IS_VIEW (view));
1106
1107         cursor = gdk_cursor_new (GDK_LEFT_PTR);
1108         gdk_window_set_cursor (view->canvas->window, cursor);
1109         gdk_cursor_unref (cursor);
1110
1111         view->mode = GL_VIEW_MODE_ARROW;
1112         view->state = GL_VIEW_IDLE;
1113
1114         gl_debug (DEBUG_VIEW, "END");
1115 }
1116
1117 /*****************************************************************************/
1118 /* Set create text object mode.                                              */
1119 /*****************************************************************************/
1120 void
1121 gl_view_object_create_mode (glView            *view,
1122                             glLabelObjectType  type)
1123 {
1124         GdkCursor *cursor = NULL;
1125
1126         gl_debug (DEBUG_VIEW, "START");
1127
1128         g_return_if_fail (view && GL_IS_VIEW (view));
1129
1130         switch (type)
1131         {
1132         case GL_LABEL_OBJECT_BOX:
1133                 cursor = gl_view_box_get_create_cursor ();
1134                 break;
1135         case GL_LABEL_OBJECT_ELLIPSE:
1136                 cursor = gl_view_ellipse_get_create_cursor ();
1137                 break;
1138         case GL_LABEL_OBJECT_LINE:
1139                 cursor = gl_view_line_get_create_cursor ();
1140                 break;
1141         case GL_LABEL_OBJECT_IMAGE:
1142                 cursor = gl_view_image_get_create_cursor ();
1143                 break;
1144         case GL_LABEL_OBJECT_TEXT:
1145                 cursor = gl_view_text_get_create_cursor ();
1146                 break;
1147         case GL_LABEL_OBJECT_BARCODE:
1148                 cursor = gl_view_barcode_get_create_cursor ();
1149                 break;
1150         default:
1151                 g_message ("Invalid label object type.");/*Should not happen!*/
1152                 break;
1153         }
1154
1155         gdk_window_set_cursor (view->canvas->window, cursor);
1156         gdk_cursor_unref (cursor);
1157
1158         view->mode = GL_VIEW_MODE_OBJECT_CREATE;
1159         view->state = GL_VIEW_IDLE;
1160         view->create_type = type;
1161
1162         gl_debug (DEBUG_VIEW, "END");
1163 }
1164
1165 /*****************************************************************************/
1166 /* Select given object (adding to current selection).                        */
1167 /*****************************************************************************/
1168 void
1169 gl_view_select_object (glView       *view,
1170                        glViewObject *view_object)
1171 {
1172         gl_debug (DEBUG_VIEW, "START");
1173
1174         g_return_if_fail (view && GL_IS_VIEW (view));
1175
1176         select_object_real (view, view_object);
1177
1178         g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1179
1180         gl_debug (DEBUG_VIEW, "END");
1181 }
1182
1183 /*****************************************************************************/
1184 /* Unselect given object (removing from current selection).                  */
1185 /*****************************************************************************/
1186 void
1187 gl_view_unselect_object (glView       *view,
1188                          glViewObject *view_object)
1189 {
1190         gl_debug (DEBUG_VIEW, "START");
1191
1192         g_return_if_fail (view && GL_IS_VIEW (view));
1193
1194         unselect_object_real (view, view_object);
1195
1196         g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1197
1198         gl_debug (DEBUG_VIEW, "END");
1199 }
1200
1201 /*****************************************************************************/
1202 /* Select all items.                                                         */
1203 /*****************************************************************************/
1204 void
1205 gl_view_select_all (glView *view)
1206 {
1207         GList *p, *p_next;
1208
1209         gl_debug (DEBUG_VIEW, "START");
1210
1211         g_return_if_fail (view && GL_IS_VIEW (view));
1212
1213         /* 1st unselect anything already selected. */
1214         for (p = view->selected_object_list; p != NULL; p = p_next) {
1215                 p_next = p->next;
1216                 unselect_object_real (view, GL_VIEW_OBJECT (p->data));
1217         }
1218
1219         /* Finally select all objects. */
1220         for (p = view->object_list; p != NULL; p = p->next) {
1221                 select_object_real (view, GL_VIEW_OBJECT (p->data));
1222         }
1223
1224         g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1225
1226         gl_debug (DEBUG_VIEW, "END");
1227 }
1228
1229 /*****************************************************************************/
1230 /* Remove all selections                                                     */
1231 /*****************************************************************************/
1232 void
1233 gl_view_unselect_all (glView *view)
1234 {
1235         GList *p;
1236         GList *p_next;
1237
1238         gl_debug (DEBUG_VIEW, "START");
1239
1240         g_return_if_fail (view && GL_IS_VIEW (view));
1241
1242         for (p = view->selected_object_list; p != NULL; p = p_next) {
1243                 p_next = p->next;
1244                 unselect_object_real (view, GL_VIEW_OBJECT (p->data));
1245         }
1246
1247         g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1248
1249         gl_debug (DEBUG_VIEW, "END");
1250 }
1251
1252 /*****************************************************************************/
1253 /* Select all objects within given rectangular region (adding to selection). */
1254 /*****************************************************************************/
1255 void
1256 gl_view_select_region (glView        *view,
1257                        glLabelRegion *region)
1258 {
1259         GList         *p;
1260         glViewObject  *view_object;
1261         glLabelObject *object;
1262         gdouble        r_x1, r_y1;
1263         gdouble        r_x2, r_y2;
1264         glLabelRegion  obj_extent;
1265
1266         gl_debug (DEBUG_VIEW, "START");
1267
1268         g_return_if_fail (view && GL_IS_VIEW (view));
1269
1270         r_x1 = MIN (region->x1, region->x2);
1271         r_y1 = MIN (region->y1, region->y2);
1272         r_x2 = MAX (region->x1, region->x2);
1273         r_y2 = MAX (region->y1, region->y2);
1274
1275         for (p = view->object_list; p != NULL; p = p->next)
1276         {
1277                 view_object = GL_VIEW_OBJECT(p->data);
1278                 if (!gl_view_is_object_selected (view, view_object))
1279                 {
1280
1281                         object = gl_view_object_get_object (view_object);
1282
1283                         gl_label_object_get_extent (object, &obj_extent);
1284                         if ((obj_extent.x1 >= r_x1) &&
1285                             (obj_extent.x2 <= r_x2) &&
1286                             (obj_extent.y1 >= r_y1) &&
1287                             (obj_extent.y2 <= r_y2))
1288                         {
1289                                 select_object_real (view, view_object);
1290                         }
1291
1292                 }
1293         }
1294
1295         g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1296
1297         gl_debug (DEBUG_VIEW, "END");
1298 }
1299
1300 /*---------------------------------------------------------------------------*/
1301 /* PRIVATE. Select an object.                                                */
1302 /*---------------------------------------------------------------------------*/
1303 static void
1304 select_object_real (glView       *view,
1305                     glViewObject *view_object)
1306 {
1307         gl_debug (DEBUG_VIEW, "START");
1308
1309         g_return_if_fail (view && GL_IS_VIEW (view));
1310         g_return_if_fail (GL_IS_VIEW_OBJECT (view_object));
1311
1312         if (!gl_view_is_object_selected (view, view_object)) {
1313                 view->selected_object_list =
1314                     g_list_append (view->selected_object_list, view_object);
1315         }
1316         gtk_widget_grab_focus (GTK_WIDGET (view->canvas));
1317
1318         gl_view_update (view);
1319
1320         gl_debug (DEBUG_VIEW, "END");
1321 }
1322
1323 /*---------------------------------------------------------------------------*/
1324 /* PRIVATE.  Un-select object.                                               */
1325 /*---------------------------------------------------------------------------*/
1326 static void
1327 unselect_object_real (glView       *view,
1328                       glViewObject *view_object)
1329 {
1330         gl_debug (DEBUG_VIEW, "START");
1331
1332         g_return_if_fail (view && GL_IS_VIEW (view));
1333         g_return_if_fail (GL_IS_VIEW_OBJECT (view_object));
1334
1335         view->selected_object_list =
1336             g_list_remove (view->selected_object_list, view_object);
1337
1338         gl_view_update (view);
1339
1340         gl_debug (DEBUG_VIEW, "END");
1341 }
1342
1343 /*---------------------------------------------------------------------------*/
1344 /* PRIVATE. Return object at (x,y).                                          */
1345 /*---------------------------------------------------------------------------*/
1346 static glViewObject *
1347 view_view_object_at (glView  *view,
1348                      cairo_t *cr,
1349                      gdouble  x,
1350                      gdouble  y)
1351 {
1352         GList            *p_obj;
1353         glViewObject     *view_object;
1354
1355         g_return_val_if_fail (view && GL_IS_VIEW (view), NULL);
1356
1357         for (p_obj = g_list_last (view->object_list); p_obj != NULL; p_obj = p_obj->prev)
1358         {
1359
1360                 view_object = GL_VIEW_OBJECT (p_obj->data);
1361
1362                 if (gl_view_object_at (view_object, cr, x, y))
1363                 {
1364                         return view_object;
1365                 }
1366
1367         }
1368
1369         return NULL;
1370 }
1371
1372 /*---------------------------------------------------------------------------*/
1373 /* PRIVATE. Return object handle at (x,y).                                   */
1374 /*---------------------------------------------------------------------------*/
1375 static glViewObject *
1376 view_handle_at (glView             *view,
1377                 cairo_t            *cr,
1378                 gdouble             x,
1379                 gdouble             y,
1380                 glViewObjectHandle *handle)
1381 {
1382         GList            *p_obj;
1383         glViewObject     *view_object;
1384
1385         g_return_val_if_fail (view && GL_IS_VIEW (view), NULL);
1386
1387         for (p_obj = g_list_last (view->selected_object_list); p_obj != NULL; p_obj = p_obj->prev)
1388         {
1389
1390                 view_object = GL_VIEW_OBJECT (p_obj->data);
1391
1392                 if ((*handle = gl_view_object_handle_at (view_object, cr, x, y)))
1393                 {
1394                         return view_object;
1395                 }
1396
1397         }
1398
1399         return NULL;
1400 }
1401
1402 /*****************************************************************************/
1403 /* Is the object in our current selection?                                   */
1404 /*****************************************************************************/
1405 gboolean
1406 gl_view_is_object_selected (glView       *view,
1407                             glViewObject *view_object)
1408 {
1409         gl_debug (DEBUG_VIEW, "");
1410
1411         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
1412         g_return_val_if_fail (GL_IS_VIEW_OBJECT (view_object), FALSE);
1413
1414         if (g_list_find (view->selected_object_list, view_object) == NULL) {
1415                 return FALSE;
1416         }
1417         return TRUE;
1418 }
1419
1420 /*****************************************************************************/
1421 /* Is our current selection empty?                                           */
1422 /*****************************************************************************/
1423 gboolean
1424 gl_view_is_selection_empty (glView *view)
1425 {
1426         gl_debug (DEBUG_VIEW, "");
1427
1428         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
1429
1430         if (view->selected_object_list == NULL) {
1431                 return TRUE;
1432         } else {
1433                 return FALSE;
1434         }
1435 }
1436
1437 /*****************************************************************************/
1438 /* Is our current selection atomic?  I.e. only one item selected.            */
1439 /*****************************************************************************/
1440 gboolean
1441 gl_view_is_selection_atomic (glView *view)
1442 {
1443         gl_debug (DEBUG_VIEW, "");
1444
1445         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
1446
1447         if (view->selected_object_list == NULL)
1448                 return FALSE;
1449         if (view->selected_object_list->next == NULL)
1450                 return TRUE;
1451         return FALSE;
1452 }
1453
1454 /*****************************************************************************/
1455 /* Delete selected objects. (Bypass clipboard)                               */
1456 /*****************************************************************************/
1457 void
1458 gl_view_delete_selection (glView *view)
1459 {
1460         GList         *object_list;
1461         GList         *p;
1462         GList         *p_next;
1463         glViewObject  *view_object;
1464         glLabelObject *object;
1465
1466         gl_debug (DEBUG_VIEW, "START");
1467
1468         g_return_if_fail (view && GL_IS_VIEW (view));
1469
1470         object_list = view->selected_object_list;
1471         view->selected_object_list = NULL;
1472         g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1473
1474         for (p = object_list; p != NULL; p = p_next) {
1475                 p_next = p->next;
1476                 view_object = GL_VIEW_OBJECT (p->data);
1477                 object = gl_view_object_get_object (view_object);
1478                 gl_label_object_remove (object);
1479         }
1480
1481         g_list_free (object_list);
1482
1483         gl_debug (DEBUG_VIEW, "END");
1484 }
1485
1486 /*****************************************************************************/
1487 /* Get object property editor of first selected object.                      */
1488 /*****************************************************************************/
1489 GtkWidget *
1490 gl_view_get_editor (glView *view)
1491 {
1492         glViewObject *view_object;
1493         GtkWidget    *editor = NULL;
1494
1495         gl_debug (DEBUG_VIEW, "START");
1496
1497         g_return_val_if_fail (view && GL_IS_VIEW (view), NULL);
1498
1499         if (!gl_view_is_selection_empty (view)) {
1500
1501                 view_object = GL_VIEW_OBJECT(view->selected_object_list->data);
1502                 editor = gl_view_object_get_editor (view_object);
1503
1504         }
1505
1506         gl_debug (DEBUG_VIEW, "END");
1507
1508         return editor;
1509 }
1510
1511 /*****************************************************************************/
1512 /* Raise selected items to top.                                              */
1513 /*****************************************************************************/
1514 void
1515 gl_view_raise_selection (glView *view)
1516 {
1517         GList         *p;
1518         glViewObject  *view_object;
1519         glLabelObject *object;
1520
1521         gl_debug (DEBUG_VIEW, "START");
1522
1523         g_return_if_fail (view && GL_IS_VIEW (view));
1524
1525         for (p = view->selected_object_list; p != NULL; p = p->next) {
1526                 view_object = GL_VIEW_OBJECT (p->data);
1527                 object = gl_view_object_get_object (view_object);
1528                 gl_label_object_raise_to_top (object);
1529         }
1530
1531         gl_debug (DEBUG_VIEW, "END");
1532 }
1533
1534 /*****************************************************************************/
1535 /* Lower selected items to bottom.                                           */
1536 /*****************************************************************************/
1537 void
1538 gl_view_lower_selection (glView *view)
1539 {
1540         GList         *p;
1541         glViewObject  *view_object;
1542         glLabelObject *object;
1543
1544         gl_debug (DEBUG_VIEW, "START");
1545
1546         g_return_if_fail (view && GL_IS_VIEW (view));
1547
1548         for (p = view->selected_object_list; p != NULL; p = p->next) {
1549                 view_object = GL_VIEW_OBJECT (p->data);
1550                 object = gl_view_object_get_object (view_object);
1551                 gl_label_object_lower_to_bottom (object);
1552         }
1553
1554         gl_debug (DEBUG_VIEW, "END");
1555 }
1556
1557 /*****************************************************************************/
1558 /* Rotate selected objects by given angle.                                   */
1559 /*****************************************************************************/
1560 void
1561 gl_view_rotate_selection (glView *view,
1562                           gdouble theta_degs)
1563 {
1564         GList         *p;
1565         glViewObject  *view_object;
1566         glLabelObject *object;
1567
1568         gl_debug (DEBUG_VIEW, "START");
1569
1570         g_return_if_fail (view && GL_IS_VIEW (view));
1571
1572         for (p = view->selected_object_list; p != NULL; p = p->next) {
1573                 view_object = GL_VIEW_OBJECT (p->data);
1574                 object = gl_view_object_get_object (view_object);
1575                 gl_label_object_rotate (object, theta_degs);
1576         }
1577
1578         gl_debug (DEBUG_VIEW, "END");
1579 }
1580
1581 /*****************************************************************************/
1582 /* Rotate selected objects 90 degrees left.                                  */
1583 /*****************************************************************************/
1584 void
1585 gl_view_rotate_selection_left (glView *view)
1586 {
1587         GList         *p;
1588         glViewObject  *view_object;
1589         glLabelObject *object;
1590
1591         gl_debug (DEBUG_VIEW, "START");
1592
1593         g_return_if_fail (view && GL_IS_VIEW (view));
1594
1595         for (p = view->selected_object_list; p != NULL; p = p->next) {
1596                 view_object = GL_VIEW_OBJECT (p->data);
1597                 object = gl_view_object_get_object (view_object);
1598                 gl_label_object_rotate (object, -90.0);
1599         }
1600
1601         gl_debug (DEBUG_VIEW, "END");
1602 }
1603
1604 /*****************************************************************************/
1605 /* Rotate selected objects 90 degrees right.                                 */
1606 /*****************************************************************************/
1607 void
1608 gl_view_rotate_selection_right (glView *view)
1609 {
1610         GList         *p;
1611         glViewObject  *view_object;
1612         glLabelObject *object;
1613
1614         gl_debug (DEBUG_VIEW, "START");
1615
1616         g_return_if_fail (view && GL_IS_VIEW (view));
1617
1618         for (p = view->selected_object_list; p != NULL; p = p->next) {
1619                 view_object = GL_VIEW_OBJECT (p->data);
1620                 object = gl_view_object_get_object (view_object);
1621                 gl_label_object_rotate (object, 90.0);
1622         }
1623
1624         gl_debug (DEBUG_VIEW, "END");
1625 }
1626
1627 /*****************************************************************************/
1628 /* Flip selected objects horizontally.                                       */
1629 /*****************************************************************************/
1630 void
1631 gl_view_flip_selection_horiz (glView *view)
1632 {
1633         GList         *p;
1634         glViewObject  *view_object;
1635         glLabelObject *object;
1636
1637         gl_debug (DEBUG_VIEW, "START");
1638
1639         g_return_if_fail (view && GL_IS_VIEW (view));
1640
1641         for (p = view->selected_object_list; p != NULL; p = p->next) {
1642                 view_object = GL_VIEW_OBJECT (p->data);
1643                 object = gl_view_object_get_object (view_object);
1644                 gl_label_object_flip_horiz (object);
1645         }
1646
1647         gl_debug (DEBUG_VIEW, "END");
1648 }
1649
1650 /*****************************************************************************/
1651 /* Flip selected objects vertically.                                         */
1652 /*****************************************************************************/
1653 void
1654 gl_view_flip_selection_vert (glView *view)
1655 {
1656         GList         *p;
1657         glViewObject  *view_object;
1658         glLabelObject *object;
1659
1660         gl_debug (DEBUG_VIEW, "START");
1661
1662         g_return_if_fail (view && GL_IS_VIEW (view));
1663
1664         for (p = view->selected_object_list; p != NULL; p = p->next) {
1665                 view_object = GL_VIEW_OBJECT (p->data);
1666                 object = gl_view_object_get_object (view_object);
1667                 gl_label_object_flip_vert (object);
1668         }
1669
1670         gl_debug (DEBUG_VIEW, "END");
1671 }
1672
1673 /*****************************************************************************/
1674 /* Align selected objects to left most edge.                                 */
1675 /*****************************************************************************/
1676 void
1677 gl_view_align_selection_left (glView *view)
1678 {
1679         GList         *p;
1680         glViewObject  *view_object;
1681         glLabelObject *object;
1682         gdouble        dx, x1_min;
1683         glLabelRegion  obj_extent;
1684
1685         gl_debug (DEBUG_VIEW, "START");
1686
1687         g_return_if_fail (view && GL_IS_VIEW (view));
1688
1689         g_return_if_fail (!gl_view_is_selection_empty (view) &&
1690                           !gl_view_is_selection_atomic (view));
1691
1692         /* find left most edge */
1693         p = view->selected_object_list;
1694         view_object = GL_VIEW_OBJECT (p->data);
1695         object = gl_view_object_get_object (view_object);
1696         gl_label_object_get_extent (object, &obj_extent);
1697         x1_min = obj_extent.x1;
1698         for (p = p->next; p != NULL; p = p->next)
1699         {
1700                 view_object = GL_VIEW_OBJECT (p->data);
1701                 object = gl_view_object_get_object (view_object);
1702                 gl_label_object_get_extent (object, &obj_extent);
1703                 if ( obj_extent.x1 < x1_min ) x1_min = obj_extent.x1;
1704         }
1705
1706         /* now adjust the object positions to line up the left edges */
1707         for (p = view->selected_object_list; p != NULL; p = p->next)
1708         {
1709                 view_object = GL_VIEW_OBJECT (p->data);
1710                 object = gl_view_object_get_object (view_object);
1711                 gl_label_object_get_extent (object, &obj_extent);
1712                 dx = x1_min - obj_extent.x1;
1713                 gl_label_object_set_position_relative (object, dx, 0.0);
1714         }
1715
1716         gl_debug (DEBUG_VIEW, "END");
1717 }
1718
1719
1720 /*****************************************************************************/
1721 /* Align selected objects to right most edge.                                */
1722 /*****************************************************************************/
1723 void
1724 gl_view_align_selection_right (glView *view)
1725 {
1726         GList         *p;
1727         glViewObject  *view_object;
1728         glLabelObject *object;
1729         gdouble        dx, x2_max;
1730         glLabelRegion  obj_extent;
1731
1732         gl_debug (DEBUG_VIEW, "START");
1733
1734         g_return_if_fail (view && GL_IS_VIEW (view));
1735
1736         g_return_if_fail (!gl_view_is_selection_empty (view) &&
1737                           !gl_view_is_selection_atomic (view));
1738
1739         /* find right most edge */
1740         p = view->selected_object_list;
1741         view_object = GL_VIEW_OBJECT (p->data);
1742         object = gl_view_object_get_object (view_object);
1743         gl_label_object_get_extent (object, &obj_extent);
1744         x2_max = obj_extent.x2;
1745         for (p = p->next; p != NULL; p = p->next)
1746         {
1747                 view_object = GL_VIEW_OBJECT (p->data);
1748                 object = gl_view_object_get_object (view_object);
1749                 gl_label_object_get_extent (object, &obj_extent);
1750                 if ( obj_extent.x2 > x2_max ) x2_max = obj_extent.x2;
1751         }
1752
1753         /* now adjust the object positions to line up the right edges */
1754         for (p = view->selected_object_list; p != NULL; p = p->next)
1755         {
1756                 view_object = GL_VIEW_OBJECT (p->data);
1757                 object = gl_view_object_get_object (view_object);
1758                 gl_label_object_get_extent (object, &obj_extent);
1759                 dx = x2_max - obj_extent.x2;
1760                 gl_label_object_set_position_relative (object, dx, 0.0);
1761         }
1762
1763         gl_debug (DEBUG_VIEW, "END");
1764 }
1765
1766 /*****************************************************************************/
1767 /* Align selected objects to horizontal center of objects.                   */
1768 /*****************************************************************************/
1769 void
1770 gl_view_align_selection_hcenter (glView *view)
1771 {
1772         GList         *p;
1773         glViewObject  *view_object;
1774         glLabelObject *object;
1775         gdouble        dx;
1776         gdouble        dxmin;
1777         gdouble        xsum, xavg;
1778         glLabelRegion  obj_extent;
1779         gdouble        xcenter;
1780         gint           n;
1781
1782         gl_debug (DEBUG_VIEW, "START");
1783
1784         g_return_if_fail (view && GL_IS_VIEW (view));
1785
1786         g_return_if_fail (!gl_view_is_selection_empty (view) &&
1787                           !gl_view_is_selection_atomic (view));
1788
1789         /* find average center of objects */
1790         xsum = 0.0;
1791         n = 0;
1792         for (p = view->selected_object_list; p != NULL; p = p->next)
1793         {
1794                 view_object = GL_VIEW_OBJECT (p->data);
1795                 object = gl_view_object_get_object (view_object);
1796                 gl_label_object_get_extent (object, &obj_extent);
1797                 xsum += (obj_extent.x1 + obj_extent.x2) / 2.0;
1798                 n++;
1799         }
1800         xavg = xsum / n;
1801
1802         /* find center of object closest to average center */
1803         p = view->selected_object_list;
1804         view_object = GL_VIEW_OBJECT (p->data);
1805         object = gl_view_object_get_object (view_object);
1806         gl_label_object_get_extent (object, &obj_extent);
1807         dxmin = fabs (xavg - (obj_extent.x1 + obj_extent.x2)/2.0);
1808         xcenter = (obj_extent.x1 + obj_extent.x2)/2.0;
1809         for (p = p->next; p != NULL; p = p->next)
1810         {
1811                 view_object = GL_VIEW_OBJECT (p->data);
1812                 object = gl_view_object_get_object (view_object);
1813                 gl_label_object_get_extent (object, &obj_extent);
1814                 dx = fabs (xavg - (obj_extent.x1 + obj_extent.x2)/2.0);
1815                 if ( dx < dxmin )
1816                 {
1817                         dxmin = dx;
1818                         xcenter = (obj_extent.x1 + obj_extent.x2)/2.0;
1819                 }
1820         }
1821
1822         /* now adjust the object positions to line up this center */
1823         for (p = view->selected_object_list; p != NULL; p = p->next) {
1824                 view_object = GL_VIEW_OBJECT (p->data);
1825                 object = gl_view_object_get_object (view_object);
1826                 gl_label_object_get_extent (object, &obj_extent);
1827                 dx = xcenter - (obj_extent.x1 + obj_extent.x2)/2.0;
1828                 gl_label_object_set_position_relative (object, dx, 0.0);
1829         }
1830
1831         gl_debug (DEBUG_VIEW, "END");
1832 }
1833
1834 /*****************************************************************************/
1835 /* Align selected objects to top most edge.                                  */
1836 /*****************************************************************************/
1837 void
1838 gl_view_align_selection_top (glView *view)
1839 {
1840         GList         *p;
1841         glViewObject  *view_object;
1842         glLabelObject *object;
1843         gdouble        dy, y1_min;
1844         glLabelRegion  obj_extent;
1845
1846         gl_debug (DEBUG_VIEW, "START");
1847
1848         g_return_if_fail (view && GL_IS_VIEW (view));
1849
1850         g_return_if_fail (!gl_view_is_selection_empty (view) &&
1851                           !gl_view_is_selection_atomic (view));
1852
1853         /* find top most edge */
1854         p = view->selected_object_list;
1855         view_object = GL_VIEW_OBJECT (p->data);
1856         object = gl_view_object_get_object (view_object);
1857         gl_label_object_get_extent (object, &obj_extent);
1858         y1_min = obj_extent.y1;
1859         for (p = p->next; p != NULL; p = p->next)
1860         {
1861                 view_object = GL_VIEW_OBJECT (p->data);
1862                 object = gl_view_object_get_object (view_object);
1863                 gl_label_object_get_extent (object, &obj_extent);
1864                 if ( obj_extent.y1 < y1_min ) y1_min = obj_extent.y1;
1865         }
1866
1867         /* now adjust the object positions to line up the top edges */
1868         for (p = view->selected_object_list; p != NULL; p = p->next)
1869         {
1870                 view_object = GL_VIEW_OBJECT (p->data);
1871                 object = gl_view_object_get_object (view_object);
1872                 gl_label_object_get_extent (object, &obj_extent);
1873                 dy = y1_min - obj_extent.y1;
1874                 gl_label_object_set_position_relative (object, 0.0, dy);
1875         }
1876
1877         gl_debug (DEBUG_VIEW, "END");
1878 }
1879
1880 /*****************************************************************************/
1881 /* Align selected objects to bottom most edge.                               */
1882 /*****************************************************************************/
1883 void
1884 gl_view_align_selection_bottom (glView *view)
1885 {
1886         GList         *p;
1887         glViewObject  *view_object;
1888         glLabelObject *object;
1889         gdouble        dy, y2_max;
1890         glLabelRegion  obj_extent;
1891
1892         gl_debug (DEBUG_VIEW, "START");
1893
1894         g_return_if_fail (view && GL_IS_VIEW (view));
1895
1896         g_return_if_fail (!gl_view_is_selection_empty (view) &&
1897                           !gl_view_is_selection_atomic (view));
1898
1899         /* find bottom most edge */
1900         p = view->selected_object_list;
1901         view_object = GL_VIEW_OBJECT (p->data);
1902         object = gl_view_object_get_object (view_object);
1903         gl_label_object_get_extent (object, &obj_extent);
1904         y2_max = obj_extent.y2;
1905         for (p = p->next; p != NULL; p = p->next)
1906         {
1907                 view_object = GL_VIEW_OBJECT (p->data);
1908                 object = gl_view_object_get_object (view_object);
1909                 gl_label_object_get_extent (object, &obj_extent);
1910                 if ( obj_extent.y2 > y2_max ) y2_max = obj_extent.y2;
1911         }
1912
1913         /* now adjust the object positions to line up the bottom edges */
1914         for (p = view->selected_object_list; p != NULL; p = p->next)
1915         {
1916                 view_object = GL_VIEW_OBJECT (p->data);
1917                 object = gl_view_object_get_object (view_object);
1918                 gl_label_object_get_extent (object, &obj_extent);
1919                 dy = y2_max - obj_extent.y2;
1920                 gl_label_object_set_position_relative (object, 0.0, dy);
1921         }
1922
1923         gl_debug (DEBUG_VIEW, "END");
1924 }
1925
1926 /*****************************************************************************/
1927 /* Align selected objects to viertical center of objects.                    */
1928 /*****************************************************************************/
1929 void
1930 gl_view_align_selection_vcenter (glView *view)
1931 {
1932         GList         *p;
1933         glViewObject  *view_object;
1934         glLabelObject *object;
1935         gdouble        dy;
1936         gdouble        dymin;
1937         gdouble        ysum, yavg;
1938         glLabelRegion  obj_extent;
1939         gdouble        ycenter;
1940         gint           n;
1941
1942         gl_debug (DEBUG_VIEW, "START");
1943
1944         g_return_if_fail (view && GL_IS_VIEW (view));
1945
1946         g_return_if_fail (!gl_view_is_selection_empty (view) &&
1947                           !gl_view_is_selection_atomic (view));
1948
1949         /* find average center of objects */
1950         ysum = 0.0;
1951         n = 0;
1952         for (p = view->selected_object_list; p != NULL; p = p->next)
1953         {
1954                 view_object = GL_VIEW_OBJECT (p->data);
1955                 object = gl_view_object_get_object (view_object);
1956                 gl_label_object_get_extent (object, &obj_extent);
1957                 ysum += (obj_extent.y1 + obj_extent.y2) / 2.0;
1958                 n++;
1959         }
1960         yavg = ysum / n;
1961
1962         /* find center of object closest to average center */
1963         p = view->selected_object_list;
1964         view_object = GL_VIEW_OBJECT (p->data);
1965         object = gl_view_object_get_object (view_object);
1966         gl_label_object_get_extent (object, &obj_extent);
1967         dymin = fabs (yavg - (obj_extent.y1 + obj_extent.y2)/2.0);
1968         ycenter = (obj_extent.y1 + obj_extent.y2)/2.0;
1969         for (p = p->next; p != NULL; p = p->next)
1970         {
1971                 view_object = GL_VIEW_OBJECT (p->data);
1972                 object = gl_view_object_get_object (view_object);
1973                 gl_label_object_get_extent (object, &obj_extent);
1974                 dy = fabs (yavg - (obj_extent.y1 + obj_extent.y2)/2.0);
1975                 if ( dy < dymin )
1976                 {
1977                         dymin = dy;
1978                         ycenter = (obj_extent.y1 + obj_extent.y2)/2.0;
1979                 }
1980         }
1981
1982         /* now adjust the object positions to line up this center */
1983         for (p = view->selected_object_list; p != NULL; p = p->next)
1984         {
1985                 view_object = GL_VIEW_OBJECT (p->data);
1986                 object = gl_view_object_get_object (view_object);
1987                 gl_label_object_get_extent (object, &obj_extent);
1988                 dy = ycenter - (obj_extent.y1 + obj_extent.y2)/2.0;
1989                 gl_label_object_set_position_relative (object, 0.0, dy);
1990         }
1991
1992         gl_debug (DEBUG_VIEW, "END");
1993 }
1994
1995 /*****************************************************************************/
1996 /* Center selected objects to in center of label.                            */
1997 /*****************************************************************************/
1998 void
1999 gl_view_center_selection_horiz (glView *view)
2000 {
2001         GList         *p;
2002         glViewObject  *view_object;
2003         glLabelObject *object;
2004         gdouble        dx;
2005         gdouble        x_label_center;
2006         gdouble        x_obj_center;
2007         glLabelRegion  obj_extent;
2008         gdouble        w, h;
2009
2010         gl_debug (DEBUG_VIEW, "START");
2011
2012         g_return_if_fail (view && GL_IS_VIEW (view));
2013
2014         g_return_if_fail (!gl_view_is_selection_empty (view));
2015
2016         gl_label_get_size (view->label, &w, &h);
2017         x_label_center = w / 2.0;
2018
2019         /* adjust the object positions */
2020         for (p = view->selected_object_list; p != NULL; p = p->next)
2021         {
2022                 view_object = GL_VIEW_OBJECT (p->data);
2023                 object = gl_view_object_get_object (view_object);
2024                 gl_label_object_get_extent (object, &obj_extent);
2025                 x_obj_center = (obj_extent.x1 + obj_extent.x2) / 2.0;
2026                 dx = x_label_center - x_obj_center;
2027                 gl_label_object_set_position_relative (object, dx, 0.0);
2028         }
2029
2030         gl_debug (DEBUG_VIEW, "END");
2031 }
2032
2033
2034 /*****************************************************************************/
2035 /* Center selected objects to in center of label.                            */
2036 /*****************************************************************************/
2037 void
2038 gl_view_center_selection_vert (glView *view)
2039 {
2040         GList         *p;
2041         glViewObject  *view_object;
2042         glLabelObject *object;
2043         gdouble        dy;
2044         gdouble        y_label_center;
2045         gdouble        y_obj_center;
2046         glLabelRegion  obj_extent;
2047         gdouble        w, h;
2048
2049         gl_debug (DEBUG_VIEW, "START");
2050
2051         g_return_if_fail (view && GL_IS_VIEW (view));
2052
2053         g_return_if_fail (!gl_view_is_selection_empty (view));
2054
2055         gl_label_get_size (view->label, &w, &h);
2056         y_label_center = h / 2.0;
2057
2058         /* adjust the object positions */
2059         for (p = view->selected_object_list; p != NULL; p = p->next)
2060         {
2061                 view_object = GL_VIEW_OBJECT (p->data);
2062                 object = gl_view_object_get_object (view_object);
2063                 gl_label_object_get_extent (object, &obj_extent);
2064                 y_obj_center = (obj_extent.y1 + obj_extent.y2) / 2.0;
2065                 dy = y_label_center - y_obj_center;
2066                 gl_label_object_set_position_relative (object, 0.0, dy);
2067         }
2068
2069         gl_debug (DEBUG_VIEW, "END");
2070 }
2071
2072
2073 /*****************************************************************************/
2074 /* Move selected objects                                                     */
2075 /*****************************************************************************/
2076 void
2077 gl_view_move_selection (glView  *view,
2078                         gdouble  dx,
2079                         gdouble  dy)
2080 {
2081         GList         *p;
2082         glLabelObject *object;
2083
2084         gl_debug (DEBUG_VIEW, "START");
2085
2086         g_return_if_fail (view && GL_IS_VIEW (view));
2087
2088         for (p = view->selected_object_list; p != NULL; p = p->next)
2089         {
2090
2091                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2092                 gl_label_object_set_position_relative (object, dx, dy);
2093
2094         }
2095
2096         gl_debug (DEBUG_VIEW, "END");
2097 }
2098
2099 /*****************************************************************************/
2100 /* Can text properties be set for selection?                                 */
2101 /*****************************************************************************/
2102 gboolean
2103 gl_view_can_selection_text (glView *view)
2104 {
2105         GList         *p;
2106         glLabelObject *object;
2107
2108         gl_debug (DEBUG_VIEW, "");
2109
2110         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
2111
2112         for (p = view->selected_object_list; p != NULL; p = p->next)
2113         {
2114
2115                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2116                 if (gl_label_object_can_text (object))
2117                 {
2118                         return TRUE;
2119                 }
2120
2121         }
2122
2123         return FALSE;
2124 }
2125
2126 /*****************************************************************************/
2127 /* Set font family for all text contained in selected objects.               */
2128 /*****************************************************************************/
2129 void
2130 gl_view_set_selection_font_family (glView      *view,
2131                                    const gchar *font_family)
2132 {
2133         GList         *p;
2134         glLabelObject *object;
2135
2136         gl_debug (DEBUG_VIEW, "START");
2137
2138         g_return_if_fail (view && GL_IS_VIEW (view));
2139
2140         for (p = view->selected_object_list; p != NULL; p = p->next) {
2141
2142                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2143                 gl_label_object_set_font_family (object, font_family);
2144
2145         }
2146
2147         gl_debug (DEBUG_VIEW, "END");
2148 }
2149
2150 /*****************************************************************************/
2151 /* Set font size for all text contained in selected objects.                 */
2152 /*****************************************************************************/
2153 void
2154 gl_view_set_selection_font_size (glView  *view,
2155                                  gdouble  font_size)
2156 {
2157         GList         *p;
2158         glLabelObject *object;
2159
2160         gl_debug (DEBUG_VIEW, "START");
2161
2162         g_return_if_fail (view && GL_IS_VIEW (view));
2163
2164         for (p = view->selected_object_list; p != NULL; p = p->next) {
2165
2166                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2167                 gl_label_object_set_font_size (object, font_size);
2168
2169         }
2170
2171         gl_debug (DEBUG_VIEW, "END");
2172 }
2173
2174 /*****************************************************************************/
2175 /* Set font weight for all text contained in selected objects.               */
2176 /*****************************************************************************/
2177 void
2178 gl_view_set_selection_font_weight (glView      *view,
2179                                    PangoWeight  font_weight)
2180 {
2181         GList         *p;
2182         glLabelObject *object;
2183
2184         gl_debug (DEBUG_VIEW, "START");
2185
2186         g_return_if_fail (view && GL_IS_VIEW (view));
2187
2188         for (p = view->selected_object_list; p != NULL; p = p->next) {
2189
2190                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2191                 gl_label_object_set_font_weight (object, font_weight);
2192
2193         }
2194
2195         gl_debug (DEBUG_VIEW, "END");
2196 }
2197
2198 /*****************************************************************************/
2199 /* Set font italic flag for all text contained in selected objects.          */
2200 /*****************************************************************************/
2201 void
2202 gl_view_set_selection_font_italic_flag (glView   *view,
2203                                         gboolean  font_italic_flag)
2204 {
2205         GList         *p;
2206         glLabelObject *object;
2207
2208         gl_debug (DEBUG_VIEW, "START");
2209
2210         g_return_if_fail (view && GL_IS_VIEW (view));
2211
2212         for (p = view->selected_object_list; p != NULL; p = p->next) {
2213
2214                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2215                 gl_label_object_set_font_italic_flag (object, font_italic_flag);
2216
2217         }
2218
2219         gl_debug (DEBUG_VIEW, "END");
2220 }
2221
2222 /*****************************************************************************/
2223 /* Set text alignment for all text contained in selected objects.            */
2224 /*****************************************************************************/
2225 void
2226 gl_view_set_selection_text_alignment (glView            *view,
2227                                       PangoAlignment     text_alignment)
2228 {
2229         GList         *p;
2230         glLabelObject *object;
2231
2232         gl_debug (DEBUG_VIEW, "START");
2233
2234         g_return_if_fail (view && GL_IS_VIEW (view));
2235
2236         for (p = view->selected_object_list; p != NULL; p = p->next) {
2237
2238                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2239                 gl_label_object_set_text_alignment (object, text_alignment);
2240
2241         }
2242
2243         gl_debug (DEBUG_VIEW, "END");
2244 }
2245
2246 /*****************************************************************************/
2247 /* Set text line spacing for all text contained in selected objects.         */
2248 /*****************************************************************************/
2249 void
2250 gl_view_set_selection_text_line_spacing (glView  *view,
2251                                          gdouble  text_line_spacing)
2252 {
2253         GList         *p;
2254         glLabelObject *object;
2255
2256         gl_debug (DEBUG_VIEW, "START");
2257
2258         g_return_if_fail (view && GL_IS_VIEW (view));
2259
2260         for (p = view->selected_object_list; p != NULL; p = p->next) {
2261
2262                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2263                 gl_label_object_set_text_line_spacing (object, text_line_spacing);
2264
2265         }
2266
2267         gl_debug (DEBUG_VIEW, "END");
2268 }
2269 /*****************************************************************************/
2270 /* Set text color for all text contained in selected objects.                */
2271 /*****************************************************************************/
2272 void
2273 gl_view_set_selection_text_color (glView      *view,
2274                                   glColorNode *text_color_node)
2275 {
2276         GList         *p;
2277         glLabelObject *object;
2278
2279         gl_debug (DEBUG_VIEW, "START");
2280
2281         g_return_if_fail (view && GL_IS_VIEW (view));
2282
2283         for (p = view->selected_object_list; p != NULL; p = p->next) {
2284
2285                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2286                 gl_label_object_set_text_color (object, text_color_node);
2287
2288         }
2289
2290         gl_debug (DEBUG_VIEW, "END");
2291 }
2292
2293 /*****************************************************************************/
2294 /* Can fill properties be set for selection?                                 */
2295 /*****************************************************************************/
2296 gboolean
2297 gl_view_can_selection_fill (glView *view)
2298 {
2299         GList         *p;
2300         glLabelObject *object;
2301
2302         gl_debug (DEBUG_VIEW, "");
2303
2304         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
2305
2306         for (p = view->selected_object_list; p != NULL; p = p->next) {
2307
2308                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2309                 if (gl_label_object_can_fill (object)) {
2310                         return TRUE;
2311                 }
2312
2313         }
2314
2315         return FALSE;
2316 }
2317
2318 /*****************************************************************************/
2319 /* Set fill color for all selected objects.                                  */
2320 /*****************************************************************************/
2321 void
2322 gl_view_set_selection_fill_color (glView      *view,
2323                                   glColorNode *fill_color_node)
2324 {
2325         GList         *p;
2326         glLabelObject *object;
2327
2328         gl_debug (DEBUG_VIEW, "START");
2329
2330         g_return_if_fail (view && GL_IS_VIEW (view));
2331
2332         for (p = view->selected_object_list; p != NULL; p = p->next) {
2333
2334                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2335                 gl_label_object_set_fill_color (object, fill_color_node);
2336
2337         }
2338
2339         gl_debug (DEBUG_VIEW, "END");
2340 }
2341
2342 /*****************************************************************************/
2343 /* Can line color properties be set for selection?                           */
2344 /*****************************************************************************/
2345 gboolean
2346 gl_view_can_selection_line_color (glView *view)
2347 {
2348         GList         *p;
2349         glLabelObject *object;
2350
2351         gl_debug (DEBUG_VIEW, "");
2352
2353         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
2354
2355         for (p = view->selected_object_list; p != NULL; p = p->next) {
2356
2357                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2358                 if (gl_label_object_can_line_color (object)) {
2359                         return TRUE;
2360                 }
2361
2362         }
2363
2364         return FALSE;
2365 }
2366
2367 /*****************************************************************************/
2368 /* Set line color for all selected objects.                                  */
2369 /*****************************************************************************/
2370 void
2371 gl_view_set_selection_line_color (glView      *view,
2372                                   glColorNode *line_color_node)
2373 {
2374         GList         *p;
2375         glLabelObject *object;
2376
2377         gl_debug (DEBUG_VIEW, "START");
2378
2379         g_return_if_fail (view && GL_IS_VIEW (view));
2380
2381         for (p = view->selected_object_list; p != NULL; p = p->next) {
2382
2383                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2384                 gl_label_object_set_line_color (object, line_color_node);
2385
2386         }
2387
2388         gl_debug (DEBUG_VIEW, "END");
2389 }
2390
2391 /*****************************************************************************/
2392 /* Can line width properties be set for selection?                           */
2393 /*****************************************************************************/
2394 gboolean
2395 gl_view_can_selection_line_width (glView *view)
2396 {
2397         GList         *p;
2398         glLabelObject *object;
2399
2400         gl_debug (DEBUG_VIEW, "");
2401
2402         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
2403
2404         for (p = view->selected_object_list; p != NULL; p = p->next) {
2405
2406                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2407                 if (gl_label_object_can_line_width (object)) {
2408                         return TRUE;
2409                 }
2410
2411         }
2412
2413         return FALSE;
2414 }
2415
2416 /*****************************************************************************/
2417 /* Set line width for all selected objects.                                  */
2418 /*****************************************************************************/
2419 void
2420 gl_view_set_selection_line_width (glView  *view,
2421                                   gdouble  line_width)
2422 {
2423         GList         *p;
2424         glLabelObject *object;
2425
2426         gl_debug (DEBUG_VIEW, "START");
2427
2428         g_return_if_fail (view && GL_IS_VIEW (view));
2429
2430         for (p = view->selected_object_list; p != NULL; p = p->next) {
2431
2432                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2433                 gl_label_object_set_line_width (object, line_width);
2434
2435         }
2436
2437         gl_debug (DEBUG_VIEW, "END");
2438 }
2439
2440 /*****************************************************************************/
2441 /* "Cut" selected items and place in clipboard selections.                   */
2442 /*****************************************************************************/
2443 void
2444 gl_view_cut (glView *view)
2445 {
2446         gl_debug (DEBUG_VIEW, "START");
2447
2448         g_return_if_fail (view && GL_IS_VIEW (view));
2449
2450         gl_view_copy (view);
2451         gl_view_delete_selection (view);
2452
2453         gl_debug (DEBUG_VIEW, "END");
2454 }
2455
2456 /*****************************************************************************/
2457 /* "Copy" selected items to clipboard selections.                            */
2458 /*****************************************************************************/
2459 void
2460 gl_view_copy (glView *view)
2461 {
2462         GList         *p;
2463         glViewObject  *view_object;
2464         glLabelObject *object;
2465
2466         gl_debug (DEBUG_VIEW, "START");
2467
2468         g_return_if_fail (view && GL_IS_VIEW (view));
2469
2470         if (view->selected_object_list) {
2471
2472                 if ( view->selection_data ) {
2473                         g_object_unref (view->selection_data);
2474                 }
2475                 view->selection_data = GL_LABEL(gl_label_new ());
2476                 gl_label_set_template (view->selection_data, view->label->template);
2477                 gl_label_set_rotate_flag (view->selection_data, view->label->rotate_flag);
2478
2479                 for (p = view->selected_object_list; p != NULL; p = p->next) {
2480
2481                         view_object = GL_VIEW_OBJECT (p->data);
2482                         object = gl_view_object_get_object (view_object);
2483
2484                         gl_label_object_dup (object, view->selection_data);
2485
2486                 }
2487
2488                 gtk_selection_owner_set (view->invisible,
2489                                          clipboard_atom, GDK_CURRENT_TIME);
2490                 view->have_selection = TRUE;
2491
2492         }
2493
2494         gl_debug (DEBUG_VIEW, "END");
2495 }
2496
2497 /*****************************************************************************/
2498 /* "Paste" from private clipboard selection.                                 */
2499 /*****************************************************************************/
2500 void
2501 gl_view_paste (glView *view)
2502 {
2503         gl_debug (DEBUG_VIEW, "START");
2504
2505         g_return_if_fail (view && GL_IS_VIEW (view));
2506
2507         gtk_selection_convert (GTK_WIDGET (view->invisible),
2508                                clipboard_atom, GDK_SELECTION_TYPE_STRING,
2509                                GDK_CURRENT_TIME);
2510
2511         gl_debug (DEBUG_VIEW, "END");
2512 }
2513
2514 /*****************************************************************************/
2515 /* Zoom in one "notch"                                                       */
2516 /*****************************************************************************/
2517 void
2518 gl_view_zoom_in (glView *view)
2519 {
2520         gint    i, i_min;
2521         gdouble dist, dist_min;
2522
2523         gl_debug (DEBUG_VIEW, "START");
2524
2525         g_return_if_fail (view && GL_IS_VIEW (view));
2526
2527         /* Find index of current scale (or best match) */
2528         i_min = 1;              /* start with 2nd largest scale */
2529         dist_min = fabs (zooms[1] - view->zoom);
2530         for (i = 2; i < N_ZOOMS; i++) {
2531                 dist = fabs (zooms[i] - view->zoom);
2532                 if (dist < dist_min) {
2533                         i_min = i;
2534                         dist_min = dist;
2535                 }
2536         }
2537
2538         /* zoom in one "notch" */
2539         i = MAX (0, i_min - 1);
2540         gl_debug (DEBUG_VIEW, "zoom[%d] = %g", i, zooms[i]);
2541         set_zoom_real (view, zooms[i], FALSE);
2542
2543         gl_debug (DEBUG_VIEW, "END");
2544 }
2545
2546 /*****************************************************************************/
2547 /* Zoom out one "notch"                                                      */
2548 /*****************************************************************************/
2549 void
2550 gl_view_zoom_out (glView *view)
2551 {
2552         gint    i, i_min;
2553         gdouble dist, dist_min;
2554
2555         gl_debug (DEBUG_VIEW, "START");
2556
2557         g_return_if_fail (view && GL_IS_VIEW (view));
2558
2559         /* Find index of current scale (or best match) */
2560         i_min = 0;              /* start with largest scale */
2561         dist_min = fabs (zooms[0] - view->zoom);
2562         for (i = 1; i < N_ZOOMS; i++) {
2563                 dist = fabs (zooms[i] - view->zoom);
2564                 if (dist < dist_min) {
2565                         i_min = i;
2566                         dist_min = dist;
2567                 }
2568         }
2569
2570         /* zoom out one "notch" */
2571         if (i_min >= N_ZOOMS)
2572                 return;
2573         i = i_min + 1;
2574         if (i >= N_ZOOMS)
2575                 return;
2576         set_zoom_real (view, zooms[i], FALSE);
2577
2578         gl_debug (DEBUG_VIEW, "END");
2579 }
2580
2581 /*****************************************************************************/
2582 /* Set zoom to best fit.                                                     */
2583 /*****************************************************************************/
2584 void
2585 gl_view_zoom_to_fit (glView *view)
2586 {
2587         gint    w_view, h_view;
2588         gdouble w_label, h_label;
2589         gdouble x_scale, y_scale, scale;
2590
2591         gl_debug (DEBUG_VIEW, "");
2592
2593         if ( ! GTK_WIDGET_VISIBLE(view)) {
2594                 set_zoom_real (view, 1.0, TRUE);
2595                 return;
2596         }
2597
2598         w_view = GTK_WIDGET(view)->allocation.width;
2599         h_view = GTK_WIDGET(view)->allocation.height;
2600
2601         gl_label_get_size (GL_LABEL(view->label), &w_label, &h_label);
2602
2603         gl_debug (DEBUG_VIEW, "View size: %d, %d", w_view, h_view);
2604         gl_debug (DEBUG_VIEW, "Label size: %g, %g", w_label, h_label);
2605
2606         /* Calculate best scale */
2607         x_scale = (double)(w_view - ZOOMTOFIT_PAD) / w_label;
2608         y_scale = (double)(h_view - ZOOMTOFIT_PAD) / h_label;
2609         scale = MIN (x_scale, y_scale);
2610         gl_debug (DEBUG_VIEW, "Candidate zooms: %g, %g => %g", x_scale, y_scale, scale);
2611
2612         /* Limit */
2613         gl_debug (DEBUG_VIEW, "Scale: %g", scale);
2614         scale = MIN (scale, zooms[0]*view->home_scale);
2615         scale = MAX (scale, zooms[N_ZOOMS-1]*view->home_scale);
2616         gl_debug (DEBUG_VIEW, "Limitted scale: %g", scale);
2617
2618         set_zoom_real (view, scale/view->home_scale, TRUE);
2619 }
2620
2621 /*****************************************************************************/
2622 /* Set current zoom factor to explicit value.                                */
2623 /*****************************************************************************/
2624 void
2625 gl_view_set_zoom (glView  *view,
2626                   gdouble  zoom)
2627 {
2628         gl_debug (DEBUG_VIEW, "START");
2629
2630         set_zoom_real (view, zoom, FALSE);
2631
2632         gl_debug (DEBUG_VIEW, "END");
2633 }
2634
2635 /*---------------------------------------------------------------------------*/
2636 /* PRIVATE.  Set canvas scale.                                               */
2637 /*---------------------------------------------------------------------------*/
2638 static void
2639 set_zoom_real (glView   *view,
2640                gdouble   zoom,
2641                gboolean  zoom_to_fit_flag)
2642 {
2643         gl_debug (DEBUG_VIEW, "START");
2644
2645         g_return_if_fail (view && GL_IS_VIEW (view));
2646         g_return_if_fail (zoom > 0.0);
2647
2648         /* Limit, if needed */
2649         gl_debug (DEBUG_VIEW, "Zoom requested: %g", zoom);
2650         zoom = MIN (zoom, zooms[0]);
2651         zoom = MAX (zoom, zooms[N_ZOOMS-1]);
2652         gl_debug (DEBUG_VIEW, "Limitted zoom: %g", zoom);
2653
2654         if ( zoom != view->zoom ) {
2655
2656                 view->zoom = zoom;
2657                 view->zoom_to_fit_flag = zoom_to_fit_flag;
2658
2659                 gl_view_update (view);
2660
2661                 g_signal_emit (G_OBJECT(view), signals[ZOOM_CHANGED], 0, zoom);
2662
2663         }
2664
2665         gl_debug (DEBUG_VIEW, "END");
2666
2667 }
2668
2669
2670 /*****************************************************************************/
2671 /* Get current zoom factor.                                                  */
2672 /*****************************************************************************/
2673 gdouble
2674 gl_view_get_zoom (glView *view)
2675 {
2676         gl_debug (DEBUG_VIEW, "");
2677
2678         g_return_val_if_fail (view && GL_IS_VIEW (view), 1.0);
2679
2680         return view->zoom;
2681 }
2682
2683 /*****************************************************************************/
2684 /* Is this the maximum zoom level.                                           */
2685 /*****************************************************************************/
2686 gboolean
2687 gl_view_is_zoom_max (glView *view)
2688 {
2689         gl_debug (DEBUG_VIEW, "");
2690
2691         g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
2692
2693         return view->zoom >= zooms[0];
2694 }
2695
2696 /*****************************************************************************/
2697 /* Is this the minimum zoom level.                                           */
2698 /*****************************************************************************/
2699 gboolean
2700 gl_view_is_zoom_min (glView *view)
2701 {
2702         gl_debug (DEBUG_VIEW, "");
2703
2704         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
2705
2706         return view->zoom <= zooms[N_ZOOMS-1];
2707 }
2708
2709 /*---------------------------------------------------------------------------*/
2710 /* PRIVATE.  Handle "selection-clear" signal.                                */
2711 /*---------------------------------------------------------------------------*/
2712 static void
2713 selection_clear_cb (GtkWidget         *widget,
2714                     GdkEventSelection *event,
2715                     glView            *view)
2716 {
2717         gl_debug (DEBUG_VIEW, "START");
2718
2719         g_return_if_fail (view && GL_IS_VIEW (view));
2720
2721         view->have_selection = FALSE;
2722         g_object_unref (view->selection_data);
2723         view->selection_data = NULL;
2724
2725         gl_debug (DEBUG_VIEW, "END");
2726 }
2727
2728 /*---------------------------------------------------------------------------*/
2729 /* PRIVATE.  Handle "selection-get" signal.                                  */
2730 /*---------------------------------------------------------------------------*/
2731 static void
2732 selection_get_cb (GtkWidget        *widget,
2733                   GtkSelectionData *selection_data,
2734                   guint             info,
2735                   guint             time,
2736                   glView           *view)
2737 {
2738         gchar            *buffer;
2739         glXMLLabelStatus  status;
2740
2741         gl_debug (DEBUG_VIEW, "START");
2742
2743         g_return_if_fail (view && GL_IS_VIEW (view));
2744
2745         if (view->have_selection) {
2746
2747                 buffer = gl_xml_label_save_buffer (view->selection_data,
2748                                                    &status);
2749                 gtk_selection_data_set (selection_data,
2750                                         GDK_SELECTION_TYPE_STRING, 8,
2751                                         (guchar *)buffer, strlen (buffer));
2752                 g_free (buffer);
2753         }
2754
2755         gl_debug (DEBUG_VIEW, "END");
2756 }
2757
2758 /*---------------------------------------------------------------------------*/
2759 /* PRIVATE.  Handle "selection-received" signal.  (Result of Paste)          */
2760 /*---------------------------------------------------------------------------*/
2761 static void
2762 selection_received_cb (GtkWidget        *widget,
2763                        GtkSelectionData *selection_data,
2764                        guint             time,
2765                        glView           *view)
2766 {
2767         glLabel          *label = NULL;
2768         glXMLLabelStatus  status;
2769         GList            *p, *p_next;
2770         glLabelObject    *object, *newobject;
2771         glViewObject     *view_object;
2772
2773         gl_debug (DEBUG_VIEW, "START");
2774
2775         g_return_if_fail (view && GL_IS_VIEW (view));
2776
2777         if (selection_data->length < 0) {
2778                 return;
2779         }
2780         if (selection_data->type != GDK_SELECTION_TYPE_STRING) {
2781                 return;
2782         }
2783
2784         gl_view_unselect_all (view);
2785
2786         label = gl_xml_label_open_buffer ((gchar *)selection_data->data, &status);
2787         for (p = label->objects; p != NULL; p = p_next) {
2788                 p_next = p->next;
2789
2790                 object = (glLabelObject *) p->data;
2791                 newobject = gl_label_object_dup (object, view->label);
2792
2793                 gl_debug (DEBUG_VIEW, "object pasted");
2794
2795                 if (GL_IS_LABEL_BOX (newobject)) {
2796                         view_object = gl_view_box_new (GL_LABEL_BOX(newobject),
2797                                                        view);
2798                 } else if (GL_IS_LABEL_ELLIPSE (newobject)) {
2799                         view_object = gl_view_ellipse_new (GL_LABEL_ELLIPSE(newobject),
2800                                                            view);
2801                 } else if (GL_IS_LABEL_LINE (newobject)) {
2802                         view_object = gl_view_line_new (GL_LABEL_LINE(newobject),
2803                                                         view);
2804                 } else if (GL_IS_LABEL_IMAGE (newobject)) {
2805                         view_object = gl_view_image_new (GL_LABEL_IMAGE(newobject),
2806                                                          view);
2807                 } else if (GL_IS_LABEL_TEXT (newobject)) {
2808                         view_object = gl_view_text_new (GL_LABEL_TEXT(newobject),
2809                                                         view);
2810                 } else if (GL_IS_LABEL_BARCODE (newobject)) {
2811                         view_object = gl_view_barcode_new (GL_LABEL_BARCODE(newobject),
2812                                                            view);
2813                 } else {
2814                         /* Should not happen! */
2815                         view_object = NULL;
2816                         g_message ("Invalid label object type.");
2817                 }
2818                 gl_view_select_object (view, view_object);
2819         }
2820         g_object_unref (label);
2821
2822         gl_debug (DEBUG_VIEW, "END");
2823 }
2824
2825 /****************************************************************************/
2826 /* Set default font family.                                                 */
2827 /****************************************************************************/
2828 void
2829 gl_view_set_default_font_family (glView      *view,
2830                                  const gchar *font_family)
2831 {
2832         gl_debug (DEBUG_VIEW, "START");
2833
2834         g_return_if_fail (view && GL_IS_VIEW (view));
2835
2836         if (view->default_font_family) {
2837                 g_free (view->default_font_family);
2838         }
2839         view->default_font_family = g_strdup (font_family);
2840
2841         gl_debug (DEBUG_VIEW, "END");
2842 }
2843
2844
2845 /****************************************************************************/
2846 /* Set default font size.                                                   */
2847 /****************************************************************************/
2848 void
2849 gl_view_set_default_font_size (glView  *view,
2850                                gdouble  font_size)
2851 {
2852         gl_debug (DEBUG_VIEW, "START");
2853
2854         g_return_if_fail (view && GL_IS_VIEW (view));
2855
2856         view->default_font_size = font_size;
2857
2858         gl_debug (DEBUG_VIEW, "END");
2859 }
2860
2861
2862 /****************************************************************************/
2863 /* Set default font weight.                                                 */
2864 /****************************************************************************/
2865 void
2866 gl_view_set_default_font_weight (glView      *view,
2867                                  PangoWeight  font_weight)
2868 {
2869         gl_debug (DEBUG_VIEW, "START");
2870
2871         g_return_if_fail (view && GL_IS_VIEW (view));
2872
2873         view->default_font_weight = font_weight;
2874
2875         gl_debug (DEBUG_VIEW, "END");
2876 }
2877
2878
2879 /****************************************************************************/
2880 /* Set default font italic flag.                                            */
2881 /****************************************************************************/
2882 void
2883 gl_view_set_default_font_italic_flag (glView   *view,
2884                                       gboolean  font_italic_flag)
2885 {
2886         gl_debug (DEBUG_VIEW, "START");
2887
2888         g_return_if_fail (view && GL_IS_VIEW (view));
2889
2890         view->default_font_italic_flag = font_italic_flag;
2891
2892         gl_debug (DEBUG_VIEW, "END");
2893 }
2894
2895
2896 /****************************************************************************/
2897 /* Set default text color.                                                  */
2898 /****************************************************************************/
2899 void
2900 gl_view_set_default_text_color (glView *view,
2901                                 guint   text_color)
2902 {
2903         gl_debug (DEBUG_VIEW, "START");
2904
2905         g_return_if_fail (view && GL_IS_VIEW (view));
2906
2907         view->default_text_color = text_color;
2908
2909         gl_debug (DEBUG_VIEW, "END");
2910 }
2911
2912
2913 /****************************************************************************/
2914 /* Set default text alignment.                                              */
2915 /****************************************************************************/
2916 void
2917 gl_view_set_default_text_alignment (glView           *view,
2918                                     PangoAlignment    text_alignment)
2919 {
2920         gl_debug (DEBUG_VIEW, "START");
2921
2922         g_return_if_fail (view && GL_IS_VIEW (view));
2923
2924         view->default_text_alignment = text_alignment;
2925         gl_debug (DEBUG_VIEW, "END");
2926 }
2927
2928 /****************************************************************************/
2929 /* Set default text line spacing.                                           */
2930 /****************************************************************************/
2931 void
2932 gl_view_set_default_text_line_spacing (glView  *view,
2933                                        gdouble  text_line_spacing)
2934 {
2935         gl_debug (DEBUG_VIEW, "START");
2936
2937         g_return_if_fail (view && GL_IS_VIEW (view));
2938
2939         view->default_text_line_spacing = text_line_spacing;
2940
2941         gl_debug (DEBUG_VIEW, "END");
2942 }
2943
2944
2945 /****************************************************************************/
2946 /* Set default line width.                                                  */
2947 /****************************************************************************/
2948 void
2949 gl_view_set_default_line_width (glView  *view,
2950                                 gdouble  line_width)
2951 {
2952         gl_debug (DEBUG_VIEW, "START");
2953
2954         g_return_if_fail (view && GL_IS_VIEW (view));
2955
2956         view->default_line_width = line_width;
2957
2958         gl_debug (DEBUG_VIEW, "END");
2959 }
2960
2961
2962 /****************************************************************************/
2963 /* Set default line color.                                                  */
2964 /****************************************************************************/
2965 void
2966 gl_view_set_default_line_color (glView *view,
2967                                 guint   line_color)
2968 {
2969         gl_debug (DEBUG_VIEW, "START");
2970
2971         g_return_if_fail (view && GL_IS_VIEW (view));
2972
2973         view->default_line_color = line_color;
2974
2975         gl_debug (DEBUG_VIEW, "END");
2976 }
2977
2978
2979 /****************************************************************************/
2980 /* Set default fill color.                                                  */
2981 /****************************************************************************/
2982 void
2983 gl_view_set_default_fill_color (glView *view,
2984                                 guint   fill_color)
2985 {
2986         gl_debug (DEBUG_VIEW, "START");
2987
2988         g_return_if_fail (view && GL_IS_VIEW (view));
2989
2990         view->default_fill_color = fill_color;
2991
2992         gl_debug (DEBUG_VIEW, "END");
2993 }
2994
2995
2996
2997 /****************************************************************************/
2998 /* Get default font family.                                                 */
2999 /****************************************************************************/
3000 gchar *
3001 gl_view_get_default_font_family (glView *view)
3002 {
3003         gl_debug (DEBUG_VIEW, "START");
3004
3005         g_return_val_if_fail (view && GL_IS_VIEW (view), NULL);
3006
3007         gl_debug (DEBUG_VIEW, "END");
3008
3009         return g_strdup (view->default_font_family);
3010 }
3011
3012
3013 /****************************************************************************/
3014 /* Get default font size.                                                   */
3015 /****************************************************************************/
3016 gdouble
3017 gl_view_get_default_font_size (glView *view)
3018 {
3019         gl_debug (DEBUG_VIEW, "START");
3020
3021         g_return_val_if_fail (view && GL_IS_VIEW (view), 12.0);
3022
3023         gl_debug (DEBUG_VIEW, "END");
3024
3025         return view->default_font_size;
3026 }
3027
3028
3029 /****************************************************************************/
3030 /* Get default font weight.                                                 */
3031 /****************************************************************************/
3032 PangoWeight
3033 gl_view_get_default_font_weight (glView *view)
3034 {
3035         gl_debug (DEBUG_VIEW, "START");
3036
3037         g_return_val_if_fail (view && GL_IS_VIEW (view), PANGO_WEIGHT_NORMAL);
3038
3039         gl_debug (DEBUG_VIEW, "END");
3040
3041         return view->default_font_weight;
3042 }
3043
3044
3045 /****************************************************************************/
3046 /* Get default font italic flag.                                            */
3047 /****************************************************************************/
3048 gboolean
3049 gl_view_get_default_font_italic_flag (glView *view)
3050 {
3051         gl_debug (DEBUG_VIEW, "START");
3052
3053         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
3054
3055         gl_debug (DEBUG_VIEW, "END");
3056
3057         return view->default_font_italic_flag;
3058 }
3059
3060
3061 /****************************************************************************/
3062 /* Get default text color.                                                  */
3063 /****************************************************************************/
3064 guint
3065 gl_view_get_default_text_color (glView *view)
3066 {
3067         gl_debug (DEBUG_VIEW, "START");
3068
3069         g_return_val_if_fail (view && GL_IS_VIEW (view), 0);
3070
3071         gl_debug (DEBUG_VIEW, "END");
3072
3073         return view->default_text_color;
3074 }
3075
3076
3077 /****************************************************************************/
3078 /* Get default text alignment.                                              */
3079 /****************************************************************************/
3080 PangoAlignment
3081 gl_view_get_default_text_alignment (glView *view)
3082 {
3083         gl_debug (DEBUG_VIEW, "START");
3084
3085         g_return_val_if_fail (view && GL_IS_VIEW (view), PANGO_ALIGN_LEFT);
3086
3087         gl_debug (DEBUG_VIEW, "END");
3088
3089         return view->default_text_alignment;
3090 }
3091
3092 /****************************************************************************/
3093 /* Get default text line spacing.                                           */
3094 /****************************************************************************/
3095 gdouble
3096 gl_view_get_default_text_line_spacing (glView *view)
3097 {
3098         gl_debug (DEBUG_VIEW, "START");
3099
3100         g_return_val_if_fail (view && GL_IS_VIEW (view), 1.0);
3101
3102         gl_debug (DEBUG_VIEW, "END");
3103
3104         return view->default_text_line_spacing;
3105 }
3106
3107
3108
3109 /****************************************************************************/
3110 /* Get default line width.                                                  */
3111 /****************************************************************************/
3112 gdouble
3113 gl_view_get_default_line_width (glView *view)
3114 {
3115         gl_debug (DEBUG_VIEW, "START");
3116
3117         g_return_val_if_fail (view && GL_IS_VIEW (view), 1.0);
3118
3119         gl_debug (DEBUG_VIEW, "END");
3120
3121         return view->default_line_width;
3122 }
3123
3124
3125 /****************************************************************************/
3126 /* Get default line color.                                                  */
3127 /****************************************************************************/
3128 guint
3129 gl_view_get_default_line_color (glView *view)
3130 {
3131         gl_debug (DEBUG_VIEW, "START");
3132
3133         g_return_val_if_fail (view && GL_IS_VIEW (view), 0);
3134
3135         gl_debug (DEBUG_VIEW, "END");
3136
3137         return view->default_line_color;
3138 }
3139
3140
3141 /****************************************************************************/
3142 /* Get default fill color.                                                  */
3143 /****************************************************************************/
3144 guint
3145 gl_view_get_default_fill_color (glView *view)
3146 {
3147         gl_debug (DEBUG_VIEW, "START");
3148
3149         g_return_val_if_fail (view && GL_IS_VIEW (view), 0);
3150
3151         gl_debug (DEBUG_VIEW, "END");
3152
3153         return view->default_fill_color;
3154 }
3155
3156 /*---------------------------------------------------------------------------*/
3157 /* PRIVATE.  Focus in event handler.                                         */
3158 /*---------------------------------------------------------------------------*/
3159 static gboolean
3160 focus_in_event_cb (glView            *view,
3161                    GdkEventFocus     *event)
3162 {
3163         GTK_WIDGET_SET_FLAGS (GTK_WIDGET (view->canvas), GTK_HAS_FOCUS);
3164
3165         return FALSE;
3166 }
3167
3168 /*---------------------------------------------------------------------------*/
3169 /* PRIVATE.  Focus out event handler.                                        */
3170 /*---------------------------------------------------------------------------*/
3171 static gboolean
3172 focus_out_event_cb (glView            *view,
3173                     GdkEventFocus     *event)
3174 {
3175         GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (view->canvas), GTK_HAS_FOCUS);
3176
3177         return FALSE;
3178 }
3179
3180 /*---------------------------------------------------------------------------*/
3181 /* PRIVATE.  Enter notify event handler.                                     */
3182 /*---------------------------------------------------------------------------*/
3183 static gboolean
3184 enter_notify_event_cb (glView            *view,
3185                        GdkEventCrossing  *event)
3186 {
3187         gtk_widget_grab_focus(GTK_WIDGET (view->canvas));
3188
3189         return FALSE;
3190 }
3191
3192 /*---------------------------------------------------------------------------*/
3193 /* PRIVATE.  Leave notify event handler.                                     */
3194 /*---------------------------------------------------------------------------*/
3195 static gboolean
3196 leave_notify_event_cb (glView            *view,
3197                        GdkEventCrossing  *event)
3198 {
3199
3200         g_signal_emit (G_OBJECT(view), signals[POINTER_EXIT], 0);
3201
3202         return FALSE;
3203 }
3204
3205 /*---------------------------------------------------------------------------*/
3206 /* PRIVATE.  Motion notify event handler.                                    */
3207 /*---------------------------------------------------------------------------*/
3208 static gboolean
3209 motion_notify_event_cb (glView            *view,
3210                         GdkEventMotion    *event)
3211 {
3212         gboolean            return_value = FALSE;
3213         cairo_t            *cr;
3214         gdouble             scale;
3215         gdouble             x, y;
3216         GdkCursor          *cursor;
3217         glViewObjectHandle  handle;
3218
3219         cr = gdk_cairo_create (GTK_LAYOUT (view->canvas)->bin_window);
3220
3221         /*
3222          * Translate to label coordinates
3223          */
3224         scale = view->zoom * view->home_scale;
3225         cairo_scale (cr, scale, scale);
3226         cairo_translate (cr, view->x0, view->y0);
3227
3228         x = event->x;
3229         y = event->y;
3230         cairo_device_to_user (cr, &x, &y);
3231
3232         /*
3233          * Emit signal regardless of mode
3234          */
3235         g_signal_emit (G_OBJECT(view), signals[POINTER_MOVED], 0, x, y);
3236
3237         /*
3238          * Handle event as appropriate for mode
3239          */
3240         switch (view->mode)
3241         {
3242
3243         case GL_VIEW_MODE_ARROW:
3244                 switch (view->state)
3245                 {
3246
3247                 case GL_VIEW_IDLE:
3248                         if (view_handle_at (view, cr, event->x, event->y, &handle))
3249                         {
3250                                 cursor = gdk_cursor_new (GDK_CROSSHAIR);
3251                         }
3252                         else if (view_view_object_at (view, cr, event->x, event->y))
3253                         {
3254                                 cursor = gdk_cursor_new (GDK_FLEUR);
3255                         }
3256                         else
3257                         {
3258                                 cursor = gdk_cursor_new (GDK_LEFT_PTR);
3259                         }
3260                         gdk_window_set_cursor (view->canvas->window, cursor);
3261                         gdk_cursor_unref (cursor);
3262                         break;
3263
3264                 case GL_VIEW_ARROW_SELECT_REGION:
3265 #ifdef CLIP_UPDATES                                
3266                         gl_view_update_region (view, cr, &view->select_region);
3267 #endif
3268                         view->select_region.x2 = x;
3269                         view->select_region.y2 = y;
3270 #ifdef CLIP_UPDATES                                
3271                         gl_view_update_region (view, cr, &view->select_region);
3272 #else
3273                         gl_view_update (view);
3274 #endif
3275                         break;
3276
3277                 case GL_VIEW_ARROW_MOVE:
3278                         gl_view_move_selection (view,
3279                                                 (x - view->move_last_x),
3280                                                 (y - view->move_last_y));
3281                         view->move_last_x = x;
3282                         view->move_last_y = y;
3283                         break;
3284
3285                 case GL_VIEW_ARROW_RESIZE:
3286                         gl_view_object_resize_event (view->resize_object,
3287                                                      view->resize_handle,
3288                                                      view->resize_honor_aspect,
3289                                                      cr,
3290                                                      event->x,
3291                                                      event->y);
3292                         break;
3293
3294                 default:
3295                         g_message ("Invalid arrow state.");      /*Should not happen!*/
3296                 }
3297                 return_value = TRUE;
3298                 break;
3299
3300
3301         case GL_VIEW_MODE_OBJECT_CREATE:
3302                 if (view->state != GL_VIEW_IDLE)
3303                 {
3304                         switch (view->create_type)
3305                         {
3306                         case GL_LABEL_OBJECT_BOX:
3307                                 gl_view_box_create_motion_event (view, x, y);
3308                                 break;
3309                         case GL_LABEL_OBJECT_ELLIPSE:
3310                                 gl_view_ellipse_create_motion_event (view, x, y);
3311                                 break;
3312                         case GL_LABEL_OBJECT_LINE: 
3313                                 gl_view_line_create_motion_event (view, x, y);
3314                                 break;
3315                         case GL_LABEL_OBJECT_IMAGE:
3316                                 gl_view_image_create_motion_event (view, x, y);
3317                                 break;
3318                         case GL_LABEL_OBJECT_TEXT:
3319                                 gl_view_text_create_motion_event (view, x, y);
3320                                 break;
3321                         case GL_LABEL_OBJECT_BARCODE:
3322                                 gl_view_barcode_create_motion_event (view, x, y);
3323                                 break;
3324                         default:
3325                                 g_message ("Invalid create type.");   /*Should not happen!*/
3326                         }
3327                 }
3328                 break;
3329
3330
3331         default:
3332                 g_message ("Invalid view mode.");      /*Should not happen!*/
3333
3334         }
3335
3336         cairo_destroy (cr);
3337
3338         /*
3339          * FIXME: we re-establish grabs here if the grab has been lost.  We seem to be
3340          *        losing grabs when we emit signals that lead to the manipulation of
3341          *        the GtkUIManager.  Needs more investigation
3342          */
3343         if (view->grabbed_flag && !gdk_pointer_is_grabbed ())
3344         {
3345                 gdk_pointer_grab (GTK_LAYOUT (view->canvas)->bin_window,
3346                                   FALSE,
3347                                   (GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK),
3348                                   NULL,
3349                                   NULL,
3350                                   event->time);
3351         }
3352
3353         return return_value;
3354 }
3355
3356 /*---------------------------------------------------------------------------*/
3357 /* PRIVATE.  Button press event handler.                                     */
3358 /*---------------------------------------------------------------------------*/
3359 static gboolean
3360 button_press_event_cb (glView            *view,
3361                        GdkEventButton    *event)
3362 {
3363         gboolean            return_value = FALSE;
3364         cairo_t            *cr;
3365         gdouble             scale;
3366         gdouble             x, y;
3367         glViewObject       *view_object;
3368         glViewObjectHandle  handle;
3369
3370         cr = gdk_cairo_create (GTK_LAYOUT (view->canvas)->bin_window);
3371
3372         /*
3373          * Translate to label coordinates
3374          */
3375         scale = view->zoom * view->home_scale;
3376         cairo_scale (cr, scale, scale);
3377         cairo_translate (cr, view->x0, view->y0);
3378
3379         x = event->x;
3380         y = event->y;
3381         cairo_device_to_user (cr, &x, &y);
3382
3383         switch (event->button)
3384         {
3385
3386         case 1:
3387                 /*
3388                  * Handle event as appropriate for mode
3389                  */
3390                 switch (view->mode)
3391                 {
3392                 case GL_VIEW_MODE_ARROW:
3393                         if ((view_object = view_handle_at (view, cr, event->x, event->y, &handle)))
3394                         {
3395                                 view->resize_object = view_object;
3396                                 view->resize_handle = handle;
3397                                 view->resize_honor_aspect = event->state & GDK_CONTROL_MASK;
3398
3399                                 view->state = GL_VIEW_ARROW_RESIZE;
3400                         }
3401                         else if ((view_object = view_view_object_at (view, cr, event->x, event->y)))
3402                         {
3403                                 if (event->state & GDK_CONTROL_MASK)
3404                                 {
3405                                         if (gl_view_is_object_selected (view, view_object))
3406                                         {
3407                                                 /* Un-selecting a selected item */
3408                                                 gl_view_unselect_object (view, view_object);
3409                                         } else {
3410                                                 /* Add to current selection */
3411                                                 gl_view_select_object (view, view_object);
3412                                         }
3413                                 }
3414                                 else
3415                                 {
3416                                         if (!gl_view_is_object_selected (view, view_object))
3417                                         {
3418                                                 /* remove any selections before adding */
3419                                                 gl_view_unselect_all (view);
3420                                                 /* Add to current selection */
3421                                                 gl_view_select_object (view, view_object);
3422                                         }
3423                                 }
3424                                 view->move_last_x = x;
3425                                 view->move_last_y = y;
3426
3427                                 view->state = GL_VIEW_ARROW_MOVE;
3428                         }
3429                         else
3430                         {
3431                                 if (!(event->state & GDK_CONTROL_MASK))
3432                                 {
3433                                         gl_view_unselect_all (view);
3434                                 }
3435
3436                                 view->select_region_visible = TRUE;
3437                                 view->select_region.x1 = x;
3438                                 view->select_region.y1 = y;
3439                                 view->select_region.x2 = x;
3440                                 view->select_region.y2 = y;
3441
3442                                 view->state = GL_VIEW_ARROW_SELECT_REGION;
3443                         }
3444
3445
3446                         return_value = TRUE;
3447                         break;
3448
3449                 case GL_VIEW_MODE_OBJECT_CREATE:
3450                         switch (view->create_type)
3451                         {
3452                         case GL_LABEL_OBJECT_BOX:
3453                                 gl_view_box_create_button_press_event (view, x, y);
3454                                 break;
3455                         case GL_LABEL_OBJECT_ELLIPSE:
3456                                 gl_view_ellipse_create_button_press_event (view, x, y);
3457                                 break;
3458                         case GL_LABEL_OBJECT_LINE:
3459                                 gl_view_line_create_button_press_event (view, x, y);
3460                                 break;
3461                         case GL_LABEL_OBJECT_IMAGE:
3462                                 gl_view_image_create_button_press_event (view, x, y);
3463                                 break;
3464                         case GL_LABEL_OBJECT_TEXT:
3465                                 gl_view_text_create_button_press_event (view, x, y);
3466                                 break;
3467                         case GL_LABEL_OBJECT_BARCODE:
3468                                 gl_view_barcode_create_button_press_event (view, x, y);
3469                                 break;
3470                         default:
3471                                 g_message ("Invalid create type.");   /*Should not happen!*/
3472                         }
3473                         view->state = GL_VIEW_CREATE_DRAG;
3474                         return_value = TRUE;
3475                         break;
3476
3477                 default:
3478                         g_message ("Invalid view mode.");      /*Should not happen!*/
3479                 }
3480
3481                 view->grabbed_flag = TRUE;
3482                 gdk_pointer_grab (GTK_LAYOUT (view->canvas)->bin_window,
3483                                   FALSE,
3484                                   (GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK),
3485                                   NULL,
3486                                   NULL,
3487                                   event->time);
3488                 break;
3489
3490         case 3:
3491                 g_signal_emit (G_OBJECT (view),
3492                                signals[CONTEXT_MENU_ACTIVATE], 0,
3493                                event->button, event->time);
3494                 return_value = TRUE;
3495                 break;
3496
3497         }
3498
3499         cairo_destroy (cr);
3500
3501         return return_value;
3502 }
3503
3504 /*---------------------------------------------------------------------------*/
3505 /* PRIVATE.  Button release event handler.                                   */
3506 /*---------------------------------------------------------------------------*/
3507 static gboolean
3508 button_release_event_cb (glView            *view,
3509                          GdkEventButton    *event)
3510 {
3511         gboolean     return_value = FALSE;
3512         cairo_t     *cr;
3513         gdouble      scale;
3514         gdouble      x, y;
3515         GdkCursor   *cursor;
3516
3517         cr = gdk_cairo_create (GTK_LAYOUT (view->canvas)->bin_window);
3518
3519         /*
3520          * Translate to label coordinates
3521          */
3522         scale = view->zoom * view->home_scale;
3523         cairo_scale (cr, scale, scale);
3524         cairo_translate (cr, view->x0, view->y0);
3525
3526         x = event->x;
3527         y = event->y;
3528         cairo_device_to_user (cr, &x, &y);
3529
3530         switch (event->button)
3531         {
3532
3533         case 1:
3534                 view->grabbed_flag = FALSE;
3535                 gdk_pointer_ungrab (event->time);
3536                 /*
3537                  * Handle event as appropriate for mode
3538                  */
3539                 switch (view->mode)
3540                 {
3541                 case GL_VIEW_MODE_ARROW:
3542                         switch (view->state)
3543                         {
3544                         case GL_VIEW_ARROW_RESIZE:
3545                                 view->resize_object = NULL;
3546
3547                                 view->state = GL_VIEW_IDLE;
3548                                 break;
3549
3550                         case GL_VIEW_ARROW_SELECT_REGION:
3551 #ifdef CLIP_UPDATES                                
3552                                 gl_view_update_region (view, cr, &view->select_region);
3553 #else
3554                                 gl_view_update (view);
3555 #endif
3556
3557                                 view->select_region_visible = FALSE;
3558                                 view->select_region.x2 = x;
3559                                 view->select_region.y2 = y;
3560
3561                                 gl_view_select_region (view, &view->select_region);
3562
3563                                 view->state = GL_VIEW_IDLE;
3564                                 break;
3565
3566                         default:
3567                                 view->state = GL_VIEW_IDLE;
3568                                 break;
3569                                 
3570                         }
3571
3572                         return_value = TRUE;
3573                         break;
3574
3575
3576                 case GL_VIEW_MODE_OBJECT_CREATE:
3577                         switch (view->create_type)
3578                         {
3579                         case GL_LABEL_OBJECT_BOX:
3580                                 gl_view_box_create_button_release_event (view, x, y);
3581                                 break;
3582                         case GL_LABEL_OBJECT_ELLIPSE:
3583                                 gl_view_ellipse_create_button_release_event (view, x, y);
3584                                 break;
3585                         case GL_LABEL_OBJECT_LINE:
3586                                 gl_view_line_create_button_release_event (view, x, y);
3587                                 break;
3588                         case GL_LABEL_OBJECT_IMAGE:
3589                                 gl_view_image_create_button_release_event (view, x, y);
3590                                 break;
3591                         case GL_LABEL_OBJECT_TEXT:
3592                                 gl_view_text_create_button_release_event (view, x, y);
3593                                 break;
3594                         case GL_LABEL_OBJECT_BARCODE:
3595                                 gl_view_barcode_create_button_release_event (view, x, y);
3596                                 break;
3597                         default:
3598                                 g_message ("Invalid create type.");   /*Should not happen!*/
3599                         }
3600                         view->mode = GL_VIEW_MODE_ARROW;
3601                         view->state = GL_VIEW_IDLE;
3602                         cursor = gdk_cursor_new (GDK_LEFT_PTR);
3603                         gdk_window_set_cursor (view->canvas->window, cursor);
3604                         gdk_cursor_unref (cursor);
3605                         break;
3606
3607
3608                 default:
3609                         g_message ("Invalid view mode.");      /*Should not happen!*/
3610                 }
3611
3612         }
3613
3614         cairo_destroy (cr);
3615
3616         return return_value;
3617 }
3618
3619 /*---------------------------------------------------------------------------*/
3620 /* PRIVATE.  Key press event handler.                                        */
3621 /*---------------------------------------------------------------------------*/
3622 static gboolean
3623 key_press_event_cb (glView            *view,
3624                     GdkEventKey       *event)
3625 {
3626         GdkCursor *cursor;
3627
3628         gl_debug (DEBUG_VIEW, "");
3629
3630         if ( (view->mode == GL_VIEW_MODE_ARROW) &&
3631              (view->state == GL_VIEW_IDLE) )
3632         {
3633                 switch (event->keyval) {
3634
3635                 case GDK_Left:
3636                 case GDK_KP_Left:
3637                         gl_view_move_selection (view, -1.0 / (view->zoom), 0.0);
3638                         break;
3639                 case GDK_Up:
3640                 case GDK_KP_Up:
3641                         gl_view_move_selection (view, 0.0, -1.0 / (view->zoom));
3642                         break;
3643                 case GDK_Right:
3644                 case GDK_KP_Right:
3645                         gl_view_move_selection (view, 1.0 / (view->zoom), 0.0);
3646                         break;
3647                 case GDK_Down:
3648                 case GDK_KP_Down:
3649                         gl_view_move_selection (view, 0.0, 1.0 / (view->zoom));
3650                         break;
3651                 case GDK_Delete:
3652                 case GDK_KP_Delete:
3653                         gl_view_delete_selection (view);
3654                         cursor = gdk_cursor_new (GDK_LEFT_PTR);
3655                         gdk_window_set_cursor (GTK_WIDGET (view->canvas)->window
3656 , cursor);
3657                         gdk_cursor_unref (cursor);
3658                         break;
3659                 default:
3660                         return FALSE;
3661  
3662                }
3663         }
3664         return TRUE;    /* We handled this or we were dragging. */
3665 }
3666