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