]> git.sur5r.net Git - glabels/blob - src/view.c
Imported Upstream version 2.2.8
[glabels] / 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
2772         gl_debug (DEBUG_VIEW, "START");
2773
2774         g_return_if_fail (view && GL_IS_VIEW (view));
2775
2776         if (selection_data->length < 0) {
2777                 return;
2778         }
2779         if (selection_data->type != GDK_SELECTION_TYPE_STRING) {
2780                 return;
2781         }
2782
2783         gl_view_unselect_all (view);
2784
2785         label = gl_xml_label_open_buffer ((gchar *)selection_data->data, &status);
2786         for (p = label->objects; p != NULL; p = p_next) {
2787                 p_next = p->next;
2788
2789                 object = (glLabelObject *) p->data;
2790                 newobject = gl_label_object_dup (object, view->label);
2791
2792                 gl_debug (DEBUG_VIEW, "object pasted");
2793         }
2794         g_object_unref (label);
2795
2796         gl_debug (DEBUG_VIEW, "END");
2797 }
2798
2799 /****************************************************************************/
2800 /* Set default font family.                                                 */
2801 /****************************************************************************/
2802 void
2803 gl_view_set_default_font_family (glView      *view,
2804                                  const gchar *font_family)
2805 {
2806         gl_debug (DEBUG_VIEW, "START");
2807
2808         g_return_if_fail (view && GL_IS_VIEW (view));
2809
2810         if (view->default_font_family) {
2811                 g_free (view->default_font_family);
2812         }
2813         view->default_font_family = g_strdup (font_family);
2814
2815         gl_debug (DEBUG_VIEW, "END");
2816 }
2817
2818
2819 /****************************************************************************/
2820 /* Set default font size.                                                   */
2821 /****************************************************************************/
2822 void
2823 gl_view_set_default_font_size (glView  *view,
2824                                gdouble  font_size)
2825 {
2826         gl_debug (DEBUG_VIEW, "START");
2827
2828         g_return_if_fail (view && GL_IS_VIEW (view));
2829
2830         view->default_font_size = font_size;
2831
2832         gl_debug (DEBUG_VIEW, "END");
2833 }
2834
2835
2836 /****************************************************************************/
2837 /* Set default font weight.                                                 */
2838 /****************************************************************************/
2839 void
2840 gl_view_set_default_font_weight (glView      *view,
2841                                  PangoWeight  font_weight)
2842 {
2843         gl_debug (DEBUG_VIEW, "START");
2844
2845         g_return_if_fail (view && GL_IS_VIEW (view));
2846
2847         view->default_font_weight = font_weight;
2848
2849         gl_debug (DEBUG_VIEW, "END");
2850 }
2851
2852
2853 /****************************************************************************/
2854 /* Set default font italic flag.                                            */
2855 /****************************************************************************/
2856 void
2857 gl_view_set_default_font_italic_flag (glView   *view,
2858                                       gboolean  font_italic_flag)
2859 {
2860         gl_debug (DEBUG_VIEW, "START");
2861
2862         g_return_if_fail (view && GL_IS_VIEW (view));
2863
2864         view->default_font_italic_flag = font_italic_flag;
2865
2866         gl_debug (DEBUG_VIEW, "END");
2867 }
2868
2869
2870 /****************************************************************************/
2871 /* Set default text color.                                                  */
2872 /****************************************************************************/
2873 void
2874 gl_view_set_default_text_color (glView *view,
2875                                 guint   text_color)
2876 {
2877         gl_debug (DEBUG_VIEW, "START");
2878
2879         g_return_if_fail (view && GL_IS_VIEW (view));
2880
2881         view->default_text_color = text_color;
2882
2883         gl_debug (DEBUG_VIEW, "END");
2884 }
2885
2886
2887 /****************************************************************************/
2888 /* Set default text alignment.                                              */
2889 /****************************************************************************/
2890 void
2891 gl_view_set_default_text_alignment (glView           *view,
2892                                     PangoAlignment    text_alignment)
2893 {
2894         gl_debug (DEBUG_VIEW, "START");
2895
2896         g_return_if_fail (view && GL_IS_VIEW (view));
2897
2898         view->default_text_alignment = text_alignment;
2899         gl_debug (DEBUG_VIEW, "END");
2900 }
2901
2902 /****************************************************************************/
2903 /* Set default text line spacing.                                           */
2904 /****************************************************************************/
2905 void
2906 gl_view_set_default_text_line_spacing (glView  *view,
2907                                        gdouble  text_line_spacing)
2908 {
2909         gl_debug (DEBUG_VIEW, "START");
2910
2911         g_return_if_fail (view && GL_IS_VIEW (view));
2912
2913         view->default_text_line_spacing = text_line_spacing;
2914
2915         gl_debug (DEBUG_VIEW, "END");
2916 }
2917
2918
2919 /****************************************************************************/
2920 /* Set default line width.                                                  */
2921 /****************************************************************************/
2922 void
2923 gl_view_set_default_line_width (glView  *view,
2924                                 gdouble  line_width)
2925 {
2926         gl_debug (DEBUG_VIEW, "START");
2927
2928         g_return_if_fail (view && GL_IS_VIEW (view));
2929
2930         view->default_line_width = line_width;
2931
2932         gl_debug (DEBUG_VIEW, "END");
2933 }
2934
2935
2936 /****************************************************************************/
2937 /* Set default line color.                                                  */
2938 /****************************************************************************/
2939 void
2940 gl_view_set_default_line_color (glView *view,
2941                                 guint   line_color)
2942 {
2943         gl_debug (DEBUG_VIEW, "START");
2944
2945         g_return_if_fail (view && GL_IS_VIEW (view));
2946
2947         view->default_line_color = line_color;
2948
2949         gl_debug (DEBUG_VIEW, "END");
2950 }
2951
2952
2953 /****************************************************************************/
2954 /* Set default fill color.                                                  */
2955 /****************************************************************************/
2956 void
2957 gl_view_set_default_fill_color (glView *view,
2958                                 guint   fill_color)
2959 {
2960         gl_debug (DEBUG_VIEW, "START");
2961
2962         g_return_if_fail (view && GL_IS_VIEW (view));
2963
2964         view->default_fill_color = fill_color;
2965
2966         gl_debug (DEBUG_VIEW, "END");
2967 }
2968
2969
2970
2971 /****************************************************************************/
2972 /* Get default font family.                                                 */
2973 /****************************************************************************/
2974 gchar *
2975 gl_view_get_default_font_family (glView *view)
2976 {
2977         gl_debug (DEBUG_VIEW, "START");
2978
2979         g_return_val_if_fail (view && GL_IS_VIEW (view), NULL);
2980
2981         gl_debug (DEBUG_VIEW, "END");
2982
2983         return g_strdup (view->default_font_family);
2984 }
2985
2986
2987 /****************************************************************************/
2988 /* Get default font size.                                                   */
2989 /****************************************************************************/
2990 gdouble
2991 gl_view_get_default_font_size (glView *view)
2992 {
2993         gl_debug (DEBUG_VIEW, "START");
2994
2995         g_return_val_if_fail (view && GL_IS_VIEW (view), 12.0);
2996
2997         gl_debug (DEBUG_VIEW, "END");
2998
2999         return view->default_font_size;
3000 }
3001
3002
3003 /****************************************************************************/
3004 /* Get default font weight.                                                 */
3005 /****************************************************************************/
3006 PangoWeight
3007 gl_view_get_default_font_weight (glView *view)
3008 {
3009         gl_debug (DEBUG_VIEW, "START");
3010
3011         g_return_val_if_fail (view && GL_IS_VIEW (view), PANGO_WEIGHT_NORMAL);
3012
3013         gl_debug (DEBUG_VIEW, "END");
3014
3015         return view->default_font_weight;
3016 }
3017
3018
3019 /****************************************************************************/
3020 /* Get default font italic flag.                                            */
3021 /****************************************************************************/
3022 gboolean
3023 gl_view_get_default_font_italic_flag (glView *view)
3024 {
3025         gl_debug (DEBUG_VIEW, "START");
3026
3027         g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
3028
3029         gl_debug (DEBUG_VIEW, "END");
3030
3031         return view->default_font_italic_flag;
3032 }
3033
3034
3035 /****************************************************************************/
3036 /* Get default text color.                                                  */
3037 /****************************************************************************/
3038 guint
3039 gl_view_get_default_text_color (glView *view)
3040 {
3041         gl_debug (DEBUG_VIEW, "START");
3042
3043         g_return_val_if_fail (view && GL_IS_VIEW (view), 0);
3044
3045         gl_debug (DEBUG_VIEW, "END");
3046
3047         return view->default_text_color;
3048 }
3049
3050
3051 /****************************************************************************/
3052 /* Get default text alignment.                                              */
3053 /****************************************************************************/
3054 PangoAlignment
3055 gl_view_get_default_text_alignment (glView *view)
3056 {
3057         gl_debug (DEBUG_VIEW, "START");
3058
3059         g_return_val_if_fail (view && GL_IS_VIEW (view), PANGO_ALIGN_LEFT);
3060
3061         gl_debug (DEBUG_VIEW, "END");
3062
3063         return view->default_text_alignment;
3064 }
3065
3066 /****************************************************************************/
3067 /* Get default text line spacing.                                           */
3068 /****************************************************************************/
3069 gdouble
3070 gl_view_get_default_text_line_spacing (glView *view)
3071 {
3072         gl_debug (DEBUG_VIEW, "START");
3073
3074         g_return_val_if_fail (view && GL_IS_VIEW (view), 1.0);
3075
3076         gl_debug (DEBUG_VIEW, "END");
3077
3078         return view->default_text_line_spacing;
3079 }
3080
3081
3082
3083 /****************************************************************************/
3084 /* Get default line width.                                                  */
3085 /****************************************************************************/
3086 gdouble
3087 gl_view_get_default_line_width (glView *view)
3088 {
3089         gl_debug (DEBUG_VIEW, "START");
3090
3091         g_return_val_if_fail (view && GL_IS_VIEW (view), 1.0);
3092
3093         gl_debug (DEBUG_VIEW, "END");
3094
3095         return view->default_line_width;
3096 }
3097
3098
3099 /****************************************************************************/
3100 /* Get default line color.                                                  */
3101 /****************************************************************************/
3102 guint
3103 gl_view_get_default_line_color (glView *view)
3104 {
3105         gl_debug (DEBUG_VIEW, "START");
3106
3107         g_return_val_if_fail (view && GL_IS_VIEW (view), 0);
3108
3109         gl_debug (DEBUG_VIEW, "END");
3110
3111         return view->default_line_color;
3112 }
3113
3114
3115 /****************************************************************************/
3116 /* Get default fill color.                                                  */
3117 /****************************************************************************/
3118 guint
3119 gl_view_get_default_fill_color (glView *view)
3120 {
3121         gl_debug (DEBUG_VIEW, "START");
3122
3123         g_return_val_if_fail (view && GL_IS_VIEW (view), 0);
3124
3125         gl_debug (DEBUG_VIEW, "END");
3126
3127         return view->default_fill_color;
3128 }
3129
3130 /*---------------------------------------------------------------------------*/
3131 /* PRIVATE.  Focus in event handler.                                         */
3132 /*---------------------------------------------------------------------------*/
3133 static gboolean
3134 focus_in_event_cb (glView            *view,
3135                    GdkEventFocus     *event)
3136 {
3137         GTK_WIDGET_SET_FLAGS (GTK_WIDGET (view->canvas), GTK_HAS_FOCUS);
3138
3139         return FALSE;
3140 }
3141
3142 /*---------------------------------------------------------------------------*/
3143 /* PRIVATE.  Focus out event handler.                                        */
3144 /*---------------------------------------------------------------------------*/
3145 static gboolean
3146 focus_out_event_cb (glView            *view,
3147                     GdkEventFocus     *event)
3148 {
3149         GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (view->canvas), GTK_HAS_FOCUS);
3150
3151         return FALSE;
3152 }
3153
3154 /*---------------------------------------------------------------------------*/
3155 /* PRIVATE.  Enter notify event handler.                                     */
3156 /*---------------------------------------------------------------------------*/
3157 static gboolean
3158 enter_notify_event_cb (glView            *view,
3159                        GdkEventCrossing  *event)
3160 {
3161         return FALSE;
3162 }
3163
3164 /*---------------------------------------------------------------------------*/
3165 /* PRIVATE.  Leave notify event handler.                                     */
3166 /*---------------------------------------------------------------------------*/
3167 static gboolean
3168 leave_notify_event_cb (glView            *view,
3169                        GdkEventCrossing  *event)
3170 {
3171
3172         g_signal_emit (G_OBJECT(view), signals[POINTER_EXIT], 0);
3173
3174         return FALSE;
3175 }
3176
3177 /*---------------------------------------------------------------------------*/
3178 /* PRIVATE.  Motion notify event handler.                                    */
3179 /*---------------------------------------------------------------------------*/
3180 static gboolean
3181 motion_notify_event_cb (glView            *view,
3182                         GdkEventMotion    *event)
3183 {
3184         gboolean            return_value = FALSE;
3185         cairo_t            *cr;
3186         gdouble             scale;
3187         gdouble             x, y;
3188         GdkCursor          *cursor;
3189         glViewObjectHandle  handle;
3190
3191         cr = gdk_cairo_create (GTK_LAYOUT (view->canvas)->bin_window);
3192
3193         /*
3194          * Translate to label coordinates
3195          */
3196         scale = view->zoom * view->home_scale;
3197         cairo_scale (cr, scale, scale);
3198         cairo_translate (cr, view->x0, view->y0);
3199
3200         x = event->x;
3201         y = event->y;
3202         cairo_device_to_user (cr, &x, &y);
3203
3204         /*
3205          * Emit signal regardless of mode
3206          */
3207         g_signal_emit (G_OBJECT(view), signals[POINTER_MOVED], 0, x, y);
3208
3209         /*
3210          * Handle event as appropriate for mode
3211          */
3212         switch (view->mode)
3213         {
3214
3215         case GL_VIEW_MODE_ARROW:
3216                 switch (view->state)
3217                 {
3218
3219                 case GL_VIEW_IDLE:
3220                         if ( gl_view_is_selection_atomic (view) &&
3221                              view_handle_at (view, cr, event->x, event->y, &handle) )
3222                         {
3223                                 cursor = gdk_cursor_new (GDK_CROSSHAIR);
3224                         }
3225                         else if (view_view_object_at (view, cr, event->x, event->y))
3226                         {
3227                                 cursor = gdk_cursor_new (GDK_FLEUR);
3228                         }
3229                         else
3230                         {
3231                                 cursor = gdk_cursor_new (GDK_LEFT_PTR);
3232                         }
3233                         gdk_window_set_cursor (view->canvas->window, cursor);
3234                         gdk_cursor_unref (cursor);
3235                         break;
3236
3237                 case GL_VIEW_ARROW_SELECT_REGION:
3238 #ifdef CLIP_UPDATES                                
3239                         gl_view_update_region (view, cr, &view->select_region);
3240 #endif
3241                         view->select_region.x2 = x;
3242                         view->select_region.y2 = y;
3243 #ifdef CLIP_UPDATES                                
3244                         gl_view_update_region (view, cr, &view->select_region);
3245 #else
3246                         gl_view_update (view);
3247 #endif
3248                         break;
3249
3250                 case GL_VIEW_ARROW_MOVE:
3251                         gl_view_move_selection (view,
3252                                                 (x - view->move_last_x),
3253                                                 (y - view->move_last_y));
3254                         view->move_last_x = x;
3255                         view->move_last_y = y;
3256                         break;
3257
3258                 case GL_VIEW_ARROW_RESIZE:
3259                         gl_view_object_resize_event (view->resize_object,
3260                                                      view->resize_handle,
3261                                                      view->resize_honor_aspect,
3262                                                      cr,
3263                                                      event->x,
3264                                                      event->y);
3265                         break;
3266
3267                 default:
3268                         g_message ("Invalid arrow state.");      /*Should not happen!*/
3269                 }
3270                 return_value = TRUE;
3271                 break;
3272
3273
3274         case GL_VIEW_MODE_OBJECT_CREATE:
3275                 if (view->state != GL_VIEW_IDLE)
3276                 {
3277                         switch (view->create_type)
3278                         {
3279                         case GL_LABEL_OBJECT_BOX:
3280                                 gl_view_box_create_motion_event (view, x, y);
3281                                 break;
3282                         case GL_LABEL_OBJECT_ELLIPSE:
3283                                 gl_view_ellipse_create_motion_event (view, x, y);
3284                                 break;
3285                         case GL_LABEL_OBJECT_LINE: 
3286                                 gl_view_line_create_motion_event (view, x, y);
3287                                 break;
3288                         case GL_LABEL_OBJECT_IMAGE:
3289                                 gl_view_image_create_motion_event (view, x, y);
3290                                 break;
3291                         case GL_LABEL_OBJECT_TEXT:
3292                                 gl_view_text_create_motion_event (view, x, y);
3293                                 break;
3294                         case GL_LABEL_OBJECT_BARCODE:
3295                                 gl_view_barcode_create_motion_event (view, x, y);
3296                                 break;
3297                         default:
3298                                 g_message ("Invalid create type.");   /*Should not happen!*/
3299                         }
3300                 }
3301                 break;
3302
3303
3304         default:
3305                 g_message ("Invalid view mode.");      /*Should not happen!*/
3306
3307         }
3308
3309         cairo_destroy (cr);
3310
3311         /*
3312          * FIXME: we re-establish grabs here if the grab has been lost.  We seem to be
3313          *        losing grabs when we emit signals that lead to the manipulation of
3314          *        the GtkUIManager.  Needs more investigation
3315          */
3316         if (view->grabbed_flag && !gdk_pointer_is_grabbed ())
3317         {
3318                 gdk_pointer_grab (GTK_LAYOUT (view->canvas)->bin_window,
3319                                   FALSE,
3320                                   (GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK),
3321                                   NULL,
3322                                   NULL,
3323                                   event->time);
3324         }
3325
3326         return return_value;
3327 }
3328
3329 /*---------------------------------------------------------------------------*/
3330 /* PRIVATE.  Button press event handler.                                     */
3331 /*---------------------------------------------------------------------------*/
3332 static gboolean
3333 button_press_event_cb (glView            *view,
3334                        GdkEventButton    *event)
3335 {
3336         gboolean            return_value = FALSE;
3337         cairo_t            *cr;
3338         gdouble             scale;
3339         gdouble             x, y;
3340         glViewObject       *view_object;
3341         glViewObjectHandle  handle;
3342
3343         gtk_widget_grab_focus(GTK_WIDGET (view->canvas));
3344
3345         cr = gdk_cairo_create (GTK_LAYOUT (view->canvas)->bin_window);
3346
3347         /*
3348          * Translate to label coordinates
3349          */
3350         scale = view->zoom * view->home_scale;
3351         cairo_scale (cr, scale, scale);
3352         cairo_translate (cr, view->x0, view->y0);
3353
3354         x = event->x;
3355         y = event->y;
3356         cairo_device_to_user (cr, &x, &y);
3357
3358         switch (event->button)
3359         {
3360
3361         case 1:
3362                 /*
3363                  * Handle event as appropriate for mode
3364                  */
3365                 switch (view->mode)
3366                 {
3367                 case GL_VIEW_MODE_ARROW:
3368                         if ( gl_view_is_selection_atomic (view) &&
3369                              (view_object = view_handle_at (view, cr, event->x, event->y, &handle)) )
3370                         {
3371                                 view->resize_object = view_object;
3372                                 view->resize_handle = handle;
3373                                 view->resize_honor_aspect = event->state & GDK_CONTROL_MASK;
3374
3375                                 view->state = GL_VIEW_ARROW_RESIZE;
3376                         }
3377                         else if ((view_object = view_view_object_at (view, cr, event->x, event->y)))
3378                         {
3379                                 if (event->state & GDK_CONTROL_MASK)
3380                                 {
3381                                         if (gl_view_is_object_selected (view, view_object))
3382                                         {
3383                                                 /* Un-selecting a selected item */
3384                                                 gl_view_unselect_object (view, view_object);
3385                                         } else {
3386                                                 /* Add to current selection */
3387                                                 gl_view_select_object (view, view_object);
3388                                         }
3389                                 }
3390                                 else
3391                                 {
3392                                         if (!gl_view_is_object_selected (view, view_object))
3393                                         {
3394                                                 /* remove any selections before adding */
3395                                                 gl_view_unselect_all (view);
3396                                                 /* Add to current selection */
3397                                                 gl_view_select_object (view, view_object);
3398                                         }
3399                                 }
3400                                 view->move_last_x = x;
3401                                 view->move_last_y = y;
3402
3403                                 view->state = GL_VIEW_ARROW_MOVE;
3404                         }
3405                         else
3406                         {
3407                                 if (!(event->state & GDK_CONTROL_MASK))
3408                                 {
3409                                         gl_view_unselect_all (view);
3410                                 }
3411
3412                                 view->select_region_visible = TRUE;
3413                                 view->select_region.x1 = x;
3414                                 view->select_region.y1 = y;
3415                                 view->select_region.x2 = x;
3416                                 view->select_region.y2 = y;
3417
3418                                 view->state = GL_VIEW_ARROW_SELECT_REGION;
3419                         }
3420
3421
3422                         return_value = TRUE;
3423                         break;
3424
3425                 case GL_VIEW_MODE_OBJECT_CREATE:
3426                         switch (view->create_type)
3427                         {
3428                         case GL_LABEL_OBJECT_BOX:
3429                                 gl_view_box_create_button_press_event (view, x, y);
3430                                 break;
3431                         case GL_LABEL_OBJECT_ELLIPSE:
3432                                 gl_view_ellipse_create_button_press_event (view, x, y);
3433                                 break;
3434                         case GL_LABEL_OBJECT_LINE:
3435                                 gl_view_line_create_button_press_event (view, x, y);
3436                                 break;
3437                         case GL_LABEL_OBJECT_IMAGE:
3438                                 gl_view_image_create_button_press_event (view, x, y);
3439                                 break;
3440                         case GL_LABEL_OBJECT_TEXT:
3441                                 gl_view_text_create_button_press_event (view, x, y);
3442                                 break;
3443                         case GL_LABEL_OBJECT_BARCODE:
3444                                 gl_view_barcode_create_button_press_event (view, x, y);
3445                                 break;
3446                         default:
3447                                 g_message ("Invalid create type.");   /*Should not happen!*/
3448                         }
3449                         view->state = GL_VIEW_CREATE_DRAG;
3450                         return_value = TRUE;
3451                         break;
3452
3453                 default:
3454                         g_message ("Invalid view mode.");      /*Should not happen!*/
3455                 }
3456
3457                 view->grabbed_flag = TRUE;
3458                 gdk_pointer_grab (GTK_LAYOUT (view->canvas)->bin_window,
3459                                   FALSE,
3460                                   (GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK),
3461                                   NULL,
3462                                   NULL,
3463                                   event->time);
3464                 break;
3465
3466         case 3:
3467                 g_signal_emit (G_OBJECT (view),
3468                                signals[CONTEXT_MENU_ACTIVATE], 0,
3469                                event->button, event->time);
3470                 return_value = TRUE;
3471                 break;
3472
3473         }
3474
3475         cairo_destroy (cr);
3476
3477         return return_value;
3478 }
3479
3480 /*---------------------------------------------------------------------------*/
3481 /* PRIVATE.  Button release event handler.                                   */
3482 /*---------------------------------------------------------------------------*/
3483 static gboolean
3484 button_release_event_cb (glView            *view,
3485                          GdkEventButton    *event)
3486 {
3487         gboolean     return_value = FALSE;
3488         cairo_t     *cr;
3489         gdouble      scale;
3490         gdouble      x, y;
3491         GdkCursor   *cursor;
3492
3493         cr = gdk_cairo_create (GTK_LAYOUT (view->canvas)->bin_window);
3494
3495         /*
3496          * Translate to label coordinates
3497          */
3498         scale = view->zoom * view->home_scale;
3499         cairo_scale (cr, scale, scale);
3500         cairo_translate (cr, view->x0, view->y0);
3501
3502         x = event->x;
3503         y = event->y;
3504         cairo_device_to_user (cr, &x, &y);
3505
3506         switch (event->button)
3507         {
3508
3509         case 1:
3510                 view->grabbed_flag = FALSE;
3511                 gdk_pointer_ungrab (event->time);
3512                 /*
3513                  * Handle event as appropriate for mode
3514                  */
3515                 switch (view->mode)
3516                 {
3517                 case GL_VIEW_MODE_ARROW:
3518                         switch (view->state)
3519                         {
3520                         case GL_VIEW_ARROW_RESIZE:
3521                                 view->resize_object = NULL;
3522
3523                                 view->state = GL_VIEW_IDLE;
3524                                 break;
3525
3526                         case GL_VIEW_ARROW_SELECT_REGION:
3527 #ifdef CLIP_UPDATES                                
3528                                 gl_view_update_region (view, cr, &view->select_region);
3529 #else
3530                                 gl_view_update (view);
3531 #endif
3532
3533                                 view->select_region_visible = FALSE;
3534                                 view->select_region.x2 = x;
3535                                 view->select_region.y2 = y;
3536
3537                                 gl_view_select_region (view, &view->select_region);
3538
3539                                 view->state = GL_VIEW_IDLE;
3540                                 break;
3541
3542                         default:
3543                                 view->state = GL_VIEW_IDLE;
3544                                 break;
3545                                 
3546                         }
3547
3548                         return_value = TRUE;
3549                         break;
3550
3551
3552                 case GL_VIEW_MODE_OBJECT_CREATE:
3553                         switch (view->create_type)
3554                         {
3555                         case GL_LABEL_OBJECT_BOX:
3556                                 gl_view_box_create_button_release_event (view, x, y);
3557                                 break;
3558                         case GL_LABEL_OBJECT_ELLIPSE:
3559                                 gl_view_ellipse_create_button_release_event (view, x, y);
3560                                 break;
3561                         case GL_LABEL_OBJECT_LINE:
3562                                 gl_view_line_create_button_release_event (view, x, y);
3563                                 break;
3564                         case GL_LABEL_OBJECT_IMAGE:
3565                                 gl_view_image_create_button_release_event (view, x, y);
3566                                 break;
3567                         case GL_LABEL_OBJECT_TEXT:
3568                                 gl_view_text_create_button_release_event (view, x, y);
3569                                 break;
3570                         case GL_LABEL_OBJECT_BARCODE:
3571                                 gl_view_barcode_create_button_release_event (view, x, y);
3572                                 break;
3573                         default:
3574                                 g_message ("Invalid create type.");   /*Should not happen!*/
3575                         }
3576                         view->mode = GL_VIEW_MODE_ARROW;
3577                         view->state = GL_VIEW_IDLE;
3578                         cursor = gdk_cursor_new (GDK_LEFT_PTR);
3579                         gdk_window_set_cursor (view->canvas->window, cursor);
3580                         gdk_cursor_unref (cursor);
3581                         break;
3582
3583
3584                 default:
3585                         g_message ("Invalid view mode.");      /*Should not happen!*/
3586                 }
3587
3588         }
3589
3590         cairo_destroy (cr);
3591
3592         return return_value;
3593 }
3594
3595 /*---------------------------------------------------------------------------*/
3596 /* PRIVATE.  Key press event handler.                                        */
3597 /*---------------------------------------------------------------------------*/
3598 static gboolean
3599 key_press_event_cb (glView            *view,
3600                     GdkEventKey       *event)
3601 {
3602         GdkCursor *cursor;
3603
3604         gl_debug (DEBUG_VIEW, "");
3605
3606         if ( (view->mode == GL_VIEW_MODE_ARROW) &&
3607              (view->state == GL_VIEW_IDLE) )
3608         {
3609                 switch (event->keyval) {
3610
3611                 case GDK_Left:
3612                 case GDK_KP_Left:
3613                         gl_view_move_selection (view, -1.0 / (view->zoom), 0.0);
3614                         break;
3615                 case GDK_Up:
3616                 case GDK_KP_Up:
3617                         gl_view_move_selection (view, 0.0, -1.0 / (view->zoom));
3618                         break;
3619                 case GDK_Right:
3620                 case GDK_KP_Right:
3621                         gl_view_move_selection (view, 1.0 / (view->zoom), 0.0);
3622                         break;
3623                 case GDK_Down:
3624                 case GDK_KP_Down:
3625                         gl_view_move_selection (view, 0.0, 1.0 / (view->zoom));
3626                         break;
3627                 case GDK_Delete:
3628                 case GDK_KP_Delete:
3629                         gl_view_delete_selection (view);
3630                         cursor = gdk_cursor_new (GDK_LEFT_PTR);
3631                         gdk_window_set_cursor (GTK_WIDGET (view->canvas)->window
3632 , cursor);
3633                         gdk_cursor_unref (cursor);
3634                         break;
3635                 default:
3636                         return FALSE;
3637  
3638                }
3639         }
3640         return TRUE;    /* We handled this or we were dragging. */
3641 }
3642