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