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