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