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"
48 /*==========================================================================*/
49 /* Private macros and constants. */
50 /*==========================================================================*/
52 #define BG_COLOR GL_COLOR (192, 192, 192)
54 #define PAPER_RGB_ARGS 1.0, 1.0, 1.0
55 #define GRID_RGB_ARGS 0.753, 0.753, 0.753
56 #define MARKUP_RGB_ARGS 0.94, 0.39, 0.39
57 #define OUTLINE_RGB_ARGS 0.68, 0.85, 0.90
58 #define SELECT_LINE_RGBA_ARGS 0.0, 0.0, 1.0, 0.5
59 #define SELECT_FILL_RGBA_ARGS 0.75, 0.75, 1.0, 0.5
61 #define GRID_LINE_WIDTH_PIXELS 1.0
62 #define MARKUP_LINE_WIDTH_PIXELS 1.0
63 #define OUTLINE_WIDTH_PIXELS 3.0
64 #define SELECT_LINE_WIDTH_PIXELS 3.0
66 #define ZOOMTOFIT_PAD 16
68 #define POINTS_PER_MM 2.83464566929
71 /*==========================================================================*/
73 /*==========================================================================*/
76 CONTEXT_MENU_ACTIVATE,
85 /*==========================================================================*/
87 /*==========================================================================*/
89 static guint signals[LAST_SIGNAL] = {0};
91 static gdouble zooms[] = {
108 #define N_ZOOMS G_N_ELEMENTS(zooms)
111 /*==========================================================================*/
112 /* Local function prototypes */
113 /*==========================================================================*/
115 static void gl_view_finalize (GObject *object);
117 static void gl_view_construct (glView *view,
120 static gdouble get_home_scale (glView *view);
122 static gboolean expose_cb (glView *view,
123 GdkEventExpose *event);
125 static void realize_cb (glView *view);
127 static void size_allocate_cb (glView *view,
128 GtkAllocation *allocation);
130 static void screen_changed_cb (glView *view);
132 static void label_changed_cb (glView *view);
134 static void label_resized_cb (glView *view);
136 static void draw_layers (glView *view,
139 static void draw_bg_layer (glView *view,
141 static void draw_grid_layer (glView *view,
143 static void draw_markup_layer (glView *view,
145 static void draw_objects_layer (glView *view,
147 static void draw_fg_layer (glView *view,
149 static void draw_highlight_layer (glView *view,
151 static void draw_select_region_layer (glView *view,
154 static void set_zoom_real (glView *view,
156 gboolean scale_to_fit_flag);
158 static gboolean focus_in_event_cb (glView *view,
159 GdkEventFocus *event);
161 static gboolean focus_out_event_cb (glView *view,
162 GdkEventFocus *event);
164 static gboolean enter_notify_event_cb (glView *view,
165 GdkEventCrossing *event);
167 static gboolean leave_notify_event_cb (glView *view,
168 GdkEventCrossing *event);
170 static gboolean motion_notify_event_cb (glView *view,
171 GdkEventMotion *event);
173 static gboolean button_press_event_cb (glView *view,
174 GdkEventButton *event);
176 static gboolean button_release_event_cb (glView *view,
177 GdkEventButton *event);
179 static gboolean key_press_event_cb (glView *view,
182 static void resize_event (glView *view,
187 /****************************************************************************/
188 /* Boilerplate Object stuff. */
189 /****************************************************************************/
190 G_DEFINE_TYPE (glView, gl_view, GTK_TYPE_VBOX);
194 gl_view_class_init (glViewClass *class)
196 GObjectClass *object_class = G_OBJECT_CLASS (class);
198 gl_debug (DEBUG_VIEW, "START");
200 gl_view_parent_class = g_type_class_peek_parent (class);
202 object_class->finalize = gl_view_finalize;
204 signals[CONTEXT_MENU_ACTIVATE] =
205 g_signal_new ("context_menu_activate",
206 G_OBJECT_CLASS_TYPE (object_class),
208 G_STRUCT_OFFSET (glViewClass, context_menu_activate),
210 gl_marshal_VOID__INT_UINT,
212 2, G_TYPE_INT, G_TYPE_UINT);
214 signals[ZOOM_CHANGED] =
215 g_signal_new ("zoom_changed",
216 G_OBJECT_CLASS_TYPE (object_class),
218 G_STRUCT_OFFSET (glViewClass, zoom_changed),
220 gl_marshal_VOID__DOUBLE,
224 signals[POINTER_MOVED] =
225 g_signal_new ("pointer_moved",
226 G_OBJECT_CLASS_TYPE (object_class),
228 G_STRUCT_OFFSET (glViewClass, pointer_moved),
230 gl_marshal_VOID__DOUBLE_DOUBLE,
232 2, G_TYPE_DOUBLE, G_TYPE_DOUBLE);
234 signals[POINTER_EXIT] =
235 g_signal_new ("pointer_exit",
236 G_OBJECT_CLASS_TYPE (object_class),
238 G_STRUCT_OFFSET (glViewClass, pointer_exit),
240 gl_marshal_VOID__VOID,
244 signals[MODE_CHANGED] =
245 g_signal_new ("mode_changed",
246 G_OBJECT_CLASS_TYPE (object_class),
248 G_STRUCT_OFFSET (glViewClass, mode_changed),
250 gl_marshal_VOID__VOID,
254 gl_debug (DEBUG_VIEW, "END");
259 gl_view_init (glView *view)
264 gl_debug (DEBUG_VIEW, "START");
267 view->grid_visible = TRUE;
268 view->grid_spacing = 9;
269 view->markup_visible = TRUE;
270 view->mode = GL_VIEW_MODE_ARROW;
272 view->home_scale = get_home_scale (view);
277 view->canvas = gtk_layout_new (NULL, NULL);
278 wscroll = gtk_scrolled_window_new (NULL, NULL);
279 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (wscroll),
280 GTK_POLICY_AUTOMATIC,
281 GTK_POLICY_AUTOMATIC);
282 gtk_box_pack_start (GTK_BOX (view), wscroll, TRUE, TRUE, 0);
283 gtk_container_add (GTK_CONTAINER (wscroll), view->canvas);
285 bg_color = gl_color_to_gdk_color (BG_COLOR);
286 gtk_widget_modify_bg (GTK_WIDGET (view->canvas), GTK_STATE_NORMAL, bg_color);
289 gtk_widget_set_can_focus (GTK_WIDGET (view->canvas), TRUE);
291 gtk_widget_add_events (GTK_WIDGET (view->canvas),
292 (GDK_FOCUS_CHANGE_MASK |
293 GDK_ENTER_NOTIFY_MASK |
294 GDK_LEAVE_NOTIFY_MASK |
295 GDK_POINTER_MOTION_MASK |
296 GDK_BUTTON_PRESS_MASK |
297 GDK_BUTTON_RELEASE_MASK |
298 GDK_KEY_PRESS_MASK));
300 g_signal_connect_swapped (G_OBJECT (view->canvas), "expose-event",
301 G_CALLBACK (expose_cb), view);
302 g_signal_connect_swapped (G_OBJECT (view->canvas), "realize",
303 G_CALLBACK (realize_cb), view);
304 g_signal_connect_swapped (G_OBJECT (view->canvas), "size-allocate",
305 G_CALLBACK (size_allocate_cb), view);
306 g_signal_connect_swapped (G_OBJECT (view->canvas), "screen-changed",
307 G_CALLBACK (screen_changed_cb), view);
308 g_signal_connect_swapped (G_OBJECT (view->canvas), "focus-in-event",
309 G_CALLBACK (focus_in_event_cb), view);
310 g_signal_connect_swapped (G_OBJECT (view->canvas), "focus-out-event",
311 G_CALLBACK (focus_out_event_cb), view);
312 g_signal_connect_swapped (G_OBJECT (view->canvas), "enter-notify-event",
313 G_CALLBACK (enter_notify_event_cb), view);
314 g_signal_connect_swapped (G_OBJECT (view->canvas), "leave-notify-event",
315 G_CALLBACK (leave_notify_event_cb), view);
316 g_signal_connect_swapped (G_OBJECT (view->canvas), "motion-notify-event",
317 G_CALLBACK (motion_notify_event_cb), view);
318 g_signal_connect_swapped (G_OBJECT (view->canvas), "button-press-event",
319 G_CALLBACK (button_press_event_cb), view);
320 g_signal_connect_swapped (G_OBJECT (view->canvas), "button-release-event",
321 G_CALLBACK (button_release_event_cb), view);
322 g_signal_connect_swapped (G_OBJECT (view->canvas), "key-press-event",
323 G_CALLBACK (key_press_event_cb), view);
325 gl_debug (DEBUG_VIEW, "END");
330 gl_view_finalize (GObject *object)
332 glView *view = GL_VIEW (object);
334 gl_debug (DEBUG_VIEW, "START");
336 g_return_if_fail (object != NULL);
337 g_return_if_fail (GL_IS_VIEW (view));
339 G_OBJECT_CLASS (gl_view_parent_class)->finalize (object);
341 gl_debug (DEBUG_VIEW, "END");
345 /****************************************************************************/
346 /* NEW view object. */
347 /****************************************************************************/
349 gl_view_new (glLabel *label)
353 gl_debug (DEBUG_VIEW, "START");
355 g_return_val_if_fail (label && GL_IS_LABEL (label), NULL);
357 view = g_object_new (GL_TYPE_VIEW, NULL);
359 gl_view_construct (view, label);
361 gl_debug (DEBUG_VIEW, "END");
363 return GTK_WIDGET (view);
367 /*---------------------------------------------------------------------------*/
368 /* PRIVATE. Construct composite widget. */
369 /*---------------------------------------------------------------------------*/
371 gl_view_construct (glView *view,
374 gl_debug (DEBUG_VIEW, "START");
376 g_return_if_fail (GL_IS_VIEW (view));
380 g_signal_connect_swapped (G_OBJECT (view->label), "selection_changed",
381 G_CALLBACK (label_changed_cb), view);
382 g_signal_connect_swapped (G_OBJECT (view->label), "changed",
383 G_CALLBACK (label_changed_cb), view);
384 g_signal_connect_swapped (G_OBJECT (view->label), "size_changed",
385 G_CALLBACK (label_resized_cb), view);
387 gl_debug (DEBUG_VIEW, "END");
391 /*---------------------------------------------------------------------------*/
392 /* PRIAVTE. Calculate 1:1 scale for screen. */
393 /*---------------------------------------------------------------------------*/
395 get_home_scale (glView *view)
398 gdouble screen_width_pixels;
399 gdouble screen_width_mm;
400 gdouble screen_height_pixels;
401 gdouble screen_height_mm;
402 gdouble x_pixels_per_mm;
403 gdouble y_pixels_per_mm;
406 if (view->canvas == NULL) return 1.0;
408 if (!gtk_widget_has_screen (GTK_WIDGET (view->canvas))) return 1.0;
410 screen = gtk_widget_get_screen (GTK_WIDGET (view->canvas));
412 gl_debug (DEBUG_VIEW, "Screen = %p", screen);
414 screen_width_pixels = gdk_screen_get_width (screen);
415 screen_width_mm = gdk_screen_get_width_mm (screen);
416 screen_height_pixels = gdk_screen_get_height (screen);
417 screen_height_mm = gdk_screen_get_height_mm (screen);
419 x_pixels_per_mm = screen_width_pixels / screen_width_mm;
420 y_pixels_per_mm = screen_height_pixels / screen_height_mm;
422 gl_debug (DEBUG_VIEW, "Horizontal dot pitch: %g pixels/mm (%g dpi)",
423 x_pixels_per_mm, x_pixels_per_mm * 25.4);
424 gl_debug (DEBUG_VIEW, "Vertical dot pitch: %g pixels/mm (%g dpi)",
425 y_pixels_per_mm, y_pixels_per_mm * 25.4);
427 scale = (x_pixels_per_mm + y_pixels_per_mm) / 2.0;
429 gl_debug (DEBUG_VIEW, "Average dot pitch: %g pixels/mm (%g dpi)",
430 scale, scale * 25.4);
432 scale /= POINTS_PER_MM;
434 gl_debug (DEBUG_VIEW, "Scale = %g pixels/point", scale);
436 /* Make sure scale is somewhat sane. */
437 if ( (scale < 0.25) || (scale > 4.0) ) return 1.0;
443 /*---------------------------------------------------------------------------*/
444 /* Schedule canvas update. */
445 /*---------------------------------------------------------------------------*/
447 gl_view_update (glView *view)
452 gl_debug (DEBUG_VIEW, "START");
454 window = gtk_widget_get_window (GTK_WIDGET (view->canvas));
458 if ( !view->update_scheduled_flag )
460 view->update_scheduled_flag = TRUE;
462 region = gdk_drawable_get_clip_region (window);
463 /* redraw the cairo canvas completely by exposing it */
464 gdk_window_invalidate_region (window, region, TRUE);
465 gdk_region_destroy (region);
468 gl_debug (DEBUG_VIEW, "END");
472 /*---------------------------------------------------------------------------*/
473 /* Schedule canvas region update. */
474 /*---------------------------------------------------------------------------*/
476 gl_view_update_region (glView *view,
478 glLabelRegion *region)
484 gl_debug (DEBUG_VIEW, "START");
486 window = gtk_widget_get_window (GTK_WIDGET (view->canvas));
490 x = MIN (region->x1, region->x2);
491 y = MIN (region->y1, region->y2);
492 w = fabs (region->x2 - region->x1);
493 h = fabs (region->y2 - region->y1);
495 cairo_user_to_device (cr, &x, &y);
496 cairo_user_to_device_distance (cr, &w, &h);
503 gdk_window_invalidate_rect (window, &rect, TRUE);
505 gl_debug (DEBUG_VIEW, "END");
509 /*---------------------------------------------------------------------------*/
510 /* PRIVATE. Expose handler. */
511 /*---------------------------------------------------------------------------*/
513 expose_cb (glView *view,
514 GdkEventExpose *event)
516 GdkWindow *bin_window;
519 gl_debug (DEBUG_VIEW, "START");
521 view->update_scheduled_flag = FALSE;
523 bin_window = gtk_layout_get_bin_window (GTK_LAYOUT (view->canvas));
524 cr = gdk_cairo_create (bin_window);
527 event->area.x, event->area.y,
528 event->area.width, event->area.height);
531 draw_layers (view, cr);
535 gl_debug (DEBUG_VIEW, "END");
541 /*---------------------------------------------------------------------------*/
542 /* PRIVATE. Realize handler. */
543 /*---------------------------------------------------------------------------*/
545 realize_cb (glView *view)
547 g_return_if_fail (view && GL_IS_VIEW (view));
549 gl_debug (DEBUG_VIEW, "START");
551 gl_debug (DEBUG_VIEW, "END");
555 /*---------------------------------------------------------------------------*/
556 /* PRIVATE. Size allocation changed callback. */
557 /*---------------------------------------------------------------------------*/
559 size_allocate_cb (glView *view,
560 GtkAllocation *allocation)
562 GtkAdjustment *hadjustment;
563 GtkAdjustment *vadjustment;
565 gl_debug (DEBUG_VIEW, "START");
567 hadjustment = gtk_layout_get_hadjustment(GTK_LAYOUT (view->canvas));
568 vadjustment = gtk_layout_get_vadjustment(GTK_LAYOUT (view->canvas));
570 gtk_adjustment_set_page_size( hadjustment, allocation->width);
571 gtk_adjustment_set_page_increment( hadjustment, allocation->width / 2);
573 gtk_adjustment_set_page_size( vadjustment, allocation->height);
574 gtk_adjustment_set_page_increment( vadjustment, allocation->height / 2);
576 g_signal_emit_by_name (hadjustment, "changed");
577 g_signal_emit_by_name (vadjustment, "changed");
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. Screen changed callback. */
590 /*---------------------------------------------------------------------------*/
592 screen_changed_cb (glView *view)
594 gl_debug (DEBUG_VIEW, "START");
596 if (gtk_widget_has_screen (GTK_WIDGET (view->canvas))) {
598 view->home_scale = get_home_scale (view);
600 if (view->zoom_to_fit_flag) {
601 /* Maintain best fit zoom */
602 gl_view_zoom_to_fit (view);
606 gl_debug (DEBUG_VIEW, "END");
610 /*---------------------------------------------------------------------------*/
611 /* PRIVATE. Handle label changed event. */
612 /*---------------------------------------------------------------------------*/
614 label_changed_cb (glView *view)
616 g_return_if_fail (view && GL_IS_VIEW (view));
618 gl_debug (DEBUG_VIEW, "START");
620 gl_view_update (view);
622 gl_debug (DEBUG_VIEW, "END");
626 /*---------------------------------------------------------------------------*/
627 /* PRIVATE. Handle label resize event. */
628 /*---------------------------------------------------------------------------*/
630 label_resized_cb (glView *view)
632 GtkAdjustment *hadjustment;
633 GtkAdjustment *vadjustment;
635 g_return_if_fail (view && GL_IS_VIEW (view));
637 gl_debug (DEBUG_VIEW, "START");
639 hadjustment = gtk_layout_get_hadjustment(GTK_LAYOUT (view->canvas));
640 vadjustment = gtk_layout_get_vadjustment(GTK_LAYOUT (view->canvas));
642 g_signal_emit_by_name (hadjustment, "changed");
643 g_signal_emit_by_name (vadjustment, "changed");
645 gl_view_update (view);
647 gl_debug (DEBUG_VIEW, "END");
651 /*---------------------------------------------------------------------------*/
652 /* PRIVATE. Create, draw and order layers. */
653 /*---------------------------------------------------------------------------*/
655 draw_layers (glView *view,
658 GdkWindow *bin_window;
661 gint canvas_w, canvas_h;
663 g_return_if_fail (view && GL_IS_VIEW (view));
664 g_return_if_fail (view->label && GL_IS_LABEL (view->label));
666 gl_debug (DEBUG_VIEW, "START");
668 bin_window = gtk_layout_get_bin_window (GTK_LAYOUT (view->canvas));
670 scale = view->zoom * view->home_scale;
672 gl_label_get_size (view->label, &w, &h);
674 scale = view->home_scale * view->zoom;
675 gtk_layout_set_size (GTK_LAYOUT (view->canvas), w*scale+8, h*scale+8);
677 gdk_drawable_get_size (bin_window, &canvas_w, &canvas_h);
679 view->x0 = (canvas_w/scale - w) / 2.0;
680 view->y0 = (canvas_h/scale - h) / 2.0;
686 cairo_scale (cr, scale, scale);
687 cairo_translate (cr, view->x0, view->y0);
689 draw_bg_layer (view, cr);
690 draw_grid_layer (view, cr);
691 draw_markup_layer (view, cr);
692 draw_objects_layer (view, cr);
693 draw_fg_layer (view, cr);
694 draw_highlight_layer (view, cr);
695 draw_select_region_layer (view, cr);
699 gl_debug (DEBUG_VIEW, "END");
704 /*---------------------------------------------------------------------------*/
705 /* PRIVATE. Draw background */
706 /*---------------------------------------------------------------------------*/
708 draw_bg_layer (glView *view,
711 const lglTemplate *template;
712 gboolean rotate_flag;
714 g_return_if_fail (view && GL_IS_VIEW (view));
715 g_return_if_fail (view->label && GL_IS_LABEL (view->label));
717 template = gl_label_get_template (view->label);
718 rotate_flag = gl_label_get_rotate_flag (view->label);
719 gl_cairo_label_path (cr, template, rotate_flag, FALSE);
721 cairo_set_source_rgb (cr, PAPER_RGB_ARGS);
722 cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
727 /*---------------------------------------------------------------------------*/
728 /* PRIVATE. Draw grid lines. */
729 /*---------------------------------------------------------------------------*/
731 draw_grid_layer (glView *view,
734 const lglTemplate *template;
735 const lglTemplateFrame *frame;
740 gl_debug (DEBUG_VIEW, "START");
742 g_return_if_fail (view && GL_IS_VIEW (view));
743 g_return_if_fail (view->label && GL_IS_LABEL(view->label));
745 if (view->grid_visible)
748 template = gl_label_get_template (view->label);
749 frame = (lglTemplateFrame *)template->frames->data;
751 gl_label_get_size (view->label, &w, &h);
753 if (frame->shape == LGL_TEMPLATE_FRAME_SHAPE_RECT) {
757 /* round labels, adjust grid to line up with center of label. */
758 x0 = fmod (w/2.0, view->grid_spacing);
759 y0 = fmod (h/2.0, view->grid_spacing);
765 cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
766 cairo_set_line_width (cr, GRID_LINE_WIDTH_PIXELS/(view->home_scale * view->zoom));
767 cairo_set_source_rgb (cr, GRID_RGB_ARGS);
769 for ( x=x0+view->grid_spacing; x < w; x += view->grid_spacing )
771 cairo_move_to (cr, x, 0);
772 cairo_line_to (cr, x, h);
776 for ( y=y0+view->grid_spacing; y < h; y += view->grid_spacing )
778 cairo_move_to (cr, 0, y);
779 cairo_line_to (cr, w, y);
787 gl_debug (DEBUG_VIEW, "END");
791 /*---------------------------------------------------------------------------*/
792 /* PRIVATE. Draw markup layer. */
793 /*---------------------------------------------------------------------------*/
795 draw_markup_layer (glView *view,
798 const lglTemplate *template;
799 const lglTemplateFrame *frame;
800 gboolean rotate_flag;
802 lglTemplateMarkup *markup;
803 gdouble width, height;
805 g_return_if_fail (view && GL_IS_VIEW (view));
806 g_return_if_fail (view->label && GL_IS_LABEL (view->label));
808 if (view->markup_visible)
811 template = gl_label_get_template (view->label);
812 frame = (lglTemplateFrame *)template->frames->data;
813 rotate_flag = gl_label_get_rotate_flag (view->label);
819 lgl_template_frame_get_size (frame, &width, &height);
820 cairo_rotate (cr, -M_PI/2.0);
821 cairo_translate (cr, -width, 0.0);
824 cairo_set_line_width (cr, MARKUP_LINE_WIDTH_PIXELS/(view->home_scale * view->zoom));
825 cairo_set_source_rgb (cr, MARKUP_RGB_ARGS);
827 for ( p=frame->all.markups; p != NULL; p=p->next )
829 markup = (lglTemplateMarkup *)p->data;
831 gl_cairo_markup_path (cr, markup, view->label);
842 /*---------------------------------------------------------------------------*/
843 /* PRIVATE. Draw objects layer. */
844 /*---------------------------------------------------------------------------*/
846 draw_objects_layer (glView *view,
849 gl_label_draw (view->label, cr, TRUE, NULL);
853 /*---------------------------------------------------------------------------*/
854 /* PRIVATE. Draw foreground */
855 /*---------------------------------------------------------------------------*/
857 draw_fg_layer (glView *view,
860 const lglTemplate *template;
861 gboolean rotate_flag;
863 g_return_if_fail (view && GL_IS_VIEW (view));
864 g_return_if_fail (view->label && GL_IS_LABEL (view->label));
866 template = gl_label_get_template (view->label);
867 rotate_flag = gl_label_get_rotate_flag (view->label);
869 gl_cairo_label_path (cr, template, rotate_flag, FALSE);
871 cairo_set_line_width (cr, OUTLINE_WIDTH_PIXELS/(view->home_scale * view->zoom));
872 cairo_set_source_rgb (cr, OUTLINE_RGB_ARGS);
877 /*---------------------------------------------------------------------------*/
878 /* PRIVATE. Create highlight layer. */
879 /*---------------------------------------------------------------------------*/
881 draw_highlight_layer (glView *view,
884 GList *selection_list;
886 glLabelObject *object;
888 g_return_if_fail (view && GL_IS_VIEW (view));
892 cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
894 selection_list = gl_label_get_selection_list (view->label);
896 for (p_obj = selection_list; p_obj != NULL; p_obj = p_obj->next)
898 object = GL_LABEL_OBJECT (p_obj->data);
900 gl_label_object_draw_handles (object, cr);
903 g_list_free (selection_list);
909 /*---------------------------------------------------------------------------*/
910 /* PRIVATE. Draw select region layer. */
911 /*---------------------------------------------------------------------------*/
913 draw_select_region_layer (glView *view,
919 g_return_if_fail (view && GL_IS_VIEW (view));
921 if (view->select_region_visible)
923 x1 = MIN (view->select_region.x1, view->select_region.x2);
924 y1 = MIN (view->select_region.y1, view->select_region.y2);
925 w = fabs (view->select_region.x2 - view->select_region.x1);
926 h = fabs (view->select_region.y2 - view->select_region.y1);
930 cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
932 cairo_rectangle (cr, x1, y1, w, h);
934 cairo_set_source_rgba (cr, SELECT_FILL_RGBA_ARGS);
935 cairo_fill_preserve (cr);
937 cairo_set_line_width (cr, SELECT_LINE_WIDTH_PIXELS/(view->home_scale * view->zoom));
938 cairo_set_source_rgba (cr, SELECT_LINE_RGBA_ARGS);
946 /*****************************************************************************/
948 /*****************************************************************************/
950 gl_view_show_grid (glView *view)
952 g_return_if_fail (view && GL_IS_VIEW (view));
954 view->grid_visible = TRUE;
955 gl_view_update (view);
959 /*****************************************************************************/
961 /*****************************************************************************/
963 gl_view_hide_grid (glView *view)
965 g_return_if_fail (view && GL_IS_VIEW (view));
967 view->grid_visible = FALSE;
968 gl_view_update (view);
972 /*****************************************************************************/
973 /* Set grid spacing. */
974 /*****************************************************************************/
976 gl_view_set_grid_spacing (glView *view,
979 g_return_if_fail (view && GL_IS_VIEW (view));
981 view->grid_spacing = spacing;
982 gl_view_update (view);
986 /*****************************************************************************/
988 /*****************************************************************************/
990 gl_view_show_markup (glView *view)
992 g_return_if_fail (view && GL_IS_VIEW (view));
994 view->markup_visible = TRUE;
995 gl_view_update (view);
999 /*****************************************************************************/
1001 /*****************************************************************************/
1003 gl_view_hide_markup (glView *view)
1005 g_return_if_fail (view && GL_IS_VIEW (view));
1007 view->markup_visible = FALSE;
1008 gl_view_update (view);
1012 /*****************************************************************************/
1013 /* Set arrow mode. */
1014 /*****************************************************************************/
1016 gl_view_arrow_mode (glView *view)
1021 gl_debug (DEBUG_VIEW, "START");
1023 g_return_if_fail (view && GL_IS_VIEW (view));
1025 window = gtk_widget_get_window (view->canvas);
1027 cursor = gdk_cursor_new (GDK_LEFT_PTR);
1028 gdk_window_set_cursor (window, cursor);
1029 gdk_cursor_unref (cursor);
1031 view->mode = GL_VIEW_MODE_ARROW;
1032 view->state = GL_VIEW_IDLE;
1034 gl_debug (DEBUG_VIEW, "END");
1038 /*****************************************************************************/
1039 /* Set create text object mode. */
1040 /*****************************************************************************/
1042 gl_view_object_create_mode (glView *view,
1043 glLabelObjectType type)
1046 GdkCursor *cursor = NULL;
1048 gl_debug (DEBUG_VIEW, "START");
1050 g_return_if_fail (view && GL_IS_VIEW (view));
1052 window = gtk_widget_get_window (view->canvas);
1056 case GL_LABEL_OBJECT_BOX:
1057 cursor = gl_view_box_get_create_cursor ();
1059 case GL_LABEL_OBJECT_ELLIPSE:
1060 cursor = gl_view_ellipse_get_create_cursor ();
1062 case GL_LABEL_OBJECT_LINE:
1063 cursor = gl_view_line_get_create_cursor ();
1065 case GL_LABEL_OBJECT_IMAGE:
1066 cursor = gl_view_image_get_create_cursor ();
1068 case GL_LABEL_OBJECT_TEXT:
1069 cursor = gl_view_text_get_create_cursor ();
1071 case GL_LABEL_OBJECT_BARCODE:
1072 cursor = gl_view_barcode_get_create_cursor ();
1075 g_message ("Invalid label object type.");/*Should not happen!*/
1079 gdk_window_set_cursor (window, cursor);
1080 gdk_cursor_unref (cursor);
1082 view->mode = GL_VIEW_MODE_OBJECT_CREATE;
1083 view->state = GL_VIEW_IDLE;
1084 view->create_type = type;
1086 gl_debug (DEBUG_VIEW, "END");
1090 /*****************************************************************************/
1091 /* Zoom in one "notch" */
1092 /*****************************************************************************/
1094 gl_view_zoom_in (glView *view)
1097 gdouble dist, dist_min;
1099 gl_debug (DEBUG_VIEW, "START");
1101 g_return_if_fail (view && GL_IS_VIEW (view));
1103 /* Find index of current scale (or best match) */
1104 i_min = 1; /* start with 2nd largest scale */
1105 dist_min = fabs (zooms[1] - view->zoom);
1106 for (i = 2; i < N_ZOOMS; i++) {
1107 dist = fabs (zooms[i] - view->zoom);
1108 if (dist < dist_min) {
1114 /* zoom in one "notch" */
1115 i = MAX (0, i_min - 1);
1116 gl_debug (DEBUG_VIEW, "zoom[%d] = %g", i, zooms[i]);
1117 set_zoom_real (view, zooms[i], FALSE);
1119 gl_debug (DEBUG_VIEW, "END");
1123 /*****************************************************************************/
1124 /* Zoom out one "notch" */
1125 /*****************************************************************************/
1127 gl_view_zoom_out (glView *view)
1130 gdouble dist, dist_min;
1132 gl_debug (DEBUG_VIEW, "START");
1134 g_return_if_fail (view && GL_IS_VIEW (view));
1136 /* Find index of current scale (or best match) */
1137 i_min = 0; /* start with largest scale */
1138 dist_min = fabs (zooms[0] - view->zoom);
1139 for (i = 1; i < N_ZOOMS; i++) {
1140 dist = fabs (zooms[i] - view->zoom);
1141 if (dist < dist_min) {
1147 /* zoom out one "notch" */
1148 if (i_min >= N_ZOOMS)
1153 set_zoom_real (view, zooms[i], FALSE);
1155 gl_debug (DEBUG_VIEW, "END");
1159 /*****************************************************************************/
1160 /* Set zoom to best fit. */
1161 /*****************************************************************************/
1163 gl_view_zoom_to_fit (glView *view)
1165 GtkAllocation allocation;
1166 gint w_view, h_view;
1167 gdouble w_label, h_label;
1168 gdouble x_scale, y_scale, scale;
1170 gl_debug (DEBUG_VIEW, "");
1172 if ( ! gtk_widget_get_window (GTK_WIDGET (view)) ) {
1173 set_zoom_real (view, 1.0, TRUE);
1177 gtk_widget_get_allocation (GTK_WIDGET (view), &allocation);
1178 w_view = allocation.width;
1179 h_view = allocation.height;
1181 gl_label_get_size (GL_LABEL(view->label), &w_label, &h_label);
1183 gl_debug (DEBUG_VIEW, "View size: %d, %d", w_view, h_view);
1184 gl_debug (DEBUG_VIEW, "Label size: %g, %g", w_label, h_label);
1186 /* Calculate best scale */
1187 x_scale = (double)(w_view - ZOOMTOFIT_PAD) / w_label;
1188 y_scale = (double)(h_view - ZOOMTOFIT_PAD) / h_label;
1189 scale = MIN (x_scale, y_scale);
1190 gl_debug (DEBUG_VIEW, "Candidate zooms: %g, %g => %g", x_scale, y_scale, scale);
1193 gl_debug (DEBUG_VIEW, "Scale: %g", scale);
1194 scale = MIN (scale, zooms[0]*view->home_scale);
1195 scale = MAX (scale, zooms[N_ZOOMS-1]*view->home_scale);
1196 gl_debug (DEBUG_VIEW, "Limitted scale: %g", scale);
1198 set_zoom_real (view, scale/view->home_scale, TRUE);
1202 /*****************************************************************************/
1203 /* Set current zoom factor to explicit value. */
1204 /*****************************************************************************/
1206 gl_view_set_zoom (glView *view,
1209 gl_debug (DEBUG_VIEW, "START");
1211 set_zoom_real (view, zoom, FALSE);
1213 gl_debug (DEBUG_VIEW, "END");
1217 /*---------------------------------------------------------------------------*/
1218 /* PRIVATE. Set canvas scale. */
1219 /*---------------------------------------------------------------------------*/
1221 set_zoom_real (glView *view,
1223 gboolean zoom_to_fit_flag)
1225 gl_debug (DEBUG_VIEW, "START");
1227 g_return_if_fail (view && GL_IS_VIEW (view));
1228 g_return_if_fail (zoom > 0.0);
1230 /* Limit, if needed */
1231 gl_debug (DEBUG_VIEW, "Zoom requested: %g", zoom);
1232 zoom = MIN (zoom, zooms[0]);
1233 zoom = MAX (zoom, zooms[N_ZOOMS-1]);
1234 gl_debug (DEBUG_VIEW, "Limitted zoom: %g", zoom);
1236 if ( zoom != view->zoom ) {
1239 view->zoom_to_fit_flag = zoom_to_fit_flag;
1241 gl_view_update (view);
1243 g_signal_emit (G_OBJECT(view), signals[ZOOM_CHANGED], 0, zoom);
1247 gl_debug (DEBUG_VIEW, "END");
1252 /*****************************************************************************/
1253 /* Get current zoom factor. */
1254 /*****************************************************************************/
1256 gl_view_get_zoom (glView *view)
1258 gl_debug (DEBUG_VIEW, "");
1260 g_return_val_if_fail (view && GL_IS_VIEW (view), 1.0);
1266 /*****************************************************************************/
1267 /* Is this the maximum zoom level. */
1268 /*****************************************************************************/
1270 gl_view_is_zoom_max (glView *view)
1272 gl_debug (DEBUG_VIEW, "");
1274 g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
1276 return view->zoom >= zooms[0];
1280 /*****************************************************************************/
1281 /* Is this the minimum zoom level. */
1282 /*****************************************************************************/
1284 gl_view_is_zoom_min (glView *view)
1286 gl_debug (DEBUG_VIEW, "");
1288 g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
1290 return view->zoom <= zooms[N_ZOOMS-1];
1294 /*---------------------------------------------------------------------------*/
1295 /* PRIVATE. Focus in event handler. */
1296 /*---------------------------------------------------------------------------*/
1298 focus_in_event_cb (glView *view,
1299 GdkEventFocus *event)
1305 /*---------------------------------------------------------------------------*/
1306 /* PRIVATE. Focus out event handler. */
1307 /*---------------------------------------------------------------------------*/
1309 focus_out_event_cb (glView *view,
1310 GdkEventFocus *event)
1316 /*---------------------------------------------------------------------------*/
1317 /* PRIVATE. Enter notify event handler. */
1318 /*---------------------------------------------------------------------------*/
1320 enter_notify_event_cb (glView *view,
1321 GdkEventCrossing *event)
1327 /*---------------------------------------------------------------------------*/
1328 /* PRIVATE. Leave notify event handler. */
1329 /*---------------------------------------------------------------------------*/
1331 leave_notify_event_cb (glView *view,
1332 GdkEventCrossing *event)
1335 g_signal_emit (G_OBJECT(view), signals[POINTER_EXIT], 0);
1341 /*---------------------------------------------------------------------------*/
1342 /* PRIVATE. Motion notify event handler. */
1343 /*---------------------------------------------------------------------------*/
1345 motion_notify_event_cb (glView *view,
1346 GdkEventMotion *event)
1348 gboolean return_value = FALSE;
1349 GdkWindow *bin_window;
1355 glLabelObjectHandle handle;
1357 bin_window = gtk_layout_get_bin_window (GTK_LAYOUT (view->canvas));
1358 window = gtk_widget_get_window (view->canvas);
1360 cr = gdk_cairo_create (bin_window);
1363 * Translate to label coordinates
1365 scale = view->zoom * view->home_scale;
1366 cairo_scale (cr, scale, scale);
1367 cairo_translate (cr, view->x0, view->y0);
1371 cairo_device_to_user (cr, &x, &y);
1374 * Emit signal regardless of mode
1376 g_signal_emit (G_OBJECT(view), signals[POINTER_MOVED], 0, x, y);
1379 * Handle event as appropriate for mode
1384 case GL_VIEW_MODE_ARROW:
1385 switch (view->state)
1389 if ( gl_label_is_selection_atomic (view->label) &&
1390 gl_label_get_handle_at (view->label, cr, event->x, event->y, &handle) )
1392 cursor = gdk_cursor_new (GDK_CROSSHAIR);
1394 else if (gl_label_object_at (view->label, cr, event->x, event->y))
1396 cursor = gdk_cursor_new (GDK_FLEUR);
1400 cursor = gdk_cursor_new (GDK_LEFT_PTR);
1402 gdk_window_set_cursor (window, cursor);
1403 gdk_cursor_unref (cursor);
1406 case GL_VIEW_ARROW_SELECT_REGION:
1408 gl_view_update_region (view, cr, &view->select_region);
1410 view->select_region.x2 = x;
1411 view->select_region.y2 = y;
1413 gl_view_update_region (view, cr, &view->select_region);
1415 gl_view_update (view);
1419 case GL_VIEW_ARROW_MOVE:
1420 gl_label_move_selection (view->label,
1421 (x - view->move_last_x),
1422 (y - view->move_last_y));
1423 view->move_last_x = x;
1424 view->move_last_y = y;
1427 case GL_VIEW_ARROW_RESIZE:
1428 resize_event (view, cr, event->x, event->y);
1432 g_message ("Invalid arrow state."); /*Should not happen!*/
1434 return_value = TRUE;
1438 case GL_VIEW_MODE_OBJECT_CREATE:
1439 if (view->state != GL_VIEW_IDLE)
1441 switch (view->create_type)
1443 case GL_LABEL_OBJECT_BOX:
1444 gl_view_box_create_motion_event (view, x, y);
1446 case GL_LABEL_OBJECT_ELLIPSE:
1447 gl_view_ellipse_create_motion_event (view, x, y);
1449 case GL_LABEL_OBJECT_LINE:
1450 gl_view_line_create_motion_event (view, x, y);
1452 case GL_LABEL_OBJECT_IMAGE:
1453 gl_view_image_create_motion_event (view, x, y);
1455 case GL_LABEL_OBJECT_TEXT:
1456 gl_view_text_create_motion_event (view, x, y);
1458 case GL_LABEL_OBJECT_BARCODE:
1459 gl_view_barcode_create_motion_event (view, x, y);
1462 g_message ("Invalid create type."); /*Should not happen!*/
1469 g_message ("Invalid view mode."); /*Should not happen!*/
1476 * FIXME: we re-establish grabs here if the grab has been lost. We seem to be
1477 * losing grabs when we emit signals that lead to the manipulation of
1478 * the GtkUIManager. Needs more investigation
1480 if (view->grabbed_flag && !gdk_pointer_is_grabbed ())
1482 gdk_pointer_grab (bin_window,
1484 (GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK),
1490 return return_value;
1494 /*---------------------------------------------------------------------------*/
1495 /* PRIVATE. Button press event handler. */
1496 /*---------------------------------------------------------------------------*/
1498 button_press_event_cb (glView *view,
1499 GdkEventButton *event)
1501 gboolean return_value = FALSE;
1502 GdkWindow *bin_window;
1506 glLabelObject *object;
1507 glLabelObjectHandle handle;
1509 gtk_widget_grab_focus(GTK_WIDGET (view->canvas));
1511 bin_window = gtk_layout_get_bin_window (GTK_LAYOUT (view->canvas));
1513 cr = gdk_cairo_create (bin_window);
1516 * Translate to label coordinates
1518 scale = view->zoom * view->home_scale;
1519 cairo_scale (cr, scale, scale);
1520 cairo_translate (cr, view->x0, view->y0);
1524 cairo_device_to_user (cr, &x, &y);
1526 switch (event->button)
1531 * Handle event as appropriate for mode
1535 case GL_VIEW_MODE_ARROW:
1536 if ( gl_label_is_selection_atomic (view->label) &&
1537 (object = gl_label_get_handle_at (view->label, cr, event->x, event->y, &handle)) )
1539 view->resize_object = object;
1540 view->resize_handle = handle;
1541 view->resize_honor_aspect = event->state & GDK_CONTROL_MASK;
1543 view->state = GL_VIEW_ARROW_RESIZE;
1545 else if ((object = gl_label_object_at (view->label, cr, event->x, event->y)))
1547 if (event->state & GDK_CONTROL_MASK)
1549 if (gl_label_object_is_selected (object))
1551 /* Un-selecting a selected item */
1552 gl_label_unselect_object (view->label, object);
1554 /* Add to current selection */
1555 gl_label_select_object (view->label, object);
1560 if (!gl_label_object_is_selected (object))
1562 /* remove any selections before adding */
1563 gl_label_unselect_all (view->label);
1564 /* Add to current selection */
1565 gl_label_select_object (view->label, object);
1568 view->move_last_x = x;
1569 view->move_last_y = y;
1571 view->state = GL_VIEW_ARROW_MOVE;
1575 if (!(event->state & GDK_CONTROL_MASK))
1577 gl_label_unselect_all (view->label);
1580 view->select_region_visible = TRUE;
1581 view->select_region.x1 = x;
1582 view->select_region.y1 = y;
1583 view->select_region.x2 = x;
1584 view->select_region.y2 = y;
1586 view->state = GL_VIEW_ARROW_SELECT_REGION;
1590 return_value = TRUE;
1593 case GL_VIEW_MODE_OBJECT_CREATE:
1594 switch (view->create_type)
1596 case GL_LABEL_OBJECT_BOX:
1597 gl_view_box_create_button_press_event (view, x, y);
1599 case GL_LABEL_OBJECT_ELLIPSE:
1600 gl_view_ellipse_create_button_press_event (view, x, y);
1602 case GL_LABEL_OBJECT_LINE:
1603 gl_view_line_create_button_press_event (view, x, y);
1605 case GL_LABEL_OBJECT_IMAGE:
1606 gl_view_image_create_button_press_event (view, x, y);
1608 case GL_LABEL_OBJECT_TEXT:
1609 gl_view_text_create_button_press_event (view, x, y);
1611 case GL_LABEL_OBJECT_BARCODE:
1612 gl_view_barcode_create_button_press_event (view, x, y);
1615 g_message ("Invalid create type."); /*Should not happen!*/
1617 view->state = GL_VIEW_CREATE_DRAG;
1618 return_value = TRUE;
1622 g_message ("Invalid view mode."); /*Should not happen!*/
1625 view->grabbed_flag = TRUE;
1626 gdk_pointer_grab (bin_window,
1628 (GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK),
1635 g_signal_emit (G_OBJECT (view),
1636 signals[CONTEXT_MENU_ACTIVATE], 0,
1637 event->button, event->time);
1638 return_value = TRUE;
1645 return return_value;
1649 /*---------------------------------------------------------------------------*/
1650 /* PRIVATE. Button release event handler. */
1651 /*---------------------------------------------------------------------------*/
1653 button_release_event_cb (glView *view,
1654 GdkEventButton *event)
1656 gboolean return_value = FALSE;
1657 GdkWindow *bin_window;
1664 bin_window = gtk_layout_get_bin_window (GTK_LAYOUT (view->canvas));
1665 window = gtk_widget_get_window (view->canvas);
1667 cr = gdk_cairo_create (bin_window);
1670 * Translate to label coordinates
1672 scale = view->zoom * view->home_scale;
1673 cairo_scale (cr, scale, scale);
1674 cairo_translate (cr, view->x0, view->y0);
1678 cairo_device_to_user (cr, &x, &y);
1680 switch (event->button)
1684 view->grabbed_flag = FALSE;
1685 gdk_pointer_ungrab (event->time);
1687 * Handle event as appropriate for mode
1691 case GL_VIEW_MODE_ARROW:
1692 switch (view->state)
1694 case GL_VIEW_ARROW_RESIZE:
1695 view->resize_object = NULL;
1697 view->state = GL_VIEW_IDLE;
1700 case GL_VIEW_ARROW_SELECT_REGION:
1702 gl_view_update_region (view, cr, &view->select_region);
1704 gl_view_update (view);
1707 view->select_region_visible = FALSE;
1708 view->select_region.x2 = x;
1709 view->select_region.y2 = y;
1711 gl_label_select_region (view->label, &view->select_region);
1713 view->state = GL_VIEW_IDLE;
1717 view->state = GL_VIEW_IDLE;
1722 return_value = TRUE;
1726 case GL_VIEW_MODE_OBJECT_CREATE:
1727 switch (view->create_type)
1729 case GL_LABEL_OBJECT_BOX:
1730 gl_view_box_create_button_release_event (view, x, y);
1732 case GL_LABEL_OBJECT_ELLIPSE:
1733 gl_view_ellipse_create_button_release_event (view, x, y);
1735 case GL_LABEL_OBJECT_LINE:
1736 gl_view_line_create_button_release_event (view, x, y);
1738 case GL_LABEL_OBJECT_IMAGE:
1739 gl_view_image_create_button_release_event (view, x, y);
1741 case GL_LABEL_OBJECT_TEXT:
1742 gl_view_text_create_button_release_event (view, x, y);
1744 case GL_LABEL_OBJECT_BARCODE:
1745 gl_view_barcode_create_button_release_event (view, x, y);
1748 g_message ("Invalid create type."); /*Should not happen!*/
1750 view->mode = GL_VIEW_MODE_ARROW;
1751 view->state = GL_VIEW_IDLE;
1752 cursor = gdk_cursor_new (GDK_LEFT_PTR);
1753 gdk_window_set_cursor (window, cursor);
1754 gdk_cursor_unref (cursor);
1756 gl_label_select_object (view->label, view->create_object);
1761 g_message ("Invalid view mode."); /*Should not happen!*/
1768 return return_value;
1772 /*---------------------------------------------------------------------------*/
1773 /* PRIVATE. Key press event handler. */
1774 /*---------------------------------------------------------------------------*/
1776 key_press_event_cb (glView *view,
1782 gl_debug (DEBUG_VIEW, "");
1784 window = gtk_widget_get_window (view->canvas);
1786 if ( (view->mode == GL_VIEW_MODE_ARROW) &&
1787 (view->state == GL_VIEW_IDLE) )
1789 switch (event->keyval) {
1793 gl_label_move_selection (view->label, -1.0 / (view->zoom), 0.0);
1797 gl_label_move_selection (view->label, 0.0, -1.0 / (view->zoom));
1801 gl_label_move_selection (view->label, 1.0 / (view->zoom), 0.0);
1805 gl_label_move_selection (view->label, 0.0, 1.0 / (view->zoom));
1809 gl_label_delete_selection (view->label);
1810 cursor = gdk_cursor_new (GDK_LEFT_PTR);
1811 gdk_window_set_cursor (window, cursor);
1812 gdk_cursor_unref (cursor);
1819 return TRUE; /* We handled this or we were dragging. */
1823 /*---------------------------------------------------------------------------*/
1824 /* PRIVATE. Resize object. */
1825 /*---------------------------------------------------------------------------*/
1827 resize_event (glView *view,
1832 cairo_matrix_t matrix;
1833 gdouble x0, y0, x1, y1, x2, y2;
1837 gl_debug (DEBUG_VIEW, "x,y world = %g, %g", x, y);
1840 * Change to item relative coordinates
1843 gl_label_object_get_position (view->resize_object, &x0, &y0);
1844 cairo_translate (cr, x0, y0);
1845 gl_label_object_get_matrix (view->resize_object, &matrix);
1846 cairo_transform (cr, &matrix);
1849 * Initialize origin and 2 corners in object relative coordinates.
1857 gl_label_object_get_size (view->resize_object, &x2, &y2);
1859 gl_debug (DEBUG_VIEW, "x0,y0 object = %g, %g", x0, y0);
1860 gl_debug (DEBUG_VIEW, "x1,y1 object = %g, %g", x1, y1);
1861 gl_debug (DEBUG_VIEW, "x2,y2 object = %g, %g", x2, y2);
1864 * Translate x,y into object relative coordinates.
1866 cairo_device_to_user (cr, &x, &y);
1868 gl_debug (DEBUG_VIEW, "x,y object = %g, %g", x, y);
1873 switch (view->resize_handle)
1876 case GL_LABEL_OBJECT_HANDLE_NW:
1877 w = MAX (x2 - x, 0);
1878 h = MAX (y2 - y, 0);
1881 case GL_LABEL_OBJECT_HANDLE_N:
1883 h = MAX (y2 - y, 0);
1886 case GL_LABEL_OBJECT_HANDLE_NE:
1887 w = MAX (x - x1, 0);
1888 h = MAX (y2 - y, 0);
1891 case GL_LABEL_OBJECT_HANDLE_E:
1892 w = MAX (x - x1, 0);
1896 case GL_LABEL_OBJECT_HANDLE_SE:
1897 w = MAX (x - x1, 0);
1898 h = MAX (y - y1, 0);
1901 case GL_LABEL_OBJECT_HANDLE_S:
1903 h = MAX (y - y1, 0);
1906 case GL_LABEL_OBJECT_HANDLE_SW:
1907 w = MAX (x2 - x, 0);
1908 h = MAX (y - y1, 0);
1911 case GL_LABEL_OBJECT_HANDLE_W:
1912 w = MAX (x2 - x, 0);
1915 case GL_LABEL_OBJECT_HANDLE_P1:
1924 case GL_LABEL_OBJECT_HANDLE_P2:
1932 g_print ("Invalid handle.\n"); /* Should not happen! */
1935 if ( (view->resize_handle != GL_LABEL_OBJECT_HANDLE_P1) &&
1936 (view->resize_handle != GL_LABEL_OBJECT_HANDLE_P2) )
1938 if ( view->resize_honor_aspect )
1940 gl_label_object_set_size_honor_aspect (view->resize_object, w, h);
1944 gl_label_object_set_size (view->resize_object, w, h);
1948 * Query the new size in case it was constrained.
1950 gl_label_object_get_size (view->resize_object, &w, &h);
1955 switch (view->resize_handle)
1958 case GL_LABEL_OBJECT_HANDLE_NW:
1963 case GL_LABEL_OBJECT_HANDLE_N:
1964 case GL_LABEL_OBJECT_HANDLE_NE:
1969 case GL_LABEL_OBJECT_HANDLE_E:
1970 case GL_LABEL_OBJECT_HANDLE_SE:
1971 case GL_LABEL_OBJECT_HANDLE_S:
1975 case GL_LABEL_OBJECT_HANDLE_SW:
1976 case GL_LABEL_OBJECT_HANDLE_W:
1982 g_print ("Invalid handle.\n"); /* Should not happen! */
1987 gl_label_object_set_size (view->resize_object, dx, dy);
1991 * Put new origin back into world coordinates and set.
1993 cairo_user_to_device (cr, &x0, &y0);
1995 cairo_device_to_user (cr, &x0, &y0);
1996 gl_label_object_set_position (view->resize_object, x0, y0);
2003 * Local Variables: -- emacs
2005 * c-basic-offset: 8 -- emacs
2006 * tab-width: 8 -- emacs
2007 * indent-tabs-mode: nil -- emacs