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