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