3 * Copyright (C) 2001-2009 Jim Evins <evins@snaught.com>.
5 * This file is part of gLabels.
7 * gLabels is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * gLabels is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with gLabels. If not, see <http://www.gnu.org/licenses/>.
26 #include "view-ellipse.h"
27 #include "view-line.h"
28 #include "view-image.h"
29 #include "view-text.h"
30 #include "view-barcode.h"
32 #include <glib/gi18n.h>
34 #include <gdk/gdkkeysyms.h>
39 #include "cairo-label-path.h"
40 #include "cairo-markup-path.h"
43 #include "units-util.h"
49 /*==========================================================================*/
50 /* Private macros and constants. */
51 /*==========================================================================*/
53 #define BG_COLOR GL_COLOR (204, 204, 204)
55 #define PAPER_RGB_ARGS 1.0, 1.0, 1.0
56 #define SHADOW_RGB_ARGS 0.2, 0.2, 0.2
57 #define GRID_RGB_ARGS 0.753, 0.753, 0.753
58 #define MARKUP_RGB_ARGS 0.94, 0.39, 0.39
59 #define OUTLINE_RGB_ARGS 0.0, 0.0, 0.0
60 #define SELECT_LINE_RGBA_ARGS 0.0, 0.0, 1.0, 0.5
61 #define SELECT_FILL_RGBA_ARGS 0.75, 0.75, 1.0, 0.5
63 #define GRID_LINE_WIDTH_PIXELS 1.0
64 #define MARKUP_LINE_WIDTH_PIXELS 1.0
65 #define OUTLINE_WIDTH_PIXELS 1.0
66 #define SELECT_LINE_WIDTH_PIXELS 3.0
68 #define ZOOMTOFIT_PAD 16
70 #define SHADOW_OFFSET_PIXELS (ZOOMTOFIT_PAD/4)
72 #define POINTS_PER_MM 2.83464566929
75 /*==========================================================================*/
77 /*==========================================================================*/
80 CONTEXT_MENU_ACTIVATE,
89 /*==========================================================================*/
91 /*==========================================================================*/
93 static guint signals[LAST_SIGNAL] = {0};
95 static gdouble zooms[] = {
112 #define N_ZOOMS G_N_ELEMENTS(zooms)
115 /*==========================================================================*/
116 /* Local function prototypes */
117 /*==========================================================================*/
119 static void gl_view_finalize (GObject *object);
121 static void gl_view_construct (glView *view,
124 static gdouble get_home_scale (glView *view);
126 static void prefs_changed_cb (glView *view);
128 static gboolean draw_cb (glView *view,
131 static void realize_cb (glView *view);
133 static void size_allocate_cb (glView *view,
134 GtkAllocation *allocation);
136 static void screen_changed_cb (glView *view);
138 static void label_changed_cb (glView *view);
140 static void label_resized_cb (glView *view);
142 static void draw_layers (glView *view,
145 static void draw_bg_layer (glView *view,
147 static void draw_grid_layer (glView *view,
149 static void draw_markup_layer (glView *view,
151 static void draw_objects_layer (glView *view,
153 static void draw_fg_layer (glView *view,
155 static void draw_highlight_layer (glView *view,
157 static void draw_select_region_layer (glView *view,
160 static void set_zoom_real (glView *view,
162 gboolean scale_to_fit_flag);
164 static gboolean focus_in_event_cb (glView *view,
165 GdkEventFocus *event);
167 static gboolean focus_out_event_cb (glView *view,
168 GdkEventFocus *event);
170 static gboolean enter_notify_event_cb (glView *view,
171 GdkEventCrossing *event);
173 static gboolean leave_notify_event_cb (glView *view,
174 GdkEventCrossing *event);
176 static gboolean motion_notify_event_cb (glView *view,
177 GdkEventMotion *event);
179 static gboolean button_press_event_cb (glView *view,
180 GdkEventButton *event);
182 static gboolean button_release_event_cb (glView *view,
183 GdkEventButton *event);
185 static gboolean key_press_event_cb (glView *view,
188 static void resize_event (glView *view,
193 /****************************************************************************/
194 /* Boilerplate Object stuff. */
195 /****************************************************************************/
196 G_DEFINE_TYPE (glView, gl_view, GTK_TYPE_VBOX)
200 gl_view_class_init (glViewClass *class)
202 GObjectClass *object_class = G_OBJECT_CLASS (class);
204 gl_debug (DEBUG_VIEW, "START");
206 gl_view_parent_class = g_type_class_peek_parent (class);
208 object_class->finalize = gl_view_finalize;
210 signals[CONTEXT_MENU_ACTIVATE] =
211 g_signal_new ("context_menu_activate",
212 G_OBJECT_CLASS_TYPE (object_class),
214 G_STRUCT_OFFSET (glViewClass, context_menu_activate),
216 gl_marshal_VOID__INT_UINT,
218 2, G_TYPE_INT, G_TYPE_UINT);
220 signals[ZOOM_CHANGED] =
221 g_signal_new ("zoom_changed",
222 G_OBJECT_CLASS_TYPE (object_class),
224 G_STRUCT_OFFSET (glViewClass, zoom_changed),
226 gl_marshal_VOID__DOUBLE,
230 signals[POINTER_MOVED] =
231 g_signal_new ("pointer_moved",
232 G_OBJECT_CLASS_TYPE (object_class),
234 G_STRUCT_OFFSET (glViewClass, pointer_moved),
236 gl_marshal_VOID__DOUBLE_DOUBLE,
238 2, G_TYPE_DOUBLE, G_TYPE_DOUBLE);
240 signals[POINTER_EXIT] =
241 g_signal_new ("pointer_exit",
242 G_OBJECT_CLASS_TYPE (object_class),
244 G_STRUCT_OFFSET (glViewClass, pointer_exit),
246 gl_marshal_VOID__VOID,
250 signals[MODE_CHANGED] =
251 g_signal_new ("mode_changed",
252 G_OBJECT_CLASS_TYPE (object_class),
254 G_STRUCT_OFFSET (glViewClass, mode_changed),
256 gl_marshal_VOID__VOID,
260 gl_debug (DEBUG_VIEW, "END");
265 gl_view_init (glView *view)
271 gl_debug (DEBUG_VIEW, "START");
273 units = gl_prefs_model_get_units (gl_prefs);
276 view->grid_visible = TRUE;
277 view->grid_spacing = gl_units_util_get_grid_size (units);
278 view->markup_visible = TRUE;
279 view->mode = GL_VIEW_MODE_ARROW;
281 view->home_scale = get_home_scale (view);
286 view->canvas = gtk_layout_new (NULL, NULL);
287 wscroll = gtk_scrolled_window_new (NULL, NULL);
288 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (wscroll),
289 GTK_POLICY_AUTOMATIC,
290 GTK_POLICY_AUTOMATIC);
291 gtk_box_pack_start (GTK_BOX (view), wscroll, TRUE, TRUE, 0);
292 gtk_container_add (GTK_CONTAINER (wscroll), view->canvas);
294 bg_color = gl_color_to_gdk_color (BG_COLOR);
295 gtk_widget_modify_bg (GTK_WIDGET (view->canvas), GTK_STATE_NORMAL, bg_color);
298 gtk_widget_set_can_focus (GTK_WIDGET (view->canvas), TRUE);
300 gtk_widget_add_events (GTK_WIDGET (view->canvas),
301 (GDK_FOCUS_CHANGE_MASK |
302 GDK_ENTER_NOTIFY_MASK |
303 GDK_LEAVE_NOTIFY_MASK |
304 GDK_POINTER_MOTION_MASK |
305 GDK_BUTTON_PRESS_MASK |
306 GDK_BUTTON_RELEASE_MASK |
307 GDK_KEY_PRESS_MASK));
309 g_signal_connect_swapped (G_OBJECT (gl_prefs), "changed",
310 G_CALLBACK (prefs_changed_cb), view);
311 g_signal_connect_swapped (G_OBJECT (view->canvas), "draw",
312 G_CALLBACK (draw_cb), view);
313 g_signal_connect_swapped (G_OBJECT (view->canvas), "realize",
314 G_CALLBACK (realize_cb), view);
315 g_signal_connect_swapped (G_OBJECT (view->canvas), "size-allocate",
316 G_CALLBACK (size_allocate_cb), view);
317 g_signal_connect_swapped (G_OBJECT (view->canvas), "screen-changed",
318 G_CALLBACK (screen_changed_cb), view);
319 g_signal_connect_swapped (G_OBJECT (view->canvas), "focus-in-event",
320 G_CALLBACK (focus_in_event_cb), view);
321 g_signal_connect_swapped (G_OBJECT (view->canvas), "focus-out-event",
322 G_CALLBACK (focus_out_event_cb), view);
323 g_signal_connect_swapped (G_OBJECT (view->canvas), "enter-notify-event",
324 G_CALLBACK (enter_notify_event_cb), view);
325 g_signal_connect_swapped (G_OBJECT (view->canvas), "leave-notify-event",
326 G_CALLBACK (leave_notify_event_cb), view);
327 g_signal_connect_swapped (G_OBJECT (view->canvas), "motion-notify-event",
328 G_CALLBACK (motion_notify_event_cb), view);
329 g_signal_connect_swapped (G_OBJECT (view->canvas), "button-press-event",
330 G_CALLBACK (button_press_event_cb), view);
331 g_signal_connect_swapped (G_OBJECT (view->canvas), "button-release-event",
332 G_CALLBACK (button_release_event_cb), view);
333 g_signal_connect_swapped (G_OBJECT (view->canvas), "key-press-event",
334 G_CALLBACK (key_press_event_cb), view);
336 gl_debug (DEBUG_VIEW, "END");
341 gl_view_finalize (GObject *object)
343 glView *view = GL_VIEW (object);
345 gl_debug (DEBUG_VIEW, "START");
347 g_return_if_fail (object != NULL);
348 g_return_if_fail (GL_IS_VIEW (view));
350 g_signal_handlers_disconnect_by_func (G_OBJECT (gl_prefs),
351 G_CALLBACK (prefs_changed_cb), view);
353 G_OBJECT_CLASS (gl_view_parent_class)->finalize (object);
355 gl_debug (DEBUG_VIEW, "END");
359 /****************************************************************************/
360 /* NEW view object. */
361 /****************************************************************************/
363 gl_view_new (glLabel *label)
367 gl_debug (DEBUG_VIEW, "START");
369 g_return_val_if_fail (label && GL_IS_LABEL (label), NULL);
371 view = g_object_new (GL_TYPE_VIEW, NULL);
373 gl_view_construct (view, label);
375 gl_debug (DEBUG_VIEW, "END");
377 return GTK_WIDGET (view);
381 /*---------------------------------------------------------------------------*/
382 /* PRIVATE. Construct composite widget. */
383 /*---------------------------------------------------------------------------*/
385 gl_view_construct (glView *view,
388 gl_debug (DEBUG_VIEW, "START");
390 g_return_if_fail (GL_IS_VIEW (view));
394 g_signal_connect_swapped (G_OBJECT (view->label), "selection_changed",
395 G_CALLBACK (label_changed_cb), view);
396 g_signal_connect_swapped (G_OBJECT (view->label), "changed",
397 G_CALLBACK (label_changed_cb), view);
398 g_signal_connect_swapped (G_OBJECT (view->label), "size_changed",
399 G_CALLBACK (label_resized_cb), view);
401 gl_debug (DEBUG_VIEW, "END");
405 /*---------------------------------------------------------------------------*/
406 /* PRIAVTE. Calculate 1:1 scale for screen. */
407 /*---------------------------------------------------------------------------*/
409 get_home_scale (glView *view)
412 gdouble screen_width_pixels;
413 gdouble screen_width_mm;
414 gdouble screen_height_pixels;
415 gdouble screen_height_mm;
416 gdouble x_pixels_per_mm;
417 gdouble y_pixels_per_mm;
420 if (view->canvas == NULL) return 1.0;
422 if (!gtk_widget_has_screen (GTK_WIDGET (view->canvas))) return 1.0;
424 screen = gtk_widget_get_screen (GTK_WIDGET (view->canvas));
426 gl_debug (DEBUG_VIEW, "Screen = %p", screen);
428 screen_width_pixels = gdk_screen_get_width (screen);
429 screen_width_mm = gdk_screen_get_width_mm (screen);
430 screen_height_pixels = gdk_screen_get_height (screen);
431 screen_height_mm = gdk_screen_get_height_mm (screen);
433 x_pixels_per_mm = screen_width_pixels / screen_width_mm;
434 y_pixels_per_mm = screen_height_pixels / screen_height_mm;
436 gl_debug (DEBUG_VIEW, "Horizontal dot pitch: %g pixels/mm (%g dpi)",
437 x_pixels_per_mm, x_pixels_per_mm * 25.4);
438 gl_debug (DEBUG_VIEW, "Vertical dot pitch: %g pixels/mm (%g dpi)",
439 y_pixels_per_mm, y_pixels_per_mm * 25.4);
441 scale = (x_pixels_per_mm + y_pixels_per_mm) / 2.0;
443 gl_debug (DEBUG_VIEW, "Average dot pitch: %g pixels/mm (%g dpi)",
444 scale, scale * 25.4);
446 scale /= POINTS_PER_MM;
448 gl_debug (DEBUG_VIEW, "Scale = %g pixels/point", scale);
450 /* Make sure scale is somewhat sane. */
451 if ( (scale < 0.25) || (scale > 4.0) ) return 1.0;
457 /*---------------------------------------------------------------------------*/
458 /* Prefs "changed" callback. */
459 /*---------------------------------------------------------------------------*/
461 prefs_changed_cb (glView *view)
465 units = gl_prefs_model_get_units (gl_prefs);
466 view->grid_spacing = gl_units_util_get_grid_size (units);
468 gl_view_update (view);
472 /*---------------------------------------------------------------------------*/
473 /* Schedule canvas update. */
474 /*---------------------------------------------------------------------------*/
476 gl_view_update (glView *view)
479 GtkAllocation allocation;
481 gl_debug (DEBUG_VIEW, "START");
483 window = gtk_widget_get_window (GTK_WIDGET (view->canvas));
488 if ( !view->update_scheduled_flag )
490 view->update_scheduled_flag = TRUE;
494 allocation.width = gtk_widget_get_allocated_width (view->canvas);
495 allocation.height = gtk_widget_get_allocated_height (view->canvas);
496 gdk_window_invalidate_rect (window, &allocation, TRUE);
501 gl_debug (DEBUG_VIEW, "END");
505 /*---------------------------------------------------------------------------*/
506 /* Schedule canvas region update. */
507 /*---------------------------------------------------------------------------*/
509 gl_view_update_region (glView *view,
511 glLabelRegion *region)
517 gl_debug (DEBUG_VIEW, "START");
519 window = gtk_widget_get_window (GTK_WIDGET (view->canvas));
523 x = MIN (region->x1, region->x2);
524 y = MIN (region->y1, region->y2);
525 w = fabs (region->x2 - region->x1);
526 h = fabs (region->y2 - region->y1);
528 cairo_user_to_device (cr, &x, &y);
529 cairo_user_to_device_distance (cr, &w, &h);
536 gdk_window_invalidate_rect (window, &rect, TRUE);
538 gl_debug (DEBUG_VIEW, "END");
542 /*---------------------------------------------------------------------------*/
543 /* PRIVATE. Expose handler. */
544 /*---------------------------------------------------------------------------*/
546 draw_cb (glView *view,
549 GdkWindow *bin_window;
552 gl_debug (DEBUG_VIEW, "START");
554 view->update_scheduled_flag = FALSE;
556 bin_window = gtk_layout_get_bin_window (GTK_LAYOUT (view->canvas));
557 bin_cr = gdk_cairo_create (bin_window);
559 draw_layers (view, bin_cr);
561 cairo_destroy (bin_cr);
563 gl_debug (DEBUG_VIEW, "END");
569 /*---------------------------------------------------------------------------*/
570 /* PRIVATE. Realize handler. */
571 /*---------------------------------------------------------------------------*/
573 realize_cb (glView *view)
575 g_return_if_fail (view && GL_IS_VIEW (view));
577 gl_debug (DEBUG_VIEW, "START");
579 if (view->zoom_to_fit_flag) {
580 /* Maintain best fit zoom */
581 gl_view_zoom_to_fit (view);
584 gl_debug (DEBUG_VIEW, "END");
588 /*---------------------------------------------------------------------------*/
589 /* PRIVATE. Size allocation changed callback. */
590 /*---------------------------------------------------------------------------*/
592 size_allocate_cb (glView *view,
593 GtkAllocation *allocation)
595 GtkAdjustment *hadjustment;
596 GtkAdjustment *vadjustment;
598 gl_debug (DEBUG_VIEW, "START");
600 hadjustment = gtk_layout_get_hadjustment(GTK_LAYOUT (view->canvas));
601 vadjustment = gtk_layout_get_vadjustment(GTK_LAYOUT (view->canvas));
603 gtk_adjustment_set_page_size( hadjustment, allocation->width);
604 gtk_adjustment_set_page_increment( hadjustment, allocation->width / 2);
606 gtk_adjustment_set_page_size( vadjustment, allocation->height);
607 gtk_adjustment_set_page_increment( vadjustment, allocation->height / 2);
609 g_signal_emit_by_name (hadjustment, "changed");
610 g_signal_emit_by_name (vadjustment, "changed");
612 if (view->zoom_to_fit_flag) {
613 /* Maintain best fit zoom */
614 gl_view_zoom_to_fit (view);
617 gl_debug (DEBUG_VIEW, "END");
621 /*---------------------------------------------------------------------------*/
622 /* PRIVATE. Screen changed callback. */
623 /*---------------------------------------------------------------------------*/
625 screen_changed_cb (glView *view)
627 gl_debug (DEBUG_VIEW, "START");
629 if (gtk_widget_has_screen (GTK_WIDGET (view->canvas))) {
631 view->home_scale = get_home_scale (view);
633 if (view->zoom_to_fit_flag) {
634 /* Maintain best fit zoom */
635 gl_view_zoom_to_fit (view);
639 gl_debug (DEBUG_VIEW, "END");
643 /*---------------------------------------------------------------------------*/
644 /* PRIVATE. Handle label changed event. */
645 /*---------------------------------------------------------------------------*/
647 label_changed_cb (glView *view)
649 g_return_if_fail (view && GL_IS_VIEW (view));
651 gl_debug (DEBUG_VIEW, "START");
653 gl_view_update (view);
655 gl_debug (DEBUG_VIEW, "END");
659 /*---------------------------------------------------------------------------*/
660 /* PRIVATE. Handle label resize event. */
661 /*---------------------------------------------------------------------------*/
663 label_resized_cb (glView *view)
665 GtkAdjustment *hadjustment;
666 GtkAdjustment *vadjustment;
668 g_return_if_fail (view && GL_IS_VIEW (view));
670 gl_debug (DEBUG_VIEW, "START");
672 hadjustment = gtk_layout_get_hadjustment(GTK_LAYOUT (view->canvas));
673 vadjustment = gtk_layout_get_vadjustment(GTK_LAYOUT (view->canvas));
675 g_signal_emit_by_name (hadjustment, "changed");
676 g_signal_emit_by_name (vadjustment, "changed");
678 gl_view_update (view);
680 gl_debug (DEBUG_VIEW, "END");
684 /*---------------------------------------------------------------------------*/
685 /* PRIVATE. Create, draw and order layers. */
686 /*---------------------------------------------------------------------------*/
688 draw_layers (glView *view,
691 GdkWindow *bin_window;
694 gint canvas_w, canvas_h;
696 g_return_if_fail (view && GL_IS_VIEW (view));
697 g_return_if_fail (view->label && GL_IS_LABEL (view->label));
699 gl_debug (DEBUG_VIEW, "START");
701 bin_window = gtk_layout_get_bin_window (GTK_LAYOUT (view->canvas));
703 scale = view->zoom * view->home_scale;
705 gl_label_get_size (view->label, &w, &h);
707 scale = view->home_scale * view->zoom;
708 gtk_layout_set_size (GTK_LAYOUT (view->canvas), w*scale+8, h*scale+8);
710 canvas_w = gdk_window_get_width (bin_window);
711 canvas_h = gdk_window_get_height (bin_window);
713 view->x0 = (canvas_w/scale - w) / 2.0;
714 view->y0 = (canvas_h/scale - h) / 2.0;
720 cairo_scale (cr, scale, scale);
721 cairo_translate (cr, view->x0, view->y0);
723 draw_bg_layer (view, cr);
724 draw_grid_layer (view, cr);
725 draw_markup_layer (view, cr);
726 draw_objects_layer (view, cr);
727 draw_fg_layer (view, cr);
728 draw_highlight_layer (view, cr);
729 draw_select_region_layer (view, cr);
733 gl_debug (DEBUG_VIEW, "END");
738 /*---------------------------------------------------------------------------*/
739 /* PRIVATE. Draw background */
740 /*---------------------------------------------------------------------------*/
742 draw_bg_layer (glView *view,
746 const lglTemplate *template;
747 gboolean rotate_flag;
749 g_return_if_fail (view && GL_IS_VIEW (view));
750 g_return_if_fail (view->label && GL_IS_LABEL (view->label));
752 scale = view->home_scale * view->zoom;
754 template = gl_label_get_template (view->label);
755 rotate_flag = gl_label_get_rotate_flag (view->label);
758 cairo_translate (cr, SHADOW_OFFSET_PIXELS/scale, SHADOW_OFFSET_PIXELS/scale);
759 gl_cairo_label_path (cr, template, rotate_flag, FALSE);
760 cairo_set_source_rgb (cr, SHADOW_RGB_ARGS);
761 cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
765 gl_cairo_label_path (cr, template, rotate_flag, FALSE);
766 cairo_set_source_rgb (cr, PAPER_RGB_ARGS);
767 cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
772 /*---------------------------------------------------------------------------*/
773 /* PRIVATE. Draw grid lines. */
774 /*---------------------------------------------------------------------------*/
776 draw_grid_layer (glView *view,
779 const lglTemplate *template;
780 gboolean rotate_flag;
781 const lglTemplateFrame *frame;
786 gl_debug (DEBUG_VIEW, "START");
788 g_return_if_fail (view && GL_IS_VIEW (view));
789 g_return_if_fail (view->label && GL_IS_LABEL(view->label));
791 if (view->grid_visible)
794 template = gl_label_get_template (view->label);
795 rotate_flag = gl_label_get_rotate_flag (view->label);
796 frame = (lglTemplateFrame *)template->frames->data;
798 gl_label_get_size (view->label, &w, &h);
800 if (frame->shape == LGL_TEMPLATE_FRAME_SHAPE_RECT) {
801 x0 = view->grid_spacing;
802 y0 = view->grid_spacing;
804 /* round labels, adjust grid to line up with center of label. */
805 x0 = fmod (w/2.0, view->grid_spacing);
806 y0 = fmod (h/2.0, view->grid_spacing);
812 gl_cairo_label_path (cr, template, rotate_flag, FALSE);
815 cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
816 cairo_set_line_width (cr, GRID_LINE_WIDTH_PIXELS/(view->home_scale * view->zoom));
817 cairo_set_source_rgb (cr, GRID_RGB_ARGS);
819 for ( x=x0; x < w; x += view->grid_spacing )
821 cairo_move_to (cr, x, 0);
822 cairo_line_to (cr, x, h);
826 for ( y=y0; y < h; y += view->grid_spacing )
828 cairo_move_to (cr, 0, y);
829 cairo_line_to (cr, w, y);
837 gl_debug (DEBUG_VIEW, "END");
841 /*---------------------------------------------------------------------------*/
842 /* PRIVATE. Draw markup layer. */
843 /*---------------------------------------------------------------------------*/
845 draw_markup_layer (glView *view,
848 const lglTemplate *template;
849 const lglTemplateFrame *frame;
850 gboolean rotate_flag;
852 lglTemplateMarkup *markup;
853 gdouble width, height;
855 g_return_if_fail (view && GL_IS_VIEW (view));
856 g_return_if_fail (view->label && GL_IS_LABEL (view->label));
858 if (view->markup_visible)
861 template = gl_label_get_template (view->label);
862 frame = (lglTemplateFrame *)template->frames->data;
863 rotate_flag = gl_label_get_rotate_flag (view->label);
869 lgl_template_frame_get_size (frame, &width, &height);
870 cairo_rotate (cr, -G_PI/2.0);
871 cairo_translate (cr, -width, 0.0);
874 cairo_set_line_width (cr, MARKUP_LINE_WIDTH_PIXELS/(view->home_scale * view->zoom));
875 cairo_set_source_rgb (cr, MARKUP_RGB_ARGS);
877 for ( p=frame->all.markups; p != NULL; p=p->next )
879 markup = (lglTemplateMarkup *)p->data;
881 gl_cairo_markup_path (cr, markup, view->label);
892 /*---------------------------------------------------------------------------*/
893 /* PRIVATE. Draw objects layer. */
894 /*---------------------------------------------------------------------------*/
896 draw_objects_layer (glView *view,
899 gl_label_draw (view->label, cr, TRUE, NULL);
903 /*---------------------------------------------------------------------------*/
904 /* PRIVATE. Draw foreground */
905 /*---------------------------------------------------------------------------*/
907 draw_fg_layer (glView *view,
910 const lglTemplate *template;
911 gboolean rotate_flag;
913 g_return_if_fail (view && GL_IS_VIEW (view));
914 g_return_if_fail (view->label && GL_IS_LABEL (view->label));
916 template = gl_label_get_template (view->label);
917 rotate_flag = gl_label_get_rotate_flag (view->label);
919 gl_cairo_label_path (cr, template, rotate_flag, FALSE);
921 cairo_set_line_width (cr, OUTLINE_WIDTH_PIXELS/(view->home_scale * view->zoom));
922 cairo_set_source_rgb (cr, OUTLINE_RGB_ARGS);
927 /*---------------------------------------------------------------------------*/
928 /* PRIVATE. Create highlight layer. */
929 /*---------------------------------------------------------------------------*/
931 draw_highlight_layer (glView *view,
934 GList *selection_list;
936 glLabelObject *object;
938 g_return_if_fail (view && GL_IS_VIEW (view));
942 cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
944 selection_list = gl_label_get_selection_list (view->label);
946 for (p_obj = selection_list; p_obj != NULL; p_obj = p_obj->next)
948 object = GL_LABEL_OBJECT (p_obj->data);
950 gl_label_object_draw_handles (object, cr);
953 g_list_free (selection_list);
959 /*---------------------------------------------------------------------------*/
960 /* PRIVATE. Draw select region layer. */
961 /*---------------------------------------------------------------------------*/
963 draw_select_region_layer (glView *view,
969 g_return_if_fail (view && GL_IS_VIEW (view));
971 if (view->select_region_visible)
973 x1 = MIN (view->select_region.x1, view->select_region.x2);
974 y1 = MIN (view->select_region.y1, view->select_region.y2);
975 w = fabs (view->select_region.x2 - view->select_region.x1);
976 h = fabs (view->select_region.y2 - view->select_region.y1);
980 cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
982 cairo_rectangle (cr, x1, y1, w, h);
984 cairo_set_source_rgba (cr, SELECT_FILL_RGBA_ARGS);
985 cairo_fill_preserve (cr);
987 cairo_set_line_width (cr, SELECT_LINE_WIDTH_PIXELS/(view->home_scale * view->zoom));
988 cairo_set_source_rgba (cr, SELECT_LINE_RGBA_ARGS);
996 /*****************************************************************************/
998 /*****************************************************************************/
1000 gl_view_show_grid (glView *view)
1002 g_return_if_fail (view && GL_IS_VIEW (view));
1004 view->grid_visible = TRUE;
1005 gl_view_update (view);
1009 /*****************************************************************************/
1011 /*****************************************************************************/
1013 gl_view_hide_grid (glView *view)
1015 g_return_if_fail (view && GL_IS_VIEW (view));
1017 view->grid_visible = FALSE;
1018 gl_view_update (view);
1022 /*****************************************************************************/
1024 /*****************************************************************************/
1026 gl_view_show_markup (glView *view)
1028 g_return_if_fail (view && GL_IS_VIEW (view));
1030 view->markup_visible = TRUE;
1031 gl_view_update (view);
1035 /*****************************************************************************/
1037 /*****************************************************************************/
1039 gl_view_hide_markup (glView *view)
1041 g_return_if_fail (view && GL_IS_VIEW (view));
1043 view->markup_visible = FALSE;
1044 gl_view_update (view);
1048 /*****************************************************************************/
1049 /* Set arrow mode. */
1050 /*****************************************************************************/
1052 gl_view_arrow_mode (glView *view)
1057 gl_debug (DEBUG_VIEW, "START");
1059 g_return_if_fail (view && GL_IS_VIEW (view));
1061 window = gtk_widget_get_window (view->canvas);
1063 cursor = gdk_cursor_new (GDK_LEFT_PTR);
1064 gdk_window_set_cursor (window, cursor);
1065 gdk_cursor_unref (cursor);
1067 view->mode = GL_VIEW_MODE_ARROW;
1068 view->state = GL_VIEW_IDLE;
1070 gl_debug (DEBUG_VIEW, "END");
1074 /*****************************************************************************/
1075 /* Set create text object mode. */
1076 /*****************************************************************************/
1078 gl_view_object_create_mode (glView *view,
1079 glLabelObjectType type)
1082 GdkCursor *cursor = NULL;
1084 gl_debug (DEBUG_VIEW, "START");
1086 g_return_if_fail (view && GL_IS_VIEW (view));
1088 window = gtk_widget_get_window (view->canvas);
1092 case GL_LABEL_OBJECT_BOX:
1093 cursor = gl_view_box_get_create_cursor ();
1095 case GL_LABEL_OBJECT_ELLIPSE:
1096 cursor = gl_view_ellipse_get_create_cursor ();
1098 case GL_LABEL_OBJECT_LINE:
1099 cursor = gl_view_line_get_create_cursor ();
1101 case GL_LABEL_OBJECT_IMAGE:
1102 cursor = gl_view_image_get_create_cursor ();
1104 case GL_LABEL_OBJECT_TEXT:
1105 cursor = gl_view_text_get_create_cursor ();
1107 case GL_LABEL_OBJECT_BARCODE:
1108 cursor = gl_view_barcode_get_create_cursor ();
1111 g_message ("Invalid label object type.");/*Should not happen!*/
1115 gdk_window_set_cursor (window, cursor);
1116 gdk_cursor_unref (cursor);
1118 view->mode = GL_VIEW_MODE_OBJECT_CREATE;
1119 view->state = GL_VIEW_IDLE;
1120 view->create_type = type;
1122 gl_debug (DEBUG_VIEW, "END");
1126 /*****************************************************************************/
1127 /* Zoom in one "notch" */
1128 /*****************************************************************************/
1130 gl_view_zoom_in (glView *view)
1133 gdouble dist, dist_min;
1135 gl_debug (DEBUG_VIEW, "START");
1137 g_return_if_fail (view && GL_IS_VIEW (view));
1139 /* Find index of current scale (or best match) */
1140 i_min = 1; /* start with 2nd largest scale */
1141 dist_min = fabs (zooms[1] - view->zoom);
1142 for (i = 2; i < N_ZOOMS; i++) {
1143 dist = fabs (zooms[i] - view->zoom);
1144 if (dist < dist_min) {
1150 /* zoom in one "notch" */
1151 i = MAX (0, i_min - 1);
1152 gl_debug (DEBUG_VIEW, "zoom[%d] = %g", i, zooms[i]);
1153 set_zoom_real (view, zooms[i], FALSE);
1155 gl_debug (DEBUG_VIEW, "END");
1159 /*****************************************************************************/
1160 /* Zoom out one "notch" */
1161 /*****************************************************************************/
1163 gl_view_zoom_out (glView *view)
1166 gdouble dist, dist_min;
1168 gl_debug (DEBUG_VIEW, "START");
1170 g_return_if_fail (view && GL_IS_VIEW (view));
1172 /* Find index of current scale (or best match) */
1173 i_min = 0; /* start with largest scale */
1174 dist_min = fabs (zooms[0] - view->zoom);
1175 for (i = 1; i < N_ZOOMS; i++) {
1176 dist = fabs (zooms[i] - view->zoom);
1177 if (dist < dist_min) {
1183 /* zoom out one "notch" */
1184 if (i_min >= N_ZOOMS)
1189 set_zoom_real (view, zooms[i], FALSE);
1191 gl_debug (DEBUG_VIEW, "END");
1195 /*****************************************************************************/
1196 /* Set zoom to best fit. */
1197 /*****************************************************************************/
1199 gl_view_zoom_to_fit (glView *view)
1201 GtkAllocation allocation;
1202 gint w_view, h_view;
1203 gdouble w_label, h_label;
1204 gdouble x_scale, y_scale, scale;
1206 gl_debug (DEBUG_VIEW, "");
1208 if ( ! gtk_widget_get_window (GTK_WIDGET (view)) ) {
1209 /* Delay until realized. */
1210 view->zoom_to_fit_flag = TRUE;
1214 gtk_widget_get_allocation (GTK_WIDGET (view), &allocation);
1215 w_view = allocation.width;
1216 h_view = allocation.height;
1218 gl_label_get_size (GL_LABEL(view->label), &w_label, &h_label);
1220 gl_debug (DEBUG_VIEW, "View size: %d, %d", w_view, h_view);
1221 gl_debug (DEBUG_VIEW, "Label size: %g, %g", w_label, h_label);
1223 /* Calculate best scale */
1224 x_scale = (double)(w_view - ZOOMTOFIT_PAD) / w_label;
1225 y_scale = (double)(h_view - ZOOMTOFIT_PAD) / h_label;
1226 scale = MIN (x_scale, y_scale);
1227 gl_debug (DEBUG_VIEW, "Candidate zooms: %g, %g => %g", x_scale, y_scale, scale);
1230 gl_debug (DEBUG_VIEW, "Scale: %g", scale);
1231 scale = MIN (scale, zooms[0]*view->home_scale);
1232 scale = MAX (scale, zooms[N_ZOOMS-1]*view->home_scale);
1233 gl_debug (DEBUG_VIEW, "Limitted scale: %g", scale);
1235 set_zoom_real (view, scale/view->home_scale, TRUE);
1239 /*****************************************************************************/
1240 /* Set current zoom factor to explicit value. */
1241 /*****************************************************************************/
1243 gl_view_set_zoom (glView *view,
1246 gl_debug (DEBUG_VIEW, "START");
1248 set_zoom_real (view, zoom, FALSE);
1250 gl_debug (DEBUG_VIEW, "END");
1254 /*---------------------------------------------------------------------------*/
1255 /* PRIVATE. Set canvas scale. */
1256 /*---------------------------------------------------------------------------*/
1258 set_zoom_real (glView *view,
1260 gboolean zoom_to_fit_flag)
1262 gl_debug (DEBUG_VIEW, "START");
1264 g_return_if_fail (view && GL_IS_VIEW (view));
1265 g_return_if_fail (zoom > 0.0);
1267 /* Limit, if needed */
1268 gl_debug (DEBUG_VIEW, "Zoom requested: %g", zoom);
1269 zoom = MIN (zoom, zooms[0]);
1270 zoom = MAX (zoom, zooms[N_ZOOMS-1]);
1271 gl_debug (DEBUG_VIEW, "Limitted zoom: %g", zoom);
1273 if ( zoom != view->zoom ) {
1276 view->zoom_to_fit_flag = zoom_to_fit_flag;
1278 gl_view_update (view);
1280 g_signal_emit (G_OBJECT(view), signals[ZOOM_CHANGED], 0, zoom);
1284 gl_debug (DEBUG_VIEW, "END");
1289 /*****************************************************************************/
1290 /* Get current zoom factor. */
1291 /*****************************************************************************/
1293 gl_view_get_zoom (glView *view)
1295 gl_debug (DEBUG_VIEW, "");
1297 g_return_val_if_fail (view && GL_IS_VIEW (view), 1.0);
1303 /*****************************************************************************/
1304 /* Is this the maximum zoom level. */
1305 /*****************************************************************************/
1307 gl_view_is_zoom_max (glView *view)
1309 gl_debug (DEBUG_VIEW, "");
1311 g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
1313 return view->zoom >= zooms[0];
1317 /*****************************************************************************/
1318 /* Is this the minimum zoom level. */
1319 /*****************************************************************************/
1321 gl_view_is_zoom_min (glView *view)
1323 gl_debug (DEBUG_VIEW, "");
1325 g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
1327 return view->zoom <= zooms[N_ZOOMS-1];
1331 /*---------------------------------------------------------------------------*/
1332 /* PRIVATE. Focus in event handler. */
1333 /*---------------------------------------------------------------------------*/
1335 focus_in_event_cb (glView *view,
1336 GdkEventFocus *event)
1342 /*---------------------------------------------------------------------------*/
1343 /* PRIVATE. Focus out event handler. */
1344 /*---------------------------------------------------------------------------*/
1346 focus_out_event_cb (glView *view,
1347 GdkEventFocus *event)
1353 /*---------------------------------------------------------------------------*/
1354 /* PRIVATE. Enter notify event handler. */
1355 /*---------------------------------------------------------------------------*/
1357 enter_notify_event_cb (glView *view,
1358 GdkEventCrossing *event)
1364 /*---------------------------------------------------------------------------*/
1365 /* PRIVATE. Leave notify event handler. */
1366 /*---------------------------------------------------------------------------*/
1368 leave_notify_event_cb (glView *view,
1369 GdkEventCrossing *event)
1372 g_signal_emit (G_OBJECT(view), signals[POINTER_EXIT], 0);
1378 /*---------------------------------------------------------------------------*/
1379 /* PRIVATE. Motion notify event handler. */
1380 /*---------------------------------------------------------------------------*/
1382 motion_notify_event_cb (glView *view,
1383 GdkEventMotion *event)
1385 gboolean return_value = FALSE;
1386 GdkWindow *bin_window;
1392 glLabelObjectHandle handle;
1394 bin_window = gtk_layout_get_bin_window (GTK_LAYOUT (view->canvas));
1395 window = gtk_widget_get_window (view->canvas);
1397 cr = gdk_cairo_create (bin_window);
1400 * Translate to label coordinates
1402 scale = view->zoom * view->home_scale;
1403 cairo_scale (cr, scale, scale);
1404 cairo_translate (cr, view->x0, view->y0);
1408 cairo_device_to_user (cr, &x, &y);
1411 * Emit signal regardless of mode
1413 g_signal_emit (G_OBJECT(view), signals[POINTER_MOVED], 0, x, y);
1416 * Handle event as appropriate for mode
1421 case GL_VIEW_MODE_ARROW:
1422 switch (view->state)
1426 if ( gl_label_is_selection_atomic (view->label) &&
1427 gl_label_get_handle_at (view->label, cr, event->x, event->y, &handle) )
1429 cursor = gdk_cursor_new (GDK_CROSSHAIR);
1431 else if (gl_label_object_at (view->label, cr, event->x, event->y))
1433 cursor = gdk_cursor_new (GDK_FLEUR);
1437 cursor = gdk_cursor_new (GDK_LEFT_PTR);
1439 gdk_window_set_cursor (window, cursor);
1440 gdk_cursor_unref (cursor);
1443 case GL_VIEW_ARROW_SELECT_REGION:
1445 gl_view_update_region (view, cr, &view->select_region);
1447 view->select_region.x2 = x;
1448 view->select_region.y2 = y;
1450 gl_view_update_region (view, cr, &view->select_region);
1452 gl_view_update (view);
1456 case GL_VIEW_ARROW_MOVE:
1457 gl_label_move_selection (view->label,
1458 (x - view->move_last_x),
1459 (y - view->move_last_y));
1460 view->move_last_x = x;
1461 view->move_last_y = y;
1464 case GL_VIEW_ARROW_RESIZE:
1465 resize_event (view, cr, event->x, event->y);
1469 g_message ("Invalid arrow state."); /*Should not happen!*/
1471 return_value = TRUE;
1475 case GL_VIEW_MODE_OBJECT_CREATE:
1476 if (view->state != GL_VIEW_IDLE)
1478 switch (view->create_type)
1480 case GL_LABEL_OBJECT_BOX:
1481 gl_view_box_create_motion_event (view, x, y);
1483 case GL_LABEL_OBJECT_ELLIPSE:
1484 gl_view_ellipse_create_motion_event (view, x, y);
1486 case GL_LABEL_OBJECT_LINE:
1487 gl_view_line_create_motion_event (view, x, y);
1489 case GL_LABEL_OBJECT_IMAGE:
1490 gl_view_image_create_motion_event (view, x, y);
1492 case GL_LABEL_OBJECT_TEXT:
1493 gl_view_text_create_motion_event (view, x, y);
1495 case GL_LABEL_OBJECT_BARCODE:
1496 gl_view_barcode_create_motion_event (view, x, y);
1499 g_message ("Invalid create type."); /*Should not happen!*/
1506 g_message ("Invalid view mode."); /*Should not happen!*/
1513 * FIXME: we re-establish grabs here if the grab has been lost. We seem to be
1514 * losing grabs when we emit signals that lead to the manipulation of
1515 * the GtkUIManager. Needs more investigation
1517 if (view->grabbed_flag && !gdk_pointer_is_grabbed ())
1519 gdk_pointer_grab (bin_window,
1521 (GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK),
1527 return return_value;
1531 /*---------------------------------------------------------------------------*/
1532 /* PRIVATE. Button press event handler. */
1533 /*---------------------------------------------------------------------------*/
1535 button_press_event_cb (glView *view,
1536 GdkEventButton *event)
1538 gboolean return_value = FALSE;
1539 GdkWindow *bin_window;
1543 glLabelObject *object;
1544 glLabelObjectHandle handle;
1546 gtk_widget_grab_focus(GTK_WIDGET (view->canvas));
1548 bin_window = gtk_layout_get_bin_window (GTK_LAYOUT (view->canvas));
1550 cr = gdk_cairo_create (bin_window);
1553 * Translate to label coordinates
1555 scale = view->zoom * view->home_scale;
1556 cairo_scale (cr, scale, scale);
1557 cairo_translate (cr, view->x0, view->y0);
1561 cairo_device_to_user (cr, &x, &y);
1563 switch (event->button)
1568 * Handle event as appropriate for mode
1572 case GL_VIEW_MODE_ARROW:
1573 if ( gl_label_is_selection_atomic (view->label) &&
1574 (object = gl_label_get_handle_at (view->label, cr, event->x, event->y, &handle)) )
1576 view->resize_object = object;
1577 view->resize_handle = handle;
1578 view->resize_honor_aspect = event->state & GDK_CONTROL_MASK;
1580 view->state = GL_VIEW_ARROW_RESIZE;
1582 else if ((object = gl_label_object_at (view->label, cr, event->x, event->y)))
1584 if (event->state & GDK_CONTROL_MASK)
1586 if (gl_label_object_is_selected (object))
1588 /* Un-selecting a selected item */
1589 gl_label_unselect_object (view->label, object);
1591 /* Add to current selection */
1592 gl_label_select_object (view->label, object);
1597 if (!gl_label_object_is_selected (object))
1599 /* remove any selections before adding */
1600 gl_label_unselect_all (view->label);
1601 /* Add to current selection */
1602 gl_label_select_object (view->label, object);
1605 view->move_last_x = x;
1606 view->move_last_y = y;
1608 view->state = GL_VIEW_ARROW_MOVE;
1612 if (!(event->state & GDK_CONTROL_MASK))
1614 gl_label_unselect_all (view->label);
1617 view->select_region_visible = TRUE;
1618 view->select_region.x1 = x;
1619 view->select_region.y1 = y;
1620 view->select_region.x2 = x;
1621 view->select_region.y2 = y;
1623 view->state = GL_VIEW_ARROW_SELECT_REGION;
1627 return_value = TRUE;
1630 case GL_VIEW_MODE_OBJECT_CREATE:
1631 switch (view->create_type)
1633 case GL_LABEL_OBJECT_BOX:
1634 gl_view_box_create_button_press_event (view, x, y);
1636 case GL_LABEL_OBJECT_ELLIPSE:
1637 gl_view_ellipse_create_button_press_event (view, x, y);
1639 case GL_LABEL_OBJECT_LINE:
1640 gl_view_line_create_button_press_event (view, x, y);
1642 case GL_LABEL_OBJECT_IMAGE:
1643 gl_view_image_create_button_press_event (view, x, y);
1645 case GL_LABEL_OBJECT_TEXT:
1646 gl_view_text_create_button_press_event (view, x, y);
1648 case GL_LABEL_OBJECT_BARCODE:
1649 gl_view_barcode_create_button_press_event (view, x, y);
1652 g_message ("Invalid create type."); /*Should not happen!*/
1654 view->state = GL_VIEW_CREATE_DRAG;
1655 return_value = TRUE;
1659 g_message ("Invalid view mode."); /*Should not happen!*/
1662 view->grabbed_flag = TRUE;
1663 gdk_pointer_grab (bin_window,
1665 (GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK),
1672 g_signal_emit (G_OBJECT (view),
1673 signals[CONTEXT_MENU_ACTIVATE], 0,
1674 event->button, event->time);
1675 return_value = TRUE;
1682 return return_value;
1686 /*---------------------------------------------------------------------------*/
1687 /* PRIVATE. Button release event handler. */
1688 /*---------------------------------------------------------------------------*/
1690 button_release_event_cb (glView *view,
1691 GdkEventButton *event)
1693 gboolean return_value = FALSE;
1694 GdkWindow *bin_window;
1701 bin_window = gtk_layout_get_bin_window (GTK_LAYOUT (view->canvas));
1702 window = gtk_widget_get_window (view->canvas);
1704 cr = gdk_cairo_create (bin_window);
1707 * Translate to label coordinates
1709 scale = view->zoom * view->home_scale;
1710 cairo_scale (cr, scale, scale);
1711 cairo_translate (cr, view->x0, view->y0);
1715 cairo_device_to_user (cr, &x, &y);
1717 switch (event->button)
1721 view->grabbed_flag = FALSE;
1722 gdk_pointer_ungrab (event->time);
1724 * Handle event as appropriate for mode
1728 case GL_VIEW_MODE_ARROW:
1729 switch (view->state)
1731 case GL_VIEW_ARROW_RESIZE:
1732 view->resize_object = NULL;
1734 view->state = GL_VIEW_IDLE;
1737 case GL_VIEW_ARROW_SELECT_REGION:
1739 gl_view_update_region (view, cr, &view->select_region);
1741 gl_view_update (view);
1744 view->select_region_visible = FALSE;
1745 view->select_region.x2 = x;
1746 view->select_region.y2 = y;
1748 gl_label_select_region (view->label, &view->select_region);
1750 view->state = GL_VIEW_IDLE;
1754 view->state = GL_VIEW_IDLE;
1759 return_value = TRUE;
1763 case GL_VIEW_MODE_OBJECT_CREATE:
1764 switch (view->create_type)
1766 case GL_LABEL_OBJECT_BOX:
1767 gl_view_box_create_button_release_event (view, x, y);
1769 case GL_LABEL_OBJECT_ELLIPSE:
1770 gl_view_ellipse_create_button_release_event (view, x, y);
1772 case GL_LABEL_OBJECT_LINE:
1773 gl_view_line_create_button_release_event (view, x, y);
1775 case GL_LABEL_OBJECT_IMAGE:
1776 gl_view_image_create_button_release_event (view, x, y);
1778 case GL_LABEL_OBJECT_TEXT:
1779 gl_view_text_create_button_release_event (view, x, y);
1781 case GL_LABEL_OBJECT_BARCODE:
1782 gl_view_barcode_create_button_release_event (view, x, y);
1785 g_message ("Invalid create type."); /*Should not happen!*/
1787 view->mode = GL_VIEW_MODE_ARROW;
1788 view->state = GL_VIEW_IDLE;
1789 cursor = gdk_cursor_new (GDK_LEFT_PTR);
1790 gdk_window_set_cursor (window, cursor);
1791 gdk_cursor_unref (cursor);
1793 gl_label_select_object (view->label, view->create_object);
1798 g_message ("Invalid view mode."); /*Should not happen!*/
1805 return return_value;
1809 /*---------------------------------------------------------------------------*/
1810 /* PRIVATE. Key press event handler. */
1811 /*---------------------------------------------------------------------------*/
1813 key_press_event_cb (glView *view,
1819 gl_debug (DEBUG_VIEW, "");
1821 window = gtk_widget_get_window (view->canvas);
1823 if ( (view->mode == GL_VIEW_MODE_ARROW) &&
1824 (view->state == GL_VIEW_IDLE) )
1826 switch (event->keyval) {
1829 case GDK_KEY_KP_Left:
1830 gl_label_move_selection (view->label, -1.0 / (view->zoom), 0.0);
1834 gl_label_move_selection (view->label, 0.0, -1.0 / (view->zoom));
1837 case GDK_KEY_KP_Right:
1838 gl_label_move_selection (view->label, 1.0 / (view->zoom), 0.0);
1841 case GDK_KEY_KP_Down:
1842 gl_label_move_selection (view->label, 0.0, 1.0 / (view->zoom));
1844 case GDK_KEY_Delete:
1845 case GDK_KEY_KP_Delete:
1846 gl_label_delete_selection (view->label);
1847 cursor = gdk_cursor_new (GDK_LEFT_PTR);
1848 gdk_window_set_cursor (window, cursor);
1849 gdk_cursor_unref (cursor);
1856 return TRUE; /* We handled this or we were dragging. */
1860 /*---------------------------------------------------------------------------*/
1861 /* PRIVATE. Resize object. */
1862 /*---------------------------------------------------------------------------*/
1864 resize_event (glView *view,
1869 cairo_matrix_t matrix;
1870 gdouble x0, y0, x1, y1, x2, y2;
1874 gl_debug (DEBUG_VIEW, "x,y world = %g, %g", x, y);
1877 * Change to item relative coordinates
1880 gl_label_object_get_position (view->resize_object, &x0, &y0);
1881 cairo_translate (cr, x0, y0);
1882 gl_label_object_get_matrix (view->resize_object, &matrix);
1883 cairo_transform (cr, &matrix);
1886 * Initialize origin and 2 corners in object relative coordinates.
1894 gl_label_object_get_size (view->resize_object, &x2, &y2);
1896 gl_debug (DEBUG_VIEW, "x0,y0 object = %g, %g", x0, y0);
1897 gl_debug (DEBUG_VIEW, "x1,y1 object = %g, %g", x1, y1);
1898 gl_debug (DEBUG_VIEW, "x2,y2 object = %g, %g", x2, y2);
1901 * Translate x,y into object relative coordinates.
1903 cairo_device_to_user (cr, &x, &y);
1905 gl_debug (DEBUG_VIEW, "x,y object = %g, %g", x, y);
1910 switch (view->resize_handle)
1913 case GL_LABEL_OBJECT_HANDLE_NW:
1914 w = MAX (x2 - x, 0);
1915 h = MAX (y2 - y, 0);
1918 case GL_LABEL_OBJECT_HANDLE_N:
1920 h = MAX (y2 - y, 0);
1923 case GL_LABEL_OBJECT_HANDLE_NE:
1924 w = MAX (x - x1, 0);
1925 h = MAX (y2 - y, 0);
1928 case GL_LABEL_OBJECT_HANDLE_E:
1929 w = MAX (x - x1, 0);
1933 case GL_LABEL_OBJECT_HANDLE_SE:
1934 w = MAX (x - x1, 0);
1935 h = MAX (y - y1, 0);
1938 case GL_LABEL_OBJECT_HANDLE_S:
1940 h = MAX (y - y1, 0);
1943 case GL_LABEL_OBJECT_HANDLE_SW:
1944 w = MAX (x2 - x, 0);
1945 h = MAX (y - y1, 0);
1948 case GL_LABEL_OBJECT_HANDLE_W:
1949 w = MAX (x2 - x, 0);
1952 case GL_LABEL_OBJECT_HANDLE_P1:
1961 case GL_LABEL_OBJECT_HANDLE_P2:
1969 g_print ("Invalid handle.\n"); /* Should not happen! */
1973 if ( (view->resize_handle != GL_LABEL_OBJECT_HANDLE_P1) &&
1974 (view->resize_handle != GL_LABEL_OBJECT_HANDLE_P2) )
1976 if ( view->resize_honor_aspect )
1978 gl_label_object_set_size_honor_aspect (view->resize_object, w, h, TRUE);
1982 gl_label_object_set_size (view->resize_object, w, h, TRUE);
1986 * Query the new size in case it was constrained.
1988 gl_label_object_get_size (view->resize_object, &w, &h);
1993 switch (view->resize_handle)
1996 case GL_LABEL_OBJECT_HANDLE_NW:
2001 case GL_LABEL_OBJECT_HANDLE_N:
2002 case GL_LABEL_OBJECT_HANDLE_NE:
2007 case GL_LABEL_OBJECT_HANDLE_E:
2008 case GL_LABEL_OBJECT_HANDLE_SE:
2009 case GL_LABEL_OBJECT_HANDLE_S:
2013 case GL_LABEL_OBJECT_HANDLE_SW:
2014 case GL_LABEL_OBJECT_HANDLE_W:
2020 g_print ("Invalid handle.\n"); /* Should not happen! */
2025 gl_label_object_set_size (view->resize_object, dx, dy, TRUE);
2029 * Put new origin back into world coordinates and set.
2031 cairo_user_to_device (cr, &x0, &y0);
2033 cairo_device_to_user (cr, &x0, &y0);
2034 gl_label_object_set_position (view->resize_object, x0, y0, FALSE);
2041 * Local Variables: -- emacs
2043 * c-basic-offset: 8 -- emacs
2044 * tab-width: 8 -- emacs
2045 * indent-tabs-mode: nil -- emacs