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 expose_cb (glView *view,
129 GdkEventExpose *event);
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), "expose-event",
312 G_CALLBACK (expose_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_OBJECT_CLASS (gl_view_parent_class)->finalize (object);
352 gl_debug (DEBUG_VIEW, "END");
356 /****************************************************************************/
357 /* NEW view object. */
358 /****************************************************************************/
360 gl_view_new (glLabel *label)
364 gl_debug (DEBUG_VIEW, "START");
366 g_return_val_if_fail (label && GL_IS_LABEL (label), NULL);
368 view = g_object_new (GL_TYPE_VIEW, NULL);
370 gl_view_construct (view, label);
372 gl_debug (DEBUG_VIEW, "END");
374 return GTK_WIDGET (view);
378 /*---------------------------------------------------------------------------*/
379 /* PRIVATE. Construct composite widget. */
380 /*---------------------------------------------------------------------------*/
382 gl_view_construct (glView *view,
385 gl_debug (DEBUG_VIEW, "START");
387 g_return_if_fail (GL_IS_VIEW (view));
391 g_signal_connect_swapped (G_OBJECT (view->label), "selection_changed",
392 G_CALLBACK (label_changed_cb), view);
393 g_signal_connect_swapped (G_OBJECT (view->label), "changed",
394 G_CALLBACK (label_changed_cb), view);
395 g_signal_connect_swapped (G_OBJECT (view->label), "size_changed",
396 G_CALLBACK (label_resized_cb), view);
398 gl_debug (DEBUG_VIEW, "END");
402 /*---------------------------------------------------------------------------*/
403 /* PRIAVTE. Calculate 1:1 scale for screen. */
404 /*---------------------------------------------------------------------------*/
406 get_home_scale (glView *view)
409 gdouble screen_width_pixels;
410 gdouble screen_width_mm;
411 gdouble screen_height_pixels;
412 gdouble screen_height_mm;
413 gdouble x_pixels_per_mm;
414 gdouble y_pixels_per_mm;
417 if (view->canvas == NULL) return 1.0;
419 if (!gtk_widget_has_screen (GTK_WIDGET (view->canvas))) return 1.0;
421 screen = gtk_widget_get_screen (GTK_WIDGET (view->canvas));
423 gl_debug (DEBUG_VIEW, "Screen = %p", screen);
425 screen_width_pixels = gdk_screen_get_width (screen);
426 screen_width_mm = gdk_screen_get_width_mm (screen);
427 screen_height_pixels = gdk_screen_get_height (screen);
428 screen_height_mm = gdk_screen_get_height_mm (screen);
430 x_pixels_per_mm = screen_width_pixels / screen_width_mm;
431 y_pixels_per_mm = screen_height_pixels / screen_height_mm;
433 gl_debug (DEBUG_VIEW, "Horizontal dot pitch: %g pixels/mm (%g dpi)",
434 x_pixels_per_mm, x_pixels_per_mm * 25.4);
435 gl_debug (DEBUG_VIEW, "Vertical dot pitch: %g pixels/mm (%g dpi)",
436 y_pixels_per_mm, y_pixels_per_mm * 25.4);
438 scale = (x_pixels_per_mm + y_pixels_per_mm) / 2.0;
440 gl_debug (DEBUG_VIEW, "Average dot pitch: %g pixels/mm (%g dpi)",
441 scale, scale * 25.4);
443 scale /= POINTS_PER_MM;
445 gl_debug (DEBUG_VIEW, "Scale = %g pixels/point", scale);
447 /* Make sure scale is somewhat sane. */
448 if ( (scale < 0.25) || (scale > 4.0) ) return 1.0;
454 /*---------------------------------------------------------------------------*/
455 /* Prefs "changed" callback. */
456 /*---------------------------------------------------------------------------*/
458 prefs_changed_cb (glView *view)
462 units = gl_prefs_model_get_units (gl_prefs);
463 view->grid_spacing = gl_units_util_get_grid_size (units);
465 gl_view_update (view);
469 /*---------------------------------------------------------------------------*/
470 /* Schedule canvas update. */
471 /*---------------------------------------------------------------------------*/
473 gl_view_update (glView *view)
478 gl_debug (DEBUG_VIEW, "START");
480 window = gtk_widget_get_window (GTK_WIDGET (view->canvas));
484 if ( !view->update_scheduled_flag )
486 view->update_scheduled_flag = TRUE;
488 region = gdk_drawable_get_clip_region (window);
489 /* redraw the cairo canvas completely by exposing it */
490 gdk_window_invalidate_region (window, region, TRUE);
491 gdk_region_destroy (region);
494 gl_debug (DEBUG_VIEW, "END");
498 /*---------------------------------------------------------------------------*/
499 /* Schedule canvas region update. */
500 /*---------------------------------------------------------------------------*/
502 gl_view_update_region (glView *view,
504 glLabelRegion *region)
510 gl_debug (DEBUG_VIEW, "START");
512 window = gtk_widget_get_window (GTK_WIDGET (view->canvas));
516 x = MIN (region->x1, region->x2);
517 y = MIN (region->y1, region->y2);
518 w = fabs (region->x2 - region->x1);
519 h = fabs (region->y2 - region->y1);
521 cairo_user_to_device (cr, &x, &y);
522 cairo_user_to_device_distance (cr, &w, &h);
529 gdk_window_invalidate_rect (window, &rect, TRUE);
531 gl_debug (DEBUG_VIEW, "END");
535 /*---------------------------------------------------------------------------*/
536 /* PRIVATE. Expose handler. */
537 /*---------------------------------------------------------------------------*/
539 expose_cb (glView *view,
540 GdkEventExpose *event)
542 GdkWindow *bin_window;
545 gl_debug (DEBUG_VIEW, "START");
547 view->update_scheduled_flag = FALSE;
549 bin_window = gtk_layout_get_bin_window (GTK_LAYOUT (view->canvas));
550 cr = gdk_cairo_create (bin_window);
553 event->area.x, event->area.y,
554 event->area.width, event->area.height);
557 draw_layers (view, cr);
561 gl_debug (DEBUG_VIEW, "END");
567 /*---------------------------------------------------------------------------*/
568 /* PRIVATE. Realize handler. */
569 /*---------------------------------------------------------------------------*/
571 realize_cb (glView *view)
573 g_return_if_fail (view && GL_IS_VIEW (view));
575 gl_debug (DEBUG_VIEW, "START");
577 if (view->zoom_to_fit_flag) {
578 /* Maintain best fit zoom */
579 gl_view_zoom_to_fit (view);
582 gl_debug (DEBUG_VIEW, "END");
586 /*---------------------------------------------------------------------------*/
587 /* PRIVATE. Size allocation changed callback. */
588 /*---------------------------------------------------------------------------*/
590 size_allocate_cb (glView *view,
591 GtkAllocation *allocation)
593 GtkAdjustment *hadjustment;
594 GtkAdjustment *vadjustment;
596 gl_debug (DEBUG_VIEW, "START");
598 hadjustment = gtk_layout_get_hadjustment(GTK_LAYOUT (view->canvas));
599 vadjustment = gtk_layout_get_vadjustment(GTK_LAYOUT (view->canvas));
601 gtk_adjustment_set_page_size( hadjustment, allocation->width);
602 gtk_adjustment_set_page_increment( hadjustment, allocation->width / 2);
604 gtk_adjustment_set_page_size( vadjustment, allocation->height);
605 gtk_adjustment_set_page_increment( vadjustment, allocation->height / 2);
607 g_signal_emit_by_name (hadjustment, "changed");
608 g_signal_emit_by_name (vadjustment, "changed");
610 if (view->zoom_to_fit_flag) {
611 /* Maintain best fit zoom */
612 gl_view_zoom_to_fit (view);
615 gl_debug (DEBUG_VIEW, "END");
619 /*---------------------------------------------------------------------------*/
620 /* PRIVATE. Screen changed callback. */
621 /*---------------------------------------------------------------------------*/
623 screen_changed_cb (glView *view)
625 gl_debug (DEBUG_VIEW, "START");
627 if (gtk_widget_has_screen (GTK_WIDGET (view->canvas))) {
629 view->home_scale = get_home_scale (view);
631 if (view->zoom_to_fit_flag) {
632 /* Maintain best fit zoom */
633 gl_view_zoom_to_fit (view);
637 gl_debug (DEBUG_VIEW, "END");
641 /*---------------------------------------------------------------------------*/
642 /* PRIVATE. Handle label changed event. */
643 /*---------------------------------------------------------------------------*/
645 label_changed_cb (glView *view)
647 g_return_if_fail (view && GL_IS_VIEW (view));
649 gl_debug (DEBUG_VIEW, "START");
651 gl_view_update (view);
653 gl_debug (DEBUG_VIEW, "END");
657 /*---------------------------------------------------------------------------*/
658 /* PRIVATE. Handle label resize event. */
659 /*---------------------------------------------------------------------------*/
661 label_resized_cb (glView *view)
663 GtkAdjustment *hadjustment;
664 GtkAdjustment *vadjustment;
666 g_return_if_fail (view && GL_IS_VIEW (view));
668 gl_debug (DEBUG_VIEW, "START");
670 hadjustment = gtk_layout_get_hadjustment(GTK_LAYOUT (view->canvas));
671 vadjustment = gtk_layout_get_vadjustment(GTK_LAYOUT (view->canvas));
673 g_signal_emit_by_name (hadjustment, "changed");
674 g_signal_emit_by_name (vadjustment, "changed");
676 gl_view_update (view);
678 gl_debug (DEBUG_VIEW, "END");
682 /*---------------------------------------------------------------------------*/
683 /* PRIVATE. Create, draw and order layers. */
684 /*---------------------------------------------------------------------------*/
686 draw_layers (glView *view,
689 GdkWindow *bin_window;
692 gint canvas_w, canvas_h;
694 g_return_if_fail (view && GL_IS_VIEW (view));
695 g_return_if_fail (view->label && GL_IS_LABEL (view->label));
697 gl_debug (DEBUG_VIEW, "START");
699 bin_window = gtk_layout_get_bin_window (GTK_LAYOUT (view->canvas));
701 scale = view->zoom * view->home_scale;
703 gl_label_get_size (view->label, &w, &h);
705 scale = view->home_scale * view->zoom;
706 gtk_layout_set_size (GTK_LAYOUT (view->canvas), w*scale+8, h*scale+8);
708 gdk_drawable_get_size (bin_window, &canvas_w, &canvas_h);
710 view->x0 = (canvas_w/scale - w) / 2.0;
711 view->y0 = (canvas_h/scale - h) / 2.0;
717 cairo_scale (cr, scale, scale);
718 cairo_translate (cr, view->x0, view->y0);
720 draw_bg_layer (view, cr);
721 draw_grid_layer (view, cr);
722 draw_markup_layer (view, cr);
723 draw_objects_layer (view, cr);
724 draw_fg_layer (view, cr);
725 draw_highlight_layer (view, cr);
726 draw_select_region_layer (view, cr);
730 gl_debug (DEBUG_VIEW, "END");
735 /*---------------------------------------------------------------------------*/
736 /* PRIVATE. Draw background */
737 /*---------------------------------------------------------------------------*/
739 draw_bg_layer (glView *view,
743 const lglTemplate *template;
744 gboolean rotate_flag;
746 g_return_if_fail (view && GL_IS_VIEW (view));
747 g_return_if_fail (view->label && GL_IS_LABEL (view->label));
749 scale = view->home_scale * view->zoom;
751 template = gl_label_get_template (view->label);
752 rotate_flag = gl_label_get_rotate_flag (view->label);
755 cairo_translate (cr, SHADOW_OFFSET_PIXELS/scale, SHADOW_OFFSET_PIXELS/scale);
756 gl_cairo_label_path (cr, template, rotate_flag, FALSE);
757 cairo_set_source_rgb (cr, SHADOW_RGB_ARGS);
758 cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
762 gl_cairo_label_path (cr, template, rotate_flag, FALSE);
763 cairo_set_source_rgb (cr, PAPER_RGB_ARGS);
764 cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
769 /*---------------------------------------------------------------------------*/
770 /* PRIVATE. Draw grid lines. */
771 /*---------------------------------------------------------------------------*/
773 draw_grid_layer (glView *view,
776 const lglTemplate *template;
777 gboolean rotate_flag;
778 const lglTemplateFrame *frame;
783 gl_debug (DEBUG_VIEW, "START");
785 g_return_if_fail (view && GL_IS_VIEW (view));
786 g_return_if_fail (view->label && GL_IS_LABEL(view->label));
788 if (view->grid_visible)
791 template = gl_label_get_template (view->label);
792 rotate_flag = gl_label_get_rotate_flag (view->label);
793 frame = (lglTemplateFrame *)template->frames->data;
795 gl_label_get_size (view->label, &w, &h);
797 if (frame->shape == LGL_TEMPLATE_FRAME_SHAPE_RECT) {
798 x0 = view->grid_spacing;
799 y0 = view->grid_spacing;
801 /* round labels, adjust grid to line up with center of label. */
802 x0 = fmod (w/2.0, view->grid_spacing);
803 y0 = fmod (h/2.0, view->grid_spacing);
809 gl_cairo_label_path (cr, template, rotate_flag, FALSE);
812 cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
813 cairo_set_line_width (cr, GRID_LINE_WIDTH_PIXELS/(view->home_scale * view->zoom));
814 cairo_set_source_rgb (cr, GRID_RGB_ARGS);
816 for ( x=x0; x < w; x += view->grid_spacing )
818 cairo_move_to (cr, x, 0);
819 cairo_line_to (cr, x, h);
823 for ( y=y0; y < h; y += view->grid_spacing )
825 cairo_move_to (cr, 0, y);
826 cairo_line_to (cr, w, y);
834 gl_debug (DEBUG_VIEW, "END");
838 /*---------------------------------------------------------------------------*/
839 /* PRIVATE. Draw markup layer. */
840 /*---------------------------------------------------------------------------*/
842 draw_markup_layer (glView *view,
845 const lglTemplate *template;
846 const lglTemplateFrame *frame;
847 gboolean rotate_flag;
849 lglTemplateMarkup *markup;
850 gdouble width, height;
852 g_return_if_fail (view && GL_IS_VIEW (view));
853 g_return_if_fail (view->label && GL_IS_LABEL (view->label));
855 if (view->markup_visible)
858 template = gl_label_get_template (view->label);
859 frame = (lglTemplateFrame *)template->frames->data;
860 rotate_flag = gl_label_get_rotate_flag (view->label);
866 lgl_template_frame_get_size (frame, &width, &height);
867 cairo_rotate (cr, -M_PI/2.0);
868 cairo_translate (cr, -width, 0.0);
871 cairo_set_line_width (cr, MARKUP_LINE_WIDTH_PIXELS/(view->home_scale * view->zoom));
872 cairo_set_source_rgb (cr, MARKUP_RGB_ARGS);
874 for ( p=frame->all.markups; p != NULL; p=p->next )
876 markup = (lglTemplateMarkup *)p->data;
878 gl_cairo_markup_path (cr, markup, view->label);
889 /*---------------------------------------------------------------------------*/
890 /* PRIVATE. Draw objects layer. */
891 /*---------------------------------------------------------------------------*/
893 draw_objects_layer (glView *view,
896 gl_label_draw (view->label, cr, TRUE, NULL);
900 /*---------------------------------------------------------------------------*/
901 /* PRIVATE. Draw foreground */
902 /*---------------------------------------------------------------------------*/
904 draw_fg_layer (glView *view,
907 const lglTemplate *template;
908 gboolean rotate_flag;
910 g_return_if_fail (view && GL_IS_VIEW (view));
911 g_return_if_fail (view->label && GL_IS_LABEL (view->label));
913 template = gl_label_get_template (view->label);
914 rotate_flag = gl_label_get_rotate_flag (view->label);
916 gl_cairo_label_path (cr, template, rotate_flag, FALSE);
918 cairo_set_line_width (cr, OUTLINE_WIDTH_PIXELS/(view->home_scale * view->zoom));
919 cairo_set_source_rgb (cr, OUTLINE_RGB_ARGS);
924 /*---------------------------------------------------------------------------*/
925 /* PRIVATE. Create highlight layer. */
926 /*---------------------------------------------------------------------------*/
928 draw_highlight_layer (glView *view,
931 GList *selection_list;
933 glLabelObject *object;
935 g_return_if_fail (view && GL_IS_VIEW (view));
939 cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
941 selection_list = gl_label_get_selection_list (view->label);
943 for (p_obj = selection_list; p_obj != NULL; p_obj = p_obj->next)
945 object = GL_LABEL_OBJECT (p_obj->data);
947 gl_label_object_draw_handles (object, cr);
950 g_list_free (selection_list);
956 /*---------------------------------------------------------------------------*/
957 /* PRIVATE. Draw select region layer. */
958 /*---------------------------------------------------------------------------*/
960 draw_select_region_layer (glView *view,
966 g_return_if_fail (view && GL_IS_VIEW (view));
968 if (view->select_region_visible)
970 x1 = MIN (view->select_region.x1, view->select_region.x2);
971 y1 = MIN (view->select_region.y1, view->select_region.y2);
972 w = fabs (view->select_region.x2 - view->select_region.x1);
973 h = fabs (view->select_region.y2 - view->select_region.y1);
977 cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
979 cairo_rectangle (cr, x1, y1, w, h);
981 cairo_set_source_rgba (cr, SELECT_FILL_RGBA_ARGS);
982 cairo_fill_preserve (cr);
984 cairo_set_line_width (cr, SELECT_LINE_WIDTH_PIXELS/(view->home_scale * view->zoom));
985 cairo_set_source_rgba (cr, SELECT_LINE_RGBA_ARGS);
993 /*****************************************************************************/
995 /*****************************************************************************/
997 gl_view_show_grid (glView *view)
999 g_return_if_fail (view && GL_IS_VIEW (view));
1001 view->grid_visible = TRUE;
1002 gl_view_update (view);
1006 /*****************************************************************************/
1008 /*****************************************************************************/
1010 gl_view_hide_grid (glView *view)
1012 g_return_if_fail (view && GL_IS_VIEW (view));
1014 view->grid_visible = FALSE;
1015 gl_view_update (view);
1019 /*****************************************************************************/
1021 /*****************************************************************************/
1023 gl_view_show_markup (glView *view)
1025 g_return_if_fail (view && GL_IS_VIEW (view));
1027 view->markup_visible = TRUE;
1028 gl_view_update (view);
1032 /*****************************************************************************/
1034 /*****************************************************************************/
1036 gl_view_hide_markup (glView *view)
1038 g_return_if_fail (view && GL_IS_VIEW (view));
1040 view->markup_visible = FALSE;
1041 gl_view_update (view);
1045 /*****************************************************************************/
1046 /* Set arrow mode. */
1047 /*****************************************************************************/
1049 gl_view_arrow_mode (glView *view)
1054 gl_debug (DEBUG_VIEW, "START");
1056 g_return_if_fail (view && GL_IS_VIEW (view));
1058 window = gtk_widget_get_window (view->canvas);
1060 cursor = gdk_cursor_new (GDK_LEFT_PTR);
1061 gdk_window_set_cursor (window, cursor);
1062 gdk_cursor_unref (cursor);
1064 view->mode = GL_VIEW_MODE_ARROW;
1065 view->state = GL_VIEW_IDLE;
1067 gl_debug (DEBUG_VIEW, "END");
1071 /*****************************************************************************/
1072 /* Set create text object mode. */
1073 /*****************************************************************************/
1075 gl_view_object_create_mode (glView *view,
1076 glLabelObjectType type)
1079 GdkCursor *cursor = NULL;
1081 gl_debug (DEBUG_VIEW, "START");
1083 g_return_if_fail (view && GL_IS_VIEW (view));
1085 window = gtk_widget_get_window (view->canvas);
1089 case GL_LABEL_OBJECT_BOX:
1090 cursor = gl_view_box_get_create_cursor ();
1092 case GL_LABEL_OBJECT_ELLIPSE:
1093 cursor = gl_view_ellipse_get_create_cursor ();
1095 case GL_LABEL_OBJECT_LINE:
1096 cursor = gl_view_line_get_create_cursor ();
1098 case GL_LABEL_OBJECT_IMAGE:
1099 cursor = gl_view_image_get_create_cursor ();
1101 case GL_LABEL_OBJECT_TEXT:
1102 cursor = gl_view_text_get_create_cursor ();
1104 case GL_LABEL_OBJECT_BARCODE:
1105 cursor = gl_view_barcode_get_create_cursor ();
1108 g_message ("Invalid label object type.");/*Should not happen!*/
1112 gdk_window_set_cursor (window, cursor);
1113 gdk_cursor_unref (cursor);
1115 view->mode = GL_VIEW_MODE_OBJECT_CREATE;
1116 view->state = GL_VIEW_IDLE;
1117 view->create_type = type;
1119 gl_debug (DEBUG_VIEW, "END");
1123 /*****************************************************************************/
1124 /* Zoom in one "notch" */
1125 /*****************************************************************************/
1127 gl_view_zoom_in (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 = 1; /* start with 2nd largest scale */
1138 dist_min = fabs (zooms[1] - view->zoom);
1139 for (i = 2; i < N_ZOOMS; i++) {
1140 dist = fabs (zooms[i] - view->zoom);
1141 if (dist < dist_min) {
1147 /* zoom in one "notch" */
1148 i = MAX (0, i_min - 1);
1149 gl_debug (DEBUG_VIEW, "zoom[%d] = %g", i, zooms[i]);
1150 set_zoom_real (view, zooms[i], FALSE);
1152 gl_debug (DEBUG_VIEW, "END");
1156 /*****************************************************************************/
1157 /* Zoom out one "notch" */
1158 /*****************************************************************************/
1160 gl_view_zoom_out (glView *view)
1163 gdouble dist, dist_min;
1165 gl_debug (DEBUG_VIEW, "START");
1167 g_return_if_fail (view && GL_IS_VIEW (view));
1169 /* Find index of current scale (or best match) */
1170 i_min = 0; /* start with largest scale */
1171 dist_min = fabs (zooms[0] - view->zoom);
1172 for (i = 1; i < N_ZOOMS; i++) {
1173 dist = fabs (zooms[i] - view->zoom);
1174 if (dist < dist_min) {
1180 /* zoom out one "notch" */
1181 if (i_min >= N_ZOOMS)
1186 set_zoom_real (view, zooms[i], FALSE);
1188 gl_debug (DEBUG_VIEW, "END");
1192 /*****************************************************************************/
1193 /* Set zoom to best fit. */
1194 /*****************************************************************************/
1196 gl_view_zoom_to_fit (glView *view)
1198 GtkAllocation allocation;
1199 gint w_view, h_view;
1200 gdouble w_label, h_label;
1201 gdouble x_scale, y_scale, scale;
1203 gl_debug (DEBUG_VIEW, "");
1205 if ( ! gtk_widget_get_window (GTK_WIDGET (view)) ) {
1206 /* Delay until realized. */
1207 view->zoom_to_fit_flag = TRUE;
1211 gtk_widget_get_allocation (GTK_WIDGET (view), &allocation);
1212 w_view = allocation.width;
1213 h_view = allocation.height;
1215 gl_label_get_size (GL_LABEL(view->label), &w_label, &h_label);
1217 gl_debug (DEBUG_VIEW, "View size: %d, %d", w_view, h_view);
1218 gl_debug (DEBUG_VIEW, "Label size: %g, %g", w_label, h_label);
1220 /* Calculate best scale */
1221 x_scale = (double)(w_view - ZOOMTOFIT_PAD) / w_label;
1222 y_scale = (double)(h_view - ZOOMTOFIT_PAD) / h_label;
1223 scale = MIN (x_scale, y_scale);
1224 gl_debug (DEBUG_VIEW, "Candidate zooms: %g, %g => %g", x_scale, y_scale, scale);
1227 gl_debug (DEBUG_VIEW, "Scale: %g", scale);
1228 scale = MIN (scale, zooms[0]*view->home_scale);
1229 scale = MAX (scale, zooms[N_ZOOMS-1]*view->home_scale);
1230 gl_debug (DEBUG_VIEW, "Limitted scale: %g", scale);
1232 set_zoom_real (view, scale/view->home_scale, TRUE);
1236 /*****************************************************************************/
1237 /* Set current zoom factor to explicit value. */
1238 /*****************************************************************************/
1240 gl_view_set_zoom (glView *view,
1243 gl_debug (DEBUG_VIEW, "START");
1245 set_zoom_real (view, zoom, FALSE);
1247 gl_debug (DEBUG_VIEW, "END");
1251 /*---------------------------------------------------------------------------*/
1252 /* PRIVATE. Set canvas scale. */
1253 /*---------------------------------------------------------------------------*/
1255 set_zoom_real (glView *view,
1257 gboolean zoom_to_fit_flag)
1259 gl_debug (DEBUG_VIEW, "START");
1261 g_return_if_fail (view && GL_IS_VIEW (view));
1262 g_return_if_fail (zoom > 0.0);
1264 /* Limit, if needed */
1265 gl_debug (DEBUG_VIEW, "Zoom requested: %g", zoom);
1266 zoom = MIN (zoom, zooms[0]);
1267 zoom = MAX (zoom, zooms[N_ZOOMS-1]);
1268 gl_debug (DEBUG_VIEW, "Limitted zoom: %g", zoom);
1270 if ( zoom != view->zoom ) {
1273 view->zoom_to_fit_flag = zoom_to_fit_flag;
1275 gl_view_update (view);
1277 g_signal_emit (G_OBJECT(view), signals[ZOOM_CHANGED], 0, zoom);
1281 gl_debug (DEBUG_VIEW, "END");
1286 /*****************************************************************************/
1287 /* Get current zoom factor. */
1288 /*****************************************************************************/
1290 gl_view_get_zoom (glView *view)
1292 gl_debug (DEBUG_VIEW, "");
1294 g_return_val_if_fail (view && GL_IS_VIEW (view), 1.0);
1300 /*****************************************************************************/
1301 /* Is this the maximum zoom level. */
1302 /*****************************************************************************/
1304 gl_view_is_zoom_max (glView *view)
1306 gl_debug (DEBUG_VIEW, "");
1308 g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
1310 return view->zoom >= zooms[0];
1314 /*****************************************************************************/
1315 /* Is this the minimum zoom level. */
1316 /*****************************************************************************/
1318 gl_view_is_zoom_min (glView *view)
1320 gl_debug (DEBUG_VIEW, "");
1322 g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
1324 return view->zoom <= zooms[N_ZOOMS-1];
1328 /*---------------------------------------------------------------------------*/
1329 /* PRIVATE. Focus in event handler. */
1330 /*---------------------------------------------------------------------------*/
1332 focus_in_event_cb (glView *view,
1333 GdkEventFocus *event)
1339 /*---------------------------------------------------------------------------*/
1340 /* PRIVATE. Focus out event handler. */
1341 /*---------------------------------------------------------------------------*/
1343 focus_out_event_cb (glView *view,
1344 GdkEventFocus *event)
1350 /*---------------------------------------------------------------------------*/
1351 /* PRIVATE. Enter notify event handler. */
1352 /*---------------------------------------------------------------------------*/
1354 enter_notify_event_cb (glView *view,
1355 GdkEventCrossing *event)
1361 /*---------------------------------------------------------------------------*/
1362 /* PRIVATE. Leave notify event handler. */
1363 /*---------------------------------------------------------------------------*/
1365 leave_notify_event_cb (glView *view,
1366 GdkEventCrossing *event)
1369 g_signal_emit (G_OBJECT(view), signals[POINTER_EXIT], 0);
1375 /*---------------------------------------------------------------------------*/
1376 /* PRIVATE. Motion notify event handler. */
1377 /*---------------------------------------------------------------------------*/
1379 motion_notify_event_cb (glView *view,
1380 GdkEventMotion *event)
1382 gboolean return_value = FALSE;
1383 GdkWindow *bin_window;
1389 glLabelObjectHandle handle;
1391 bin_window = gtk_layout_get_bin_window (GTK_LAYOUT (view->canvas));
1392 window = gtk_widget_get_window (view->canvas);
1394 cr = gdk_cairo_create (bin_window);
1397 * Translate to label coordinates
1399 scale = view->zoom * view->home_scale;
1400 cairo_scale (cr, scale, scale);
1401 cairo_translate (cr, view->x0, view->y0);
1405 cairo_device_to_user (cr, &x, &y);
1408 * Emit signal regardless of mode
1410 g_signal_emit (G_OBJECT(view), signals[POINTER_MOVED], 0, x, y);
1413 * Handle event as appropriate for mode
1418 case GL_VIEW_MODE_ARROW:
1419 switch (view->state)
1423 if ( gl_label_is_selection_atomic (view->label) &&
1424 gl_label_get_handle_at (view->label, cr, event->x, event->y, &handle) )
1426 cursor = gdk_cursor_new (GDK_CROSSHAIR);
1428 else if (gl_label_object_at (view->label, cr, event->x, event->y))
1430 cursor = gdk_cursor_new (GDK_FLEUR);
1434 cursor = gdk_cursor_new (GDK_LEFT_PTR);
1436 gdk_window_set_cursor (window, cursor);
1437 gdk_cursor_unref (cursor);
1440 case GL_VIEW_ARROW_SELECT_REGION:
1442 gl_view_update_region (view, cr, &view->select_region);
1444 view->select_region.x2 = x;
1445 view->select_region.y2 = y;
1447 gl_view_update_region (view, cr, &view->select_region);
1449 gl_view_update (view);
1453 case GL_VIEW_ARROW_MOVE:
1454 gl_label_move_selection (view->label,
1455 (x - view->move_last_x),
1456 (y - view->move_last_y));
1457 view->move_last_x = x;
1458 view->move_last_y = y;
1461 case GL_VIEW_ARROW_RESIZE:
1462 resize_event (view, cr, event->x, event->y);
1466 g_message ("Invalid arrow state."); /*Should not happen!*/
1468 return_value = TRUE;
1472 case GL_VIEW_MODE_OBJECT_CREATE:
1473 if (view->state != GL_VIEW_IDLE)
1475 switch (view->create_type)
1477 case GL_LABEL_OBJECT_BOX:
1478 gl_view_box_create_motion_event (view, x, y);
1480 case GL_LABEL_OBJECT_ELLIPSE:
1481 gl_view_ellipse_create_motion_event (view, x, y);
1483 case GL_LABEL_OBJECT_LINE:
1484 gl_view_line_create_motion_event (view, x, y);
1486 case GL_LABEL_OBJECT_IMAGE:
1487 gl_view_image_create_motion_event (view, x, y);
1489 case GL_LABEL_OBJECT_TEXT:
1490 gl_view_text_create_motion_event (view, x, y);
1492 case GL_LABEL_OBJECT_BARCODE:
1493 gl_view_barcode_create_motion_event (view, x, y);
1496 g_message ("Invalid create type."); /*Should not happen!*/
1503 g_message ("Invalid view mode."); /*Should not happen!*/
1510 * FIXME: we re-establish grabs here if the grab has been lost. We seem to be
1511 * losing grabs when we emit signals that lead to the manipulation of
1512 * the GtkUIManager. Needs more investigation
1514 if (view->grabbed_flag && !gdk_pointer_is_grabbed ())
1516 gdk_pointer_grab (bin_window,
1518 (GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK),
1524 return return_value;
1528 /*---------------------------------------------------------------------------*/
1529 /* PRIVATE. Button press event handler. */
1530 /*---------------------------------------------------------------------------*/
1532 button_press_event_cb (glView *view,
1533 GdkEventButton *event)
1535 gboolean return_value = FALSE;
1536 GdkWindow *bin_window;
1540 glLabelObject *object;
1541 glLabelObjectHandle handle;
1543 gtk_widget_grab_focus(GTK_WIDGET (view->canvas));
1545 bin_window = gtk_layout_get_bin_window (GTK_LAYOUT (view->canvas));
1547 cr = gdk_cairo_create (bin_window);
1550 * Translate to label coordinates
1552 scale = view->zoom * view->home_scale;
1553 cairo_scale (cr, scale, scale);
1554 cairo_translate (cr, view->x0, view->y0);
1558 cairo_device_to_user (cr, &x, &y);
1560 switch (event->button)
1565 * Handle event as appropriate for mode
1569 case GL_VIEW_MODE_ARROW:
1570 if ( gl_label_is_selection_atomic (view->label) &&
1571 (object = gl_label_get_handle_at (view->label, cr, event->x, event->y, &handle)) )
1573 view->resize_object = object;
1574 view->resize_handle = handle;
1575 view->resize_honor_aspect = event->state & GDK_CONTROL_MASK;
1577 view->state = GL_VIEW_ARROW_RESIZE;
1579 else if ((object = gl_label_object_at (view->label, cr, event->x, event->y)))
1581 if (event->state & GDK_CONTROL_MASK)
1583 if (gl_label_object_is_selected (object))
1585 /* Un-selecting a selected item */
1586 gl_label_unselect_object (view->label, object);
1588 /* Add to current selection */
1589 gl_label_select_object (view->label, object);
1594 if (!gl_label_object_is_selected (object))
1596 /* remove any selections before adding */
1597 gl_label_unselect_all (view->label);
1598 /* Add to current selection */
1599 gl_label_select_object (view->label, object);
1602 view->move_last_x = x;
1603 view->move_last_y = y;
1605 view->state = GL_VIEW_ARROW_MOVE;
1609 if (!(event->state & GDK_CONTROL_MASK))
1611 gl_label_unselect_all (view->label);
1614 view->select_region_visible = TRUE;
1615 view->select_region.x1 = x;
1616 view->select_region.y1 = y;
1617 view->select_region.x2 = x;
1618 view->select_region.y2 = y;
1620 view->state = GL_VIEW_ARROW_SELECT_REGION;
1624 return_value = TRUE;
1627 case GL_VIEW_MODE_OBJECT_CREATE:
1628 switch (view->create_type)
1630 case GL_LABEL_OBJECT_BOX:
1631 gl_view_box_create_button_press_event (view, x, y);
1633 case GL_LABEL_OBJECT_ELLIPSE:
1634 gl_view_ellipse_create_button_press_event (view, x, y);
1636 case GL_LABEL_OBJECT_LINE:
1637 gl_view_line_create_button_press_event (view, x, y);
1639 case GL_LABEL_OBJECT_IMAGE:
1640 gl_view_image_create_button_press_event (view, x, y);
1642 case GL_LABEL_OBJECT_TEXT:
1643 gl_view_text_create_button_press_event (view, x, y);
1645 case GL_LABEL_OBJECT_BARCODE:
1646 gl_view_barcode_create_button_press_event (view, x, y);
1649 g_message ("Invalid create type."); /*Should not happen!*/
1651 view->state = GL_VIEW_CREATE_DRAG;
1652 return_value = TRUE;
1656 g_message ("Invalid view mode."); /*Should not happen!*/
1659 view->grabbed_flag = TRUE;
1660 gdk_pointer_grab (bin_window,
1662 (GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK),
1669 g_signal_emit (G_OBJECT (view),
1670 signals[CONTEXT_MENU_ACTIVATE], 0,
1671 event->button, event->time);
1672 return_value = TRUE;
1679 return return_value;
1683 /*---------------------------------------------------------------------------*/
1684 /* PRIVATE. Button release event handler. */
1685 /*---------------------------------------------------------------------------*/
1687 button_release_event_cb (glView *view,
1688 GdkEventButton *event)
1690 gboolean return_value = FALSE;
1691 GdkWindow *bin_window;
1698 bin_window = gtk_layout_get_bin_window (GTK_LAYOUT (view->canvas));
1699 window = gtk_widget_get_window (view->canvas);
1701 cr = gdk_cairo_create (bin_window);
1704 * Translate to label coordinates
1706 scale = view->zoom * view->home_scale;
1707 cairo_scale (cr, scale, scale);
1708 cairo_translate (cr, view->x0, view->y0);
1712 cairo_device_to_user (cr, &x, &y);
1714 switch (event->button)
1718 view->grabbed_flag = FALSE;
1719 gdk_pointer_ungrab (event->time);
1721 * Handle event as appropriate for mode
1725 case GL_VIEW_MODE_ARROW:
1726 switch (view->state)
1728 case GL_VIEW_ARROW_RESIZE:
1729 view->resize_object = NULL;
1731 view->state = GL_VIEW_IDLE;
1734 case GL_VIEW_ARROW_SELECT_REGION:
1736 gl_view_update_region (view, cr, &view->select_region);
1738 gl_view_update (view);
1741 view->select_region_visible = FALSE;
1742 view->select_region.x2 = x;
1743 view->select_region.y2 = y;
1745 gl_label_select_region (view->label, &view->select_region);
1747 view->state = GL_VIEW_IDLE;
1751 view->state = GL_VIEW_IDLE;
1756 return_value = TRUE;
1760 case GL_VIEW_MODE_OBJECT_CREATE:
1761 switch (view->create_type)
1763 case GL_LABEL_OBJECT_BOX:
1764 gl_view_box_create_button_release_event (view, x, y);
1766 case GL_LABEL_OBJECT_ELLIPSE:
1767 gl_view_ellipse_create_button_release_event (view, x, y);
1769 case GL_LABEL_OBJECT_LINE:
1770 gl_view_line_create_button_release_event (view, x, y);
1772 case GL_LABEL_OBJECT_IMAGE:
1773 gl_view_image_create_button_release_event (view, x, y);
1775 case GL_LABEL_OBJECT_TEXT:
1776 gl_view_text_create_button_release_event (view, x, y);
1778 case GL_LABEL_OBJECT_BARCODE:
1779 gl_view_barcode_create_button_release_event (view, x, y);
1782 g_message ("Invalid create type."); /*Should not happen!*/
1784 view->mode = GL_VIEW_MODE_ARROW;
1785 view->state = GL_VIEW_IDLE;
1786 cursor = gdk_cursor_new (GDK_LEFT_PTR);
1787 gdk_window_set_cursor (window, cursor);
1788 gdk_cursor_unref (cursor);
1790 gl_label_select_object (view->label, view->create_object);
1795 g_message ("Invalid view mode."); /*Should not happen!*/
1802 return return_value;
1806 /*---------------------------------------------------------------------------*/
1807 /* PRIVATE. Key press event handler. */
1808 /*---------------------------------------------------------------------------*/
1810 key_press_event_cb (glView *view,
1816 gl_debug (DEBUG_VIEW, "");
1818 window = gtk_widget_get_window (view->canvas);
1820 if ( (view->mode == GL_VIEW_MODE_ARROW) &&
1821 (view->state == GL_VIEW_IDLE) )
1823 switch (event->keyval) {
1827 gl_label_move_selection (view->label, -1.0 / (view->zoom), 0.0);
1831 gl_label_move_selection (view->label, 0.0, -1.0 / (view->zoom));
1835 gl_label_move_selection (view->label, 1.0 / (view->zoom), 0.0);
1839 gl_label_move_selection (view->label, 0.0, 1.0 / (view->zoom));
1843 gl_label_delete_selection (view->label);
1844 cursor = gdk_cursor_new (GDK_LEFT_PTR);
1845 gdk_window_set_cursor (window, cursor);
1846 gdk_cursor_unref (cursor);
1853 return TRUE; /* We handled this or we were dragging. */
1857 /*---------------------------------------------------------------------------*/
1858 /* PRIVATE. Resize object. */
1859 /*---------------------------------------------------------------------------*/
1861 resize_event (glView *view,
1866 cairo_matrix_t matrix;
1867 gdouble x0, y0, x1, y1, x2, y2;
1871 gl_debug (DEBUG_VIEW, "x,y world = %g, %g", x, y);
1874 * Change to item relative coordinates
1877 gl_label_object_get_position (view->resize_object, &x0, &y0);
1878 cairo_translate (cr, x0, y0);
1879 gl_label_object_get_matrix (view->resize_object, &matrix);
1880 cairo_transform (cr, &matrix);
1883 * Initialize origin and 2 corners in object relative coordinates.
1891 gl_label_object_get_size (view->resize_object, &x2, &y2);
1893 gl_debug (DEBUG_VIEW, "x0,y0 object = %g, %g", x0, y0);
1894 gl_debug (DEBUG_VIEW, "x1,y1 object = %g, %g", x1, y1);
1895 gl_debug (DEBUG_VIEW, "x2,y2 object = %g, %g", x2, y2);
1898 * Translate x,y into object relative coordinates.
1900 cairo_device_to_user (cr, &x, &y);
1902 gl_debug (DEBUG_VIEW, "x,y object = %g, %g", x, y);
1907 switch (view->resize_handle)
1910 case GL_LABEL_OBJECT_HANDLE_NW:
1911 w = MAX (x2 - x, 0);
1912 h = MAX (y2 - y, 0);
1915 case GL_LABEL_OBJECT_HANDLE_N:
1917 h = MAX (y2 - y, 0);
1920 case GL_LABEL_OBJECT_HANDLE_NE:
1921 w = MAX (x - x1, 0);
1922 h = MAX (y2 - y, 0);
1925 case GL_LABEL_OBJECT_HANDLE_E:
1926 w = MAX (x - x1, 0);
1930 case GL_LABEL_OBJECT_HANDLE_SE:
1931 w = MAX (x - x1, 0);
1932 h = MAX (y - y1, 0);
1935 case GL_LABEL_OBJECT_HANDLE_S:
1937 h = MAX (y - y1, 0);
1940 case GL_LABEL_OBJECT_HANDLE_SW:
1941 w = MAX (x2 - x, 0);
1942 h = MAX (y - y1, 0);
1945 case GL_LABEL_OBJECT_HANDLE_W:
1946 w = MAX (x2 - x, 0);
1949 case GL_LABEL_OBJECT_HANDLE_P1:
1958 case GL_LABEL_OBJECT_HANDLE_P2:
1966 g_print ("Invalid handle.\n"); /* Should not happen! */
1970 if ( (view->resize_handle != GL_LABEL_OBJECT_HANDLE_P1) &&
1971 (view->resize_handle != GL_LABEL_OBJECT_HANDLE_P2) )
1973 if ( view->resize_honor_aspect )
1975 gl_label_object_set_size_honor_aspect (view->resize_object, w, h, TRUE);
1979 gl_label_object_set_size (view->resize_object, w, h, TRUE);
1983 * Query the new size in case it was constrained.
1985 gl_label_object_get_size (view->resize_object, &w, &h);
1990 switch (view->resize_handle)
1993 case GL_LABEL_OBJECT_HANDLE_NW:
1998 case GL_LABEL_OBJECT_HANDLE_N:
1999 case GL_LABEL_OBJECT_HANDLE_NE:
2004 case GL_LABEL_OBJECT_HANDLE_E:
2005 case GL_LABEL_OBJECT_HANDLE_SE:
2006 case GL_LABEL_OBJECT_HANDLE_S:
2010 case GL_LABEL_OBJECT_HANDLE_SW:
2011 case GL_LABEL_OBJECT_HANDLE_W:
2017 g_print ("Invalid handle.\n"); /* Should not happen! */
2022 gl_label_object_set_size (view->resize_object, dx, dy, TRUE);
2026 * Put new origin back into world coordinates and set.
2028 cairo_user_to_device (cr, &x0, &y0);
2030 cairo_device_to_user (cr, &x0, &y0);
2031 gl_label_object_set_position (view->resize_object, x0, y0, FALSE);
2038 * Local Variables: -- emacs
2040 * c-basic-offset: 8 -- emacs
2041 * tab-width: 8 -- emacs
2042 * indent-tabs-mode: nil -- emacs