1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
4 * (GLABELS) Label and Business Card Creation program for GNOME
6 * view.c: GLabels View module
8 * Copyright (C) 2001-2007 Jim Evins <evins@snaught.com>.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include <glib/gi18n.h>
30 #include <gtk/gtkscrolledwindow.h>
31 #include <gtk/gtklayout.h>
32 #include <gtk/gtkselection.h>
33 #include <gtk/gtkinvisible.h>
34 #include <gdk/gdkkeysyms.h>
39 #include "cairo-label-path.h"
40 #include "cairo-markup-path.h"
41 #include "view-object.h"
43 #include "view-ellipse.h"
44 #include "view-line.h"
45 #include "view-image.h"
46 #include "view-text.h"
47 #include "view-barcode.h"
48 #include "xml-label.h"
55 /*==========================================================================*/
56 /* Private macros and constants. */
57 /*==========================================================================*/
59 #define BG_COLOR GL_COLOR (192, 192, 192)
60 #define OUTLINE_COLOR GL_COLOR (173, 216, 230)
61 #define PAPER_COLOR GL_COLOR (255, 255, 255)
62 #define GRID_COLOR BG_COLOR
63 #define MARKUP_COLOR GL_COLOR (240, 100, 100)
65 #define SEL_LINE_COLOR GL_COLOR_A (0, 0, 255, 128)
66 #define SEL_FILL_COLOR GL_COLOR_A (192, 192, 255, 128)
68 #define ARC_FINE 2 /* Resolution in degrees of large arcs */
69 #define ARC_COURSE 5 /* Resolution in degrees of small arcs */
71 #define ZOOMTOFIT_PAD 16
73 #define POINTS_PER_MM 2.83464566929
77 /*==========================================================================*/
79 /*==========================================================================*/
83 CONTEXT_MENU_ACTIVATE,
92 /*==========================================================================*/
94 /*==========================================================================*/
96 static guint signals[LAST_SIGNAL] = {0};
98 /* "CLIPBOARD" selection */
99 static GdkAtom clipboard_atom = GDK_NONE;
101 static gdouble zooms[] = {
118 #define N_ZOOMS G_N_ELEMENTS(zooms)
121 /*==========================================================================*/
122 /* Local function prototypes */
123 /*==========================================================================*/
125 static void gl_view_finalize (GObject *object);
127 static void gl_view_construct (glView *view,
130 static gdouble get_home_scale (glView *view);
132 static gboolean expose_cb (glView *view,
133 GdkEventExpose *event);
135 static void realize_cb (glView *view);
137 static void size_allocate_cb (glView *view,
138 GtkAllocation *allocation);
140 static void screen_changed_cb (glView *view);
142 static void label_changed_cb (glView *view);
144 static void label_resized_cb (glView *view);
146 static void draw_layers (glView *view,
149 static void draw_bg_layer (glView *view,
151 static void draw_grid_layer (glView *view,
153 static void draw_markup_layer (glView *view,
155 static void draw_objects_layer (glView *view,
157 static void draw_fg_layer (glView *view,
159 static void draw_highlight_layer (glView *view,
161 static void draw_select_region_layer (glView *view,
164 static void select_object_real (glView *view,
165 glViewObject *view_object);
166 static void unselect_object_real (glView *view,
167 glViewObject *view_object);
169 static glViewObject *view_view_object_at (glView *view,
174 static void set_zoom_real (glView *view,
176 gboolean scale_to_fit_flag);
178 static void selection_clear_cb (GtkWidget *widget,
179 GdkEventSelection *event,
182 static void selection_get_cb (GtkWidget *widget,
183 GtkSelectionData *selection_data,
188 static void selection_received_cb (GtkWidget *widget,
189 GtkSelectionData *selection_data,
193 static gboolean focus_in_event_cb (glView *view,
194 GdkEventFocus *event);
196 static gboolean focus_out_event_cb (glView *view,
197 GdkEventFocus *event);
199 static gboolean enter_notify_event_cb (glView *view,
200 GdkEventCrossing *event);
202 static gboolean leave_notify_event_cb (glView *view,
203 GdkEventCrossing *event);
205 static gboolean motion_notify_event_cb (glView *view,
206 GdkEventMotion *event);
208 static gboolean button_press_event_cb (glView *view,
209 GdkEventButton *event);
211 static gboolean button_release_event_cb (glView *view,
212 GdkEventButton *event);
214 static gboolean key_press_event_cb (glView *view,
218 /****************************************************************************/
219 /* Boilerplate Object stuff. */
220 /****************************************************************************/
221 G_DEFINE_TYPE (glView, gl_view, GTK_TYPE_VBOX);
224 gl_view_class_init (glViewClass *class)
226 GObjectClass *object_class = G_OBJECT_CLASS (class);
228 gl_debug (DEBUG_VIEW, "START");
230 gl_view_parent_class = g_type_class_peek_parent (class);
232 object_class->finalize = gl_view_finalize;
234 signals[SELECTION_CHANGED] =
235 g_signal_new ("selection_changed",
236 G_OBJECT_CLASS_TYPE (object_class),
238 G_STRUCT_OFFSET (glViewClass, selection_changed),
240 gl_marshal_VOID__VOID,
244 signals[CONTEXT_MENU_ACTIVATE] =
245 g_signal_new ("context_menu_activate",
246 G_OBJECT_CLASS_TYPE (object_class),
248 G_STRUCT_OFFSET (glViewClass, context_menu_activate),
250 gl_marshal_VOID__INT_UINT,
252 2, G_TYPE_INT, G_TYPE_UINT);
254 signals[ZOOM_CHANGED] =
255 g_signal_new ("zoom_changed",
256 G_OBJECT_CLASS_TYPE (object_class),
258 G_STRUCT_OFFSET (glViewClass, zoom_changed),
260 gl_marshal_VOID__DOUBLE,
264 signals[POINTER_MOVED] =
265 g_signal_new ("pointer_moved",
266 G_OBJECT_CLASS_TYPE (object_class),
268 G_STRUCT_OFFSET (glViewClass, pointer_moved),
270 gl_marshal_VOID__DOUBLE_DOUBLE,
272 2, G_TYPE_DOUBLE, G_TYPE_DOUBLE);
274 signals[POINTER_EXIT] =
275 g_signal_new ("pointer_exit",
276 G_OBJECT_CLASS_TYPE (object_class),
278 G_STRUCT_OFFSET (glViewClass, pointer_exit),
280 gl_marshal_VOID__VOID,
284 signals[MODE_CHANGED] =
285 g_signal_new ("mode_changed",
286 G_OBJECT_CLASS_TYPE (object_class),
288 G_STRUCT_OFFSET (glViewClass, mode_changed),
290 gl_marshal_VOID__VOID,
294 gl_debug (DEBUG_VIEW, "END");
298 gl_view_init (glView *view)
303 gl_debug (DEBUG_VIEW, "START");
306 view->grid_visible = TRUE;
307 view->grid_spacing = 9;
308 view->markup_visible = TRUE;
309 view->default_font_family = NULL;
310 view->mode = GL_VIEW_MODE_ARROW;
311 view->object_list = NULL;
312 view->selected_object_list = NULL;
314 view->home_scale = get_home_scale (view);
319 view->canvas = gtk_layout_new (NULL, NULL);
320 wscroll = gtk_scrolled_window_new (NULL, NULL);
321 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (wscroll),
322 GTK_POLICY_AUTOMATIC,
323 GTK_POLICY_AUTOMATIC);
324 gtk_box_pack_start (GTK_BOX (view), wscroll, TRUE, TRUE, 0);
325 gtk_container_add (GTK_CONTAINER (wscroll), view->canvas);
327 bg_color = gl_color_to_gdk_color (BG_COLOR);
328 gtk_widget_modify_bg (GTK_WIDGET (view->canvas), GTK_STATE_NORMAL, bg_color);
331 GTK_WIDGET_SET_FLAGS (GTK_WIDGET (view->canvas), GTK_CAN_FOCUS);
333 gtk_widget_add_events (GTK_WIDGET (view->canvas),
334 (GDK_FOCUS_CHANGE_MASK |
335 GDK_ENTER_NOTIFY_MASK |
336 GDK_LEAVE_NOTIFY_MASK |
337 GDK_POINTER_MOTION_MASK |
338 GDK_BUTTON_PRESS_MASK |
339 GDK_BUTTON_RELEASE_MASK |
340 GDK_KEY_PRESS_MASK));
342 g_signal_connect_swapped (G_OBJECT (view->canvas), "expose-event",
343 G_CALLBACK (expose_cb), view);
344 g_signal_connect_swapped (G_OBJECT (view->canvas), "realize",
345 G_CALLBACK (realize_cb), view);
346 g_signal_connect_swapped (G_OBJECT (view->canvas), "size-allocate",
347 G_CALLBACK (size_allocate_cb), view);
348 g_signal_connect_swapped (G_OBJECT (view->canvas), "screen-changed",
349 G_CALLBACK (screen_changed_cb), view);
350 g_signal_connect_swapped (G_OBJECT (view->canvas), "focus-in-event",
351 G_CALLBACK (focus_in_event_cb), view);
352 g_signal_connect_swapped (G_OBJECT (view->canvas), "focus-out-event",
353 G_CALLBACK (focus_out_event_cb), view);
354 g_signal_connect_swapped (G_OBJECT (view->canvas), "enter-notify-event",
355 G_CALLBACK (enter_notify_event_cb), view);
356 g_signal_connect_swapped (G_OBJECT (view->canvas), "leave-notify-event",
357 G_CALLBACK (leave_notify_event_cb), view);
358 g_signal_connect_swapped (G_OBJECT (view->canvas), "motion-notify-event",
359 G_CALLBACK (motion_notify_event_cb), view);
360 g_signal_connect_swapped (G_OBJECT (view->canvas), "button-press-event",
361 G_CALLBACK (button_press_event_cb), view);
362 g_signal_connect_swapped (G_OBJECT (view->canvas), "button-release-event",
363 G_CALLBACK (button_release_event_cb), view);
364 g_signal_connect_swapped (G_OBJECT (view->canvas), "key-press-event",
365 G_CALLBACK (key_press_event_cb), view);
370 view->have_selection = FALSE;
371 view->selection_data = NULL;
372 view->invisible = gtk_invisible_new ();
373 if (!clipboard_atom) {
374 clipboard_atom = gdk_atom_intern ("GLABELS_CLIPBOARD", FALSE);
376 gtk_selection_add_target (view->invisible,
377 clipboard_atom, GDK_SELECTION_TYPE_STRING, 1);
378 g_signal_connect (G_OBJECT (view->invisible),
379 "selection_clear_event",
380 G_CALLBACK (selection_clear_cb), view);
381 g_signal_connect (G_OBJECT (view->invisible), "selection_get",
382 G_CALLBACK (selection_get_cb), view);
383 g_signal_connect (G_OBJECT (view->invisible),
384 "selection_received",
385 G_CALLBACK (selection_received_cb), view);
388 * Defaults from preferences
390 gl_view_set_default_font_family (view, gl_prefs->default_font_family);
391 gl_view_set_default_font_size (view, gl_prefs->default_font_size);
392 gl_view_set_default_font_weight (view, gl_prefs->default_font_weight);
393 gl_view_set_default_font_italic_flag (view, gl_prefs->default_font_italic_flag);
394 gl_view_set_default_text_color (view, gl_prefs->default_text_color);
395 gl_view_set_default_text_alignment (view, gl_prefs->default_text_alignment);
396 gl_view_set_default_text_line_spacing (view, gl_prefs->default_text_line_spacing);
397 gl_view_set_default_line_width (view, gl_prefs->default_line_width);
398 gl_view_set_default_line_color (view, gl_prefs->default_line_color);
399 gl_view_set_default_fill_color (view, gl_prefs->default_fill_color);
401 gl_debug (DEBUG_VIEW, "END");
405 gl_view_finalize (GObject *object)
407 glView *view = GL_VIEW (object);
409 gl_debug (DEBUG_VIEW, "START");
411 g_return_if_fail (object != NULL);
412 g_return_if_fail (GL_IS_VIEW (object));
414 if (view->default_font_family) {
415 g_free (view->default_font_family);
418 G_OBJECT_CLASS (gl_view_parent_class)->finalize (object);
420 gl_debug (DEBUG_VIEW, "END");
423 /****************************************************************************/
424 /* NEW view object. */
425 /****************************************************************************/
427 gl_view_new (glLabel *label)
431 gl_debug (DEBUG_VIEW, "START");
433 g_return_val_if_fail (label && GL_IS_LABEL (label), NULL);
435 view = g_object_new (GL_TYPE_VIEW, NULL);
437 gl_view_construct (view, label);
439 gl_debug (DEBUG_VIEW, "END");
441 return GTK_WIDGET (view);
444 /*---------------------------------------------------------------------------*/
445 /* PRIVATE. Construct composite widget. */
446 /*---------------------------------------------------------------------------*/
448 gl_view_construct (glView *view,
452 glLabelObject *object;
454 gl_debug (DEBUG_VIEW, "START");
456 g_return_if_fail (GL_IS_VIEW (view));
460 for (p_obj = label->objects; p_obj != NULL; p_obj = p_obj->next)
462 object = GL_LABEL_OBJECT (p_obj->data);
464 if (GL_IS_LABEL_BOX (object)) {
465 gl_view_box_new (GL_LABEL_BOX(object), view);
466 } else if (GL_IS_LABEL_ELLIPSE (object)) {
467 gl_view_ellipse_new (GL_LABEL_ELLIPSE(object), view);
468 } else if (GL_IS_LABEL_LINE (object)) {
469 gl_view_line_new (GL_LABEL_LINE(object), view);
470 } else if (GL_IS_LABEL_IMAGE (object)) {
471 gl_view_image_new (GL_LABEL_IMAGE(object), view);
472 } else if (GL_IS_LABEL_TEXT (object)) {
473 gl_view_text_new (GL_LABEL_TEXT(object), view);
474 } else if (GL_IS_LABEL_BARCODE (object)) {
475 gl_view_barcode_new (GL_LABEL_BARCODE(object), view);
477 /* Should not happen! */
478 g_message ("Invalid label object type.");
482 g_signal_connect_swapped (G_OBJECT (view->label), "changed",
483 G_CALLBACK (label_changed_cb), view);
484 g_signal_connect_swapped (G_OBJECT (view->label), "size_changed",
485 G_CALLBACK (label_resized_cb), view);
487 gl_debug (DEBUG_VIEW, "END");
490 /*---------------------------------------------------------------------------*/
491 /* PRIAVTE. Calculate 1:1 scale for screen. */
492 /*---------------------------------------------------------------------------*/
494 get_home_scale (glView *view)
497 gdouble screen_width_pixels;
498 gdouble screen_width_mm;
499 gdouble screen_height_pixels;
500 gdouble screen_height_mm;
501 gdouble x_pixels_per_mm;
502 gdouble y_pixels_per_mm;
505 if (view->canvas == NULL) return 1.0;
507 if (!gtk_widget_has_screen (GTK_WIDGET (view->canvas))) return 1.0;
509 screen = gtk_widget_get_screen (GTK_WIDGET (view->canvas));
511 gl_debug (DEBUG_VIEW, "Screen = %p", screen);
513 screen_width_pixels = gdk_screen_get_width (screen);
514 screen_width_mm = gdk_screen_get_width_mm (screen);
515 screen_height_pixels = gdk_screen_get_height (screen);
516 screen_height_mm = gdk_screen_get_height_mm (screen);
518 x_pixels_per_mm = screen_width_pixels / screen_width_mm;
519 y_pixels_per_mm = screen_height_pixels / screen_height_mm;
521 gl_debug (DEBUG_VIEW, "Horizontal dot pitch: %g pixels/mm (%g dpi)",
522 x_pixels_per_mm, x_pixels_per_mm * 25.4);
523 gl_debug (DEBUG_VIEW, "Vertical dot pitch: %g pixels/mm (%g dpi)",
524 y_pixels_per_mm, y_pixels_per_mm * 25.4);
526 scale = (x_pixels_per_mm + y_pixels_per_mm) / 2.0;
528 gl_debug (DEBUG_VIEW, "Average dot pitch: %g pixels/mm (%g dpi)",
529 scale, scale * 25.4);
531 scale /= POINTS_PER_MM;
533 gl_debug (DEBUG_VIEW, "Scale = %g pixels/point", scale);
535 /* Make sure scale is somewhat sane. */
536 if ( (scale < 0.25) || (scale > 4.0) ) return 1.0;
541 /*---------------------------------------------------------------------------*/
542 /* PRIVATE. Update canvas. */
543 /*---------------------------------------------------------------------------*/
545 gl_view_update (glView *view)
550 gl_debug (DEBUG_VIEW, "START");
552 widget = GTK_WIDGET (view->canvas);
554 if (!widget->window) return;
556 if ( !view->update_scheduled_flag )
558 view->update_scheduled_flag = TRUE;
560 region = gdk_drawable_get_clip_region (widget->window);
561 /* redraw the cairo canvas completely by exposing it */
562 gdk_window_invalidate_region (widget->window, region, TRUE);
563 gdk_region_destroy (region);
566 gl_debug (DEBUG_VIEW, "END");
569 /*---------------------------------------------------------------------------*/
570 /* PRIVATE. Expose handler. */
571 /*---------------------------------------------------------------------------*/
573 expose_cb (glView *view,
574 GdkEventExpose *event)
578 gl_debug (DEBUG_VIEW, "START");
580 view->update_scheduled_flag = FALSE;
583 cr = gdk_cairo_create (GTK_LAYOUT (view->canvas)->bin_window);
586 event->area.x, event->area.y,
587 event->area.width, event->area.height);
590 draw_layers (view, cr);
594 gl_debug (DEBUG_VIEW, "END");
599 /*---------------------------------------------------------------------------*/
600 /* PRIVATE. Realize handler. */
601 /*---------------------------------------------------------------------------*/
603 realize_cb (glView *view)
605 g_return_if_fail (view && GL_IS_VIEW (view));
607 gl_debug (DEBUG_VIEW, "START");
609 gl_debug (DEBUG_VIEW, "END");
612 /*---------------------------------------------------------------------------*/
613 /* PRIVATE. Size allocation changed callback. */
614 /*---------------------------------------------------------------------------*/
616 size_allocate_cb (glView *view,
617 GtkAllocation *allocation)
619 gl_debug (DEBUG_VIEW, "START");
621 GTK_LAYOUT (view->canvas)->hadjustment->page_size = allocation->width;
622 GTK_LAYOUT (view->canvas)->hadjustment->page_increment = allocation->width / 2;
624 GTK_LAYOUT (view->canvas)->vadjustment->page_size = allocation->height;
625 GTK_LAYOUT (view->canvas)->vadjustment->page_increment = allocation->height / 2;
627 g_signal_emit_by_name (GTK_LAYOUT (view->canvas)->hadjustment, "changed");
628 g_signal_emit_by_name (GTK_LAYOUT (view->canvas)->vadjustment, "changed");
630 if (view->zoom_to_fit_flag) {
631 /* Maintain best fit zoom */
632 gl_view_zoom_to_fit (view);
635 gl_debug (DEBUG_VIEW, "END");
640 /*---------------------------------------------------------------------------*/
641 /* PRIVATE. Screen changed callback. */
642 /*---------------------------------------------------------------------------*/
644 screen_changed_cb (glView *view)
646 gl_debug (DEBUG_VIEW, "START");
648 if (gtk_widget_has_screen (GTK_WIDGET (view->canvas))) {
650 view->home_scale = get_home_scale (view);
652 if (view->zoom_to_fit_flag) {
653 /* Maintain best fit zoom */
654 gl_view_zoom_to_fit (view);
658 gl_debug (DEBUG_VIEW, "END");
661 /*---------------------------------------------------------------------------*/
662 /* PRIVATE. Handle label changed event. */
663 /*---------------------------------------------------------------------------*/
665 label_changed_cb (glView *view)
667 g_return_if_fail (view && GL_IS_VIEW (view));
669 gl_debug (DEBUG_VIEW, "START");
671 gl_view_update (view);
673 gl_debug (DEBUG_VIEW, "END");
677 /*---------------------------------------------------------------------------*/
678 /* PRIVATE. Handle label resize event. */
679 /*---------------------------------------------------------------------------*/
681 label_resized_cb (glView *view)
683 g_return_if_fail (view && GL_IS_VIEW (view));
685 gl_debug (DEBUG_VIEW, "START");
687 g_signal_emit_by_name (GTK_LAYOUT (view->canvas)->hadjustment, "changed");
688 g_signal_emit_by_name (GTK_LAYOUT (view->canvas)->vadjustment, "changed");
690 gl_view_update (view);
692 gl_debug (DEBUG_VIEW, "END");
696 /*---------------------------------------------------------------------------*/
697 /* PRIVATE. Create, draw and order layers. */
698 /*---------------------------------------------------------------------------*/
700 draw_layers (glView *view,
705 gint canvas_w, canvas_h;
707 g_return_if_fail (view && GL_IS_VIEW (view));
708 g_return_if_fail (view->label && GL_IS_LABEL (view->label));
710 gl_debug (DEBUG_VIEW, "START");
712 scale = view->zoom * view->home_scale;
714 gl_label_get_size (view->label, &w, &h);
716 scale = view->home_scale * view->zoom;
717 gtk_layout_set_size (GTK_LAYOUT (view->canvas), w*scale+8, h*scale+8);
719 gdk_drawable_get_size (GTK_LAYOUT (view->canvas)->bin_window, &canvas_w, &canvas_h);
721 view->x0 = (canvas_w/scale - w) / 2.0;
722 view->y0 = (canvas_h/scale - h) / 2.0;
728 cairo_scale (cr, scale, scale);
729 cairo_translate (cr, view->x0, view->y0);
731 draw_bg_layer (view, cr);
732 draw_grid_layer (view, cr);
733 draw_markup_layer (view, cr);
734 draw_objects_layer (view, cr);
735 draw_fg_layer (view, cr);
736 draw_highlight_layer (view, cr);
737 draw_select_region_layer (view, cr);
741 gl_debug (DEBUG_VIEW, "END");
745 /*---------------------------------------------------------------------------*/
746 /* PRIVATE. Draw background */
747 /*---------------------------------------------------------------------------*/
749 draw_bg_layer (glView *view,
752 g_return_if_fail (view && GL_IS_VIEW (view));
753 g_return_if_fail (view->label && GL_IS_LABEL (view->label));
755 gl_cairo_label_path (cr, view->label->template, view->label->rotate_flag, FALSE);
757 cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
758 cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
762 /*---------------------------------------------------------------------------*/
763 /* PRIVATE. Draw grid lines. */
764 /*---------------------------------------------------------------------------*/
766 draw_grid_layer (glView *view,
772 const glTemplateLabelType *label_type;
774 gl_debug (DEBUG_VIEW, "START");
776 g_return_if_fail (view && GL_IS_VIEW (view));
777 g_return_if_fail (view->label && GL_IS_LABEL(view->label));
779 if (view->grid_visible)
782 label_type = gl_template_get_first_label_type (view->label->template);
784 gl_label_get_size (view->label, &w, &h);
786 if (label_type->shape == GL_TEMPLATE_SHAPE_RECT) {
790 /* round labels, adjust grid to line up with center of label. */
791 x0 = fmod (w/2.0, view->grid_spacing);
792 y0 = fmod (h/2.0, view->grid_spacing);
798 cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
799 cairo_set_line_width (cr, 1.0/(view->home_scale * view->zoom));
800 cairo_set_source_rgb (cr, 0.753, 0.753, 0.753);
802 for ( x=x0+view->grid_spacing; x < w; x += view->grid_spacing )
804 cairo_move_to (cr, x, 0);
805 cairo_line_to (cr, x, h);
809 for ( y=y0+view->grid_spacing; y < h; y += view->grid_spacing )
811 cairo_move_to (cr, 0, y);
812 cairo_line_to (cr, w, y);
820 gl_debug (DEBUG_VIEW, "END");
823 /*---------------------------------------------------------------------------*/
824 /* PRIVATE. Draw markup layer. */
825 /*---------------------------------------------------------------------------*/
827 draw_markup_layer (glView *view,
831 const glTemplateLabelType *label_type;
833 glTemplateMarkup *markup;
835 g_return_if_fail (view && GL_IS_VIEW (view));
836 g_return_if_fail (view->label && GL_IS_LABEL (view->label));
838 if (view->markup_visible)
842 label_type = gl_template_get_first_label_type (label->template);
846 cairo_set_line_width (cr, 1.0/(view->home_scale * view->zoom));
847 cairo_set_source_rgb (cr, 0.94, 0.39, 0.39);
849 for ( p=label_type->markups; p != NULL; p=p->next )
851 markup = (glTemplateMarkup *)p->data;
853 gl_cairo_markup_path (cr, markup, label);
863 /*---------------------------------------------------------------------------*/
864 /* PRIVATE. Draw objects layer. */
865 /*---------------------------------------------------------------------------*/
867 draw_objects_layer (glView *view,
870 gl_label_draw (view->label, cr, TRUE, NULL);
873 /*---------------------------------------------------------------------------*/
874 /* PRIVATE. Draw foreground */
875 /*---------------------------------------------------------------------------*/
877 draw_fg_layer (glView *view,
880 g_return_if_fail (view && GL_IS_VIEW (view));
881 g_return_if_fail (view->label && GL_IS_LABEL (view->label));
883 gl_cairo_label_path (cr, view->label->template, view->label->rotate_flag, FALSE);
885 cairo_set_line_width (cr, 3.0/(view->home_scale * view->zoom));
886 cairo_set_source_rgb (cr, 0.68, 0.85, 0.90);
890 /*---------------------------------------------------------------------------*/
891 /* PRIVATE. Create highlight layer. */
892 /*---------------------------------------------------------------------------*/
894 draw_highlight_layer (glView *view,
898 glViewObject *view_object;
900 g_return_if_fail (view && GL_IS_VIEW (view));
904 cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
906 for (p_obj = view->selected_object_list; p_obj != NULL; p_obj = p_obj->next)
908 view_object = GL_VIEW_OBJECT (p_obj->data);
910 gl_view_object_draw_handles (view_object, cr);
916 /*---------------------------------------------------------------------------*/
917 /* PRIVATE. Draw select region layer. */
918 /*---------------------------------------------------------------------------*/
920 draw_select_region_layer (glView *view,
926 g_return_if_fail (view && GL_IS_VIEW (view));
928 if (view->select_region_visible)
930 x1 = MIN (view->select_region_x1, view->select_region_x2);
931 y1 = MIN (view->select_region_y1, view->select_region_y2);
932 w = fabs (view->select_region_x2 - view->select_region_x1);
933 h = fabs (view->select_region_y2 - view->select_region_y1);
935 cairo_rectangle (cr, x1, y1, w, h);
937 cairo_set_source_rgba (cr, 0.75, 0.75, 1.0, 0.5);
938 cairo_fill_preserve (cr);
940 cairo_set_line_width (cr, 3.0/(view->home_scale * view->zoom));
941 cairo_set_source_rgba (cr, 0, 0, 1.0, 0.5);
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);
958 /*****************************************************************************/
960 /*****************************************************************************/
962 gl_view_hide_grid (glView *view)
964 g_return_if_fail (view && GL_IS_VIEW (view));
966 view->grid_visible = FALSE;
967 gl_view_update (view);
970 /*****************************************************************************/
971 /* Set grid spacing. */
972 /*****************************************************************************/
974 gl_view_set_grid_spacing (glView *view,
977 g_return_if_fail (view && GL_IS_VIEW (view));
979 view->grid_spacing = spacing;
980 gl_view_update (view);
983 /*****************************************************************************/
985 /*****************************************************************************/
987 gl_view_show_markup (glView *view)
989 g_return_if_fail (view && GL_IS_VIEW (view));
991 view->markup_visible = TRUE;
992 gl_view_update (view);
995 /*****************************************************************************/
997 /*****************************************************************************/
999 gl_view_hide_markup (glView *view)
1001 g_return_if_fail (view && GL_IS_VIEW (view));
1003 view->markup_visible = FALSE;
1004 gl_view_update (view);
1007 /*****************************************************************************/
1008 /* Set arrow mode. */
1009 /*****************************************************************************/
1011 gl_view_arrow_mode (glView *view)
1015 gl_debug (DEBUG_VIEW, "START");
1017 g_return_if_fail (view && GL_IS_VIEW (view));
1019 cursor = gdk_cursor_new (GDK_LEFT_PTR);
1020 gdk_window_set_cursor (view->canvas->window, cursor);
1021 gdk_cursor_unref (cursor);
1023 view->mode = GL_VIEW_MODE_ARROW;
1024 view->state = GL_VIEW_IDLE;
1026 gl_debug (DEBUG_VIEW, "END");
1029 /*****************************************************************************/
1030 /* Set create text object mode. */
1031 /*****************************************************************************/
1033 gl_view_object_create_mode (glView *view,
1034 glLabelObjectType type)
1036 GdkCursor *cursor = NULL;
1038 gl_debug (DEBUG_VIEW, "START");
1040 g_return_if_fail (view && GL_IS_VIEW (view));
1044 case GL_LABEL_OBJECT_BOX:
1045 cursor = gl_view_box_get_create_cursor ();
1047 case GL_LABEL_OBJECT_ELLIPSE:
1048 cursor = gl_view_ellipse_get_create_cursor ();
1050 case GL_LABEL_OBJECT_LINE:
1051 cursor = gl_view_line_get_create_cursor ();
1053 case GL_LABEL_OBJECT_IMAGE:
1054 cursor = gl_view_image_get_create_cursor ();
1056 case GL_LABEL_OBJECT_TEXT:
1057 cursor = gl_view_text_get_create_cursor ();
1059 case GL_LABEL_OBJECT_BARCODE:
1060 cursor = gl_view_barcode_get_create_cursor ();
1063 g_message ("Invalid label object type.");/*Should not happen!*/
1067 gdk_window_set_cursor (view->canvas->window, cursor);
1068 gdk_cursor_unref (cursor);
1070 view->mode = GL_VIEW_MODE_OBJECT_CREATE;
1071 view->state = GL_VIEW_IDLE;
1072 view->create_type = type;
1074 gl_debug (DEBUG_VIEW, "END");
1077 /*****************************************************************************/
1078 /* Select given object (adding to current selection). */
1079 /*****************************************************************************/
1081 gl_view_select_object (glView *view,
1082 glViewObject *view_object)
1084 gl_debug (DEBUG_VIEW, "START");
1086 g_return_if_fail (view && GL_IS_VIEW (view));
1088 select_object_real (view, view_object);
1090 g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1092 gl_debug (DEBUG_VIEW, "END");
1095 /*****************************************************************************/
1096 /* Unselect given object (removing from current selection). */
1097 /*****************************************************************************/
1099 gl_view_unselect_object (glView *view,
1100 glViewObject *view_object)
1102 gl_debug (DEBUG_VIEW, "START");
1104 g_return_if_fail (view && GL_IS_VIEW (view));
1106 unselect_object_real (view, view_object);
1108 g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1110 gl_debug (DEBUG_VIEW, "END");
1113 /*****************************************************************************/
1114 /* Select all items. */
1115 /*****************************************************************************/
1117 gl_view_select_all (glView *view)
1121 gl_debug (DEBUG_VIEW, "START");
1123 g_return_if_fail (view && GL_IS_VIEW (view));
1125 /* 1st unselect anything already selected. */
1126 for (p = view->selected_object_list; p != NULL; p = p_next) {
1128 unselect_object_real (view, GL_VIEW_OBJECT (p->data));
1131 /* Finally select all objects. */
1132 for (p = view->object_list; p != NULL; p = p->next) {
1133 select_object_real (view, GL_VIEW_OBJECT (p->data));
1136 g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1138 gl_debug (DEBUG_VIEW, "END");
1141 /*****************************************************************************/
1142 /* Remove all selections */
1143 /*****************************************************************************/
1145 gl_view_unselect_all (glView *view)
1150 gl_debug (DEBUG_VIEW, "START");
1152 g_return_if_fail (view && GL_IS_VIEW (view));
1154 for (p = view->selected_object_list; p != NULL; p = p_next) {
1156 unselect_object_real (view, GL_VIEW_OBJECT (p->data));
1159 g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1161 gl_debug (DEBUG_VIEW, "END");
1164 /*****************************************************************************/
1165 /* Select all objects within given rectangular region (adding to selection). */
1166 /*****************************************************************************/
1168 gl_view_select_region (glView *view,
1175 glViewObject *view_object;
1176 glLabelObject *object;
1182 gl_debug (DEBUG_VIEW, "START");
1184 g_return_if_fail (view && GL_IS_VIEW (view));
1186 r_x1 = MIN (x1, x2);
1187 r_y1 = MIN (y1, y2);
1188 r_x2 = MAX (x1, x2);
1189 r_y2 = MAX (y1, y2);
1191 for (p = view->object_list; p != NULL; p = p->next) {
1192 view_object = GL_VIEW_OBJECT(p->data);
1193 if (!gl_view_is_object_selected (view, view_object)) {
1195 object = gl_view_object_get_object (view_object);
1197 gl_label_object_get_extent (object, &i_x1, &i_y1, &i_x2, &i_y2);
1198 if ((i_x1 >= r_x1) && (i_x2 <= r_x2) && (i_y1 >= r_y1)
1199 && (i_y2 <= r_y2)) {
1200 select_object_real (view, view_object);
1206 g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1208 gl_debug (DEBUG_VIEW, "END");
1211 /*---------------------------------------------------------------------------*/
1212 /* PRIVATE. Select an object. */
1213 /*---------------------------------------------------------------------------*/
1215 select_object_real (glView *view,
1216 glViewObject *view_object)
1218 gl_debug (DEBUG_VIEW, "START");
1220 g_return_if_fail (view && GL_IS_VIEW (view));
1221 g_return_if_fail (GL_IS_VIEW_OBJECT (view_object));
1223 if (!gl_view_is_object_selected (view, view_object)) {
1224 view->selected_object_list =
1225 g_list_append (view->selected_object_list, view_object);
1227 gtk_widget_grab_focus (GTK_WIDGET (view->canvas));
1229 gl_view_update (view);
1231 gl_debug (DEBUG_VIEW, "END");
1234 /*---------------------------------------------------------------------------*/
1235 /* PRIVATE. Un-select object. */
1236 /*---------------------------------------------------------------------------*/
1238 unselect_object_real (glView *view,
1239 glViewObject *view_object)
1241 gl_debug (DEBUG_VIEW, "START");
1243 g_return_if_fail (view && GL_IS_VIEW (view));
1244 g_return_if_fail (GL_IS_VIEW_OBJECT (view_object));
1246 view->selected_object_list =
1247 g_list_remove (view->selected_object_list, view_object);
1249 gl_view_update (view);
1251 gl_debug (DEBUG_VIEW, "END");
1254 /*---------------------------------------------------------------------------*/
1255 /* PRIVATE. Return object at (x,y). */
1256 /*---------------------------------------------------------------------------*/
1257 static glViewObject *
1258 view_view_object_at (glView *view,
1264 glViewObject *view_object;
1266 g_return_val_if_fail (view && GL_IS_VIEW (view), NULL);
1268 for (p_obj = g_list_last (view->object_list); p_obj != NULL; p_obj = p_obj->prev)
1271 view_object = GL_VIEW_OBJECT (p_obj->data);
1273 if (gl_view_object_at (view_object, cr, x, y))
1283 /*---------------------------------------------------------------------------*/
1284 /* PRIVATE. Return object handle at (x,y). */
1285 /*---------------------------------------------------------------------------*/
1286 static glViewObject *
1287 view_handle_at (glView *view,
1291 glViewObjectHandle *handle)
1294 glViewObject *view_object;
1296 g_return_val_if_fail (view && GL_IS_VIEW (view), NULL);
1298 for (p_obj = g_list_last (view->selected_object_list); p_obj != NULL; p_obj = p_obj->prev)
1301 view_object = GL_VIEW_OBJECT (p_obj->data);
1303 if ((*handle = gl_view_object_handle_at (view_object, cr, x, y)))
1313 /*****************************************************************************/
1314 /* Is the object in our current selection? */
1315 /*****************************************************************************/
1317 gl_view_is_object_selected (glView *view,
1318 glViewObject *view_object)
1320 gl_debug (DEBUG_VIEW, "");
1322 g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
1323 g_return_val_if_fail (GL_IS_VIEW_OBJECT (view_object), FALSE);
1325 if (g_list_find (view->selected_object_list, view_object) == NULL) {
1331 /*****************************************************************************/
1332 /* Is our current selection empty? */
1333 /*****************************************************************************/
1335 gl_view_is_selection_empty (glView *view)
1337 gl_debug (DEBUG_VIEW, "");
1339 g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
1341 if (view->selected_object_list == NULL) {
1348 /*****************************************************************************/
1349 /* Is our current selection atomic? I.e. only one item selected. */
1350 /*****************************************************************************/
1352 gl_view_is_selection_atomic (glView *view)
1354 gl_debug (DEBUG_VIEW, "");
1356 g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
1358 if (view->selected_object_list == NULL)
1360 if (view->selected_object_list->next == NULL)
1365 /*****************************************************************************/
1366 /* Delete selected objects. (Bypass clipboard) */
1367 /*****************************************************************************/
1369 gl_view_delete_selection (glView *view)
1375 gl_debug (DEBUG_VIEW, "START");
1377 g_return_if_fail (view && GL_IS_VIEW (view));
1379 object_list = view->selected_object_list;
1380 view->selected_object_list = NULL;
1381 g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1383 for (p = object_list; p != NULL; p = p_next) {
1385 g_object_unref (G_OBJECT (p->data));
1386 object_list = g_list_delete_link (object_list, p);
1389 gl_debug (DEBUG_VIEW, "END");
1392 /*****************************************************************************/
1393 /* Get object property editor of first selected object. */
1394 /*****************************************************************************/
1396 gl_view_get_editor (glView *view)
1398 glViewObject *view_object;
1399 GtkWidget *editor = NULL;
1401 gl_debug (DEBUG_VIEW, "START");
1403 g_return_val_if_fail (view && GL_IS_VIEW (view), NULL);
1405 if (!gl_view_is_selection_empty (view)) {
1407 view_object = GL_VIEW_OBJECT(view->selected_object_list->data);
1408 editor = gl_view_object_get_editor (view_object);
1412 gl_debug (DEBUG_VIEW, "END");
1417 /*****************************************************************************/
1418 /* Raise selected items to top. */
1419 /*****************************************************************************/
1421 gl_view_raise_selection (glView *view)
1424 glViewObject *view_object;
1425 glLabelObject *object;
1427 gl_debug (DEBUG_VIEW, "START");
1429 g_return_if_fail (view && GL_IS_VIEW (view));
1431 for (p = view->selected_object_list; p != NULL; p = p->next) {
1432 view_object = GL_VIEW_OBJECT (p->data);
1433 object = gl_view_object_get_object (view_object);
1434 gl_label_object_raise_to_top (object);
1437 gl_debug (DEBUG_VIEW, "END");
1440 /*****************************************************************************/
1441 /* Lower selected items to bottom. */
1442 /*****************************************************************************/
1444 gl_view_lower_selection (glView *view)
1447 glViewObject *view_object;
1448 glLabelObject *object;
1450 gl_debug (DEBUG_VIEW, "START");
1452 g_return_if_fail (view && GL_IS_VIEW (view));
1454 for (p = view->selected_object_list; p != NULL; p = p->next) {
1455 view_object = GL_VIEW_OBJECT (p->data);
1456 object = gl_view_object_get_object (view_object);
1457 gl_label_object_lower_to_bottom (object);
1460 gl_debug (DEBUG_VIEW, "END");
1463 /*****************************************************************************/
1464 /* Rotate selected objects by given angle. */
1465 /*****************************************************************************/
1467 gl_view_rotate_selection (glView *view,
1471 glViewObject *view_object;
1472 glLabelObject *object;
1474 gl_debug (DEBUG_VIEW, "START");
1476 g_return_if_fail (view && GL_IS_VIEW (view));
1478 for (p = view->selected_object_list; p != NULL; p = p->next) {
1479 view_object = GL_VIEW_OBJECT (p->data);
1480 object = gl_view_object_get_object (view_object);
1481 gl_label_object_rotate (object, theta_degs);
1484 gl_debug (DEBUG_VIEW, "END");
1487 /*****************************************************************************/
1488 /* Rotate selected objects 90 degrees left. */
1489 /*****************************************************************************/
1491 gl_view_rotate_selection_left (glView *view)
1494 glViewObject *view_object;
1495 glLabelObject *object;
1497 gl_debug (DEBUG_VIEW, "START");
1499 g_return_if_fail (view && GL_IS_VIEW (view));
1501 for (p = view->selected_object_list; p != NULL; p = p->next) {
1502 view_object = GL_VIEW_OBJECT (p->data);
1503 object = gl_view_object_get_object (view_object);
1504 gl_label_object_rotate (object, -90.0);
1507 gl_debug (DEBUG_VIEW, "END");
1510 /*****************************************************************************/
1511 /* Rotate selected objects 90 degrees right. */
1512 /*****************************************************************************/
1514 gl_view_rotate_selection_right (glView *view)
1517 glViewObject *view_object;
1518 glLabelObject *object;
1520 gl_debug (DEBUG_VIEW, "START");
1522 g_return_if_fail (view && GL_IS_VIEW (view));
1524 for (p = view->selected_object_list; p != NULL; p = p->next) {
1525 view_object = GL_VIEW_OBJECT (p->data);
1526 object = gl_view_object_get_object (view_object);
1527 gl_label_object_rotate (object, 90.0);
1530 gl_debug (DEBUG_VIEW, "END");
1533 /*****************************************************************************/
1534 /* Flip selected objects horizontally. */
1535 /*****************************************************************************/
1537 gl_view_flip_selection_horiz (glView *view)
1540 glViewObject *view_object;
1541 glLabelObject *object;
1543 gl_debug (DEBUG_VIEW, "START");
1545 g_return_if_fail (view && GL_IS_VIEW (view));
1547 for (p = view->selected_object_list; p != NULL; p = p->next) {
1548 view_object = GL_VIEW_OBJECT (p->data);
1549 object = gl_view_object_get_object (view_object);
1550 gl_label_object_flip_horiz (object);
1553 gl_debug (DEBUG_VIEW, "END");
1556 /*****************************************************************************/
1557 /* Flip selected objects vertically. */
1558 /*****************************************************************************/
1560 gl_view_flip_selection_vert (glView *view)
1563 glViewObject *view_object;
1564 glLabelObject *object;
1566 gl_debug (DEBUG_VIEW, "START");
1568 g_return_if_fail (view && GL_IS_VIEW (view));
1570 for (p = view->selected_object_list; p != NULL; p = p->next) {
1571 view_object = GL_VIEW_OBJECT (p->data);
1572 object = gl_view_object_get_object (view_object);
1573 gl_label_object_flip_vert (object);
1576 gl_debug (DEBUG_VIEW, "END");
1579 /*****************************************************************************/
1580 /* Align selected objects to left most edge. */
1581 /*****************************************************************************/
1583 gl_view_align_selection_left (glView *view)
1586 glViewObject *view_object;
1587 glLabelObject *object;
1588 gdouble dx, x1min, x1, y1, x2, y2;
1590 gl_debug (DEBUG_VIEW, "START");
1592 g_return_if_fail (view && GL_IS_VIEW (view));
1594 g_return_if_fail (!gl_view_is_selection_empty (view) &&
1595 !gl_view_is_selection_atomic (view));
1597 /* find left most edge */
1598 p = view->selected_object_list;
1599 view_object = GL_VIEW_OBJECT (p->data);
1600 object = gl_view_object_get_object (view_object);
1601 gl_label_object_get_extent (object, &x1min, &y1, &x2, &y2);
1602 for (p = p->next; p != NULL; p = p->next) {
1603 view_object = GL_VIEW_OBJECT (p->data);
1604 object = gl_view_object_get_object (view_object);
1605 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
1606 if ( x1 < x1min ) x1min = x1;
1609 /* now adjust the object positions to line up the left edges */
1610 for (p = view->selected_object_list; p != NULL; p = p->next) {
1611 view_object = GL_VIEW_OBJECT (p->data);
1612 object = gl_view_object_get_object (view_object);
1613 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
1615 gl_label_object_set_position_relative (object, dx, 0.0);
1618 gl_debug (DEBUG_VIEW, "END");
1622 /*****************************************************************************/
1623 /* Align selected objects to right most edge. */
1624 /*****************************************************************************/
1626 gl_view_align_selection_right (glView *view)
1629 glViewObject *view_object;
1630 glLabelObject *object;
1636 gl_debug (DEBUG_VIEW, "START");
1638 g_return_if_fail (view && GL_IS_VIEW (view));
1640 g_return_if_fail (!gl_view_is_selection_empty (view) &&
1641 !gl_view_is_selection_atomic (view));
1643 /* find right most edge */
1644 p = view->selected_object_list;
1645 view_object = GL_VIEW_OBJECT (p->data);
1646 object = gl_view_object_get_object (view_object);
1647 gl_label_object_get_extent (object, &x1, &y1, &x2max, &y2);
1648 for (p = p->next; p != NULL; p = p->next) {
1649 view_object = GL_VIEW_OBJECT (p->data);
1650 object = gl_view_object_get_object (view_object);
1651 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
1652 if ( x2 > x2max ) x2max = x2;
1655 /* now adjust the object positions to line up the right edges */
1656 for (p = view->selected_object_list; p != NULL; p = p->next) {
1657 view_object = GL_VIEW_OBJECT (p->data);
1658 object = gl_view_object_get_object (view_object);
1659 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
1661 gl_label_object_set_position_relative (object, dx, 0.0);
1664 gl_debug (DEBUG_VIEW, "END");
1667 /*****************************************************************************/
1668 /* Align selected objects to horizontal center of objects. */
1669 /*****************************************************************************/
1671 gl_view_align_selection_hcenter (glView *view)
1674 glViewObject *view_object;
1675 glLabelObject *object;
1684 gl_debug (DEBUG_VIEW, "START");
1686 g_return_if_fail (view && GL_IS_VIEW (view));
1688 g_return_if_fail (!gl_view_is_selection_empty (view) &&
1689 !gl_view_is_selection_atomic (view));
1691 /* find average center of objects */
1694 for (p = view->selected_object_list; p != NULL; p = p->next) {
1695 view_object = GL_VIEW_OBJECT (p->data);
1696 object = gl_view_object_get_object (view_object);
1697 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
1698 xsum += (x1 + x2) / 2.0;
1703 /* find center of object closest to average center */
1704 p = view->selected_object_list;
1705 view_object = GL_VIEW_OBJECT (p->data);
1706 object = gl_view_object_get_object (view_object);
1707 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
1708 dxmin = fabs (xavg - (x1 + x2)/2.0);
1709 xcenter = (x1 + x2)/2.0;
1710 for (p = p->next; p != NULL; p = p->next) {
1711 view_object = GL_VIEW_OBJECT (p->data);
1712 object = gl_view_object_get_object (view_object);
1713 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
1714 dx = fabs (xavg - (x1 + x2)/2.0);
1717 xcenter = (x1 + x2)/2.0;
1721 /* now adjust the object positions to line up this center */
1722 for (p = view->selected_object_list; p != NULL; p = p->next) {
1723 view_object = GL_VIEW_OBJECT (p->data);
1724 object = gl_view_object_get_object (view_object);
1725 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
1726 dx = xcenter - (x1 + x2)/2.0;
1727 gl_label_object_set_position_relative (object, dx, 0.0);
1730 gl_debug (DEBUG_VIEW, "END");
1733 /*****************************************************************************/
1734 /* Align selected objects to top most edge. */
1735 /*****************************************************************************/
1737 gl_view_align_selection_top (glView *view)
1740 glViewObject *view_object;
1741 glLabelObject *object;
1747 gl_debug (DEBUG_VIEW, "START");
1749 g_return_if_fail (view && GL_IS_VIEW (view));
1751 g_return_if_fail (!gl_view_is_selection_empty (view) &&
1752 !gl_view_is_selection_atomic (view));
1754 /* find top most edge */
1755 p = view->selected_object_list;
1756 view_object = GL_VIEW_OBJECT (p->data);
1757 object = gl_view_object_get_object (view_object);
1758 gl_label_object_get_extent (object, &x1, &y1min, &x2, &y2);
1759 for (p = p->next; p != NULL; p = p->next) {
1760 view_object = GL_VIEW_OBJECT (p->data);
1761 object = gl_view_object_get_object (view_object);
1762 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
1763 if ( y1 < y1min ) y1min = y1;
1766 /* now adjust the object positions to line up the top edges */
1767 for (p = view->selected_object_list; p != NULL; p = p->next) {
1768 view_object = GL_VIEW_OBJECT (p->data);
1769 object = gl_view_object_get_object (view_object);
1770 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
1772 gl_label_object_set_position_relative (object, 0.0, dy);
1775 gl_debug (DEBUG_VIEW, "END");
1778 /*****************************************************************************/
1779 /* Align selected objects to bottom most edge. */
1780 /*****************************************************************************/
1782 gl_view_align_selection_bottom (glView *view)
1785 glViewObject *view_object;
1786 glLabelObject *object;
1792 gl_debug (DEBUG_VIEW, "START");
1794 g_return_if_fail (view && GL_IS_VIEW (view));
1796 g_return_if_fail (!gl_view_is_selection_empty (view) &&
1797 !gl_view_is_selection_atomic (view));
1799 /* find bottom most edge */
1800 p = view->selected_object_list;
1801 view_object = GL_VIEW_OBJECT (p->data);
1802 object = gl_view_object_get_object (view_object);
1803 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2max);
1804 for (p = p->next; p != NULL; p = p->next) {
1805 view_object = GL_VIEW_OBJECT (p->data);
1806 object = gl_view_object_get_object (view_object);
1807 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
1808 if ( y2 > y2max ) y2max = y2;
1811 /* now adjust the object positions to line up the bottom edges */
1812 for (p = view->selected_object_list; p != NULL; p = p->next) {
1813 view_object = GL_VIEW_OBJECT (p->data);
1814 object = gl_view_object_get_object (view_object);
1815 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
1817 gl_label_object_set_position_relative (object, 0.0, dy);
1820 gl_debug (DEBUG_VIEW, "END");
1823 /*****************************************************************************/
1824 /* Align selected objects to viertical center of objects. */
1825 /*****************************************************************************/
1827 gl_view_align_selection_vcenter (glView *view)
1830 glViewObject *view_object;
1831 glLabelObject *object;
1840 gl_debug (DEBUG_VIEW, "START");
1842 g_return_if_fail (view && GL_IS_VIEW (view));
1844 g_return_if_fail (!gl_view_is_selection_empty (view) &&
1845 !gl_view_is_selection_atomic (view));
1847 /* find average center of objects */
1850 for (p = view->selected_object_list; p != NULL; p = p->next) {
1851 view_object = GL_VIEW_OBJECT (p->data);
1852 object = gl_view_object_get_object (view_object);
1853 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
1854 ysum += (y1 + y2) / 2.0;
1859 /* find center of object closest to average center */
1860 p = view->selected_object_list;
1861 view_object = GL_VIEW_OBJECT (p->data);
1862 object = gl_view_object_get_object (view_object);
1863 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
1864 dymin = fabs (yavg - (y1 + y2)/2.0);
1865 ycenter = (y1 + y2)/2.0;
1866 for (p = p->next; p != NULL; p = p->next) {
1867 view_object = GL_VIEW_OBJECT (p->data);
1868 object = gl_view_object_get_object (view_object);
1869 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
1870 dy = fabs (yavg - (y1 + y2)/2.0);
1873 ycenter = (y1 + y2)/2.0;
1877 /* now adjust the object positions to line up this center */
1878 for (p = view->selected_object_list; p != NULL; p = p->next) {
1879 view_object = GL_VIEW_OBJECT (p->data);
1880 object = gl_view_object_get_object (view_object);
1881 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
1882 dy = ycenter - (y1 + y2)/2.0;
1883 gl_label_object_set_position_relative (object, 0.0, dy);
1886 gl_debug (DEBUG_VIEW, "END");
1889 /*****************************************************************************/
1890 /* Center selected objects to in center of label. */
1891 /*****************************************************************************/
1893 gl_view_center_selection_horiz (glView *view)
1896 glViewObject *view_object;
1897 glLabelObject *object;
1899 gdouble x_label_center;
1900 gdouble x_obj_center;
1905 gl_debug (DEBUG_VIEW, "START");
1907 g_return_if_fail (view && GL_IS_VIEW (view));
1909 g_return_if_fail (!gl_view_is_selection_empty (view));
1911 gl_label_get_size (view->label, &w, &h);
1912 x_label_center = w / 2.0;
1914 /* adjust the object positions */
1915 for (p = view->selected_object_list; p != NULL; p = p->next) {
1916 view_object = GL_VIEW_OBJECT (p->data);
1917 object = gl_view_object_get_object (view_object);
1918 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
1919 x_obj_center = (x1 + x2) / 2.0;
1920 dx = x_label_center - x_obj_center;
1921 gl_label_object_set_position_relative (object, dx, 0.0);
1924 gl_debug (DEBUG_VIEW, "END");
1928 /*****************************************************************************/
1929 /* Center selected objects to in center of label. */
1930 /*****************************************************************************/
1932 gl_view_center_selection_vert (glView *view)
1935 glViewObject *view_object;
1936 glLabelObject *object;
1938 gdouble y_label_center;
1939 gdouble y_obj_center;
1944 gl_debug (DEBUG_VIEW, "START");
1946 g_return_if_fail (view && GL_IS_VIEW (view));
1948 g_return_if_fail (!gl_view_is_selection_empty (view));
1950 gl_label_get_size (view->label, &w, &h);
1951 y_label_center = h / 2.0;
1953 /* adjust the object positions */
1954 for (p = view->selected_object_list; p != NULL; p = p->next) {
1955 view_object = GL_VIEW_OBJECT (p->data);
1956 object = gl_view_object_get_object (view_object);
1957 gl_label_object_get_extent (object, &x1, &y1, &x2, &y2);
1958 y_obj_center = (y1 + y2) / 2.0;
1959 dy = y_label_center - y_obj_center;
1960 gl_label_object_set_position_relative (object, 0.0, dy);
1963 gl_debug (DEBUG_VIEW, "END");
1967 /*****************************************************************************/
1968 /* Move selected objects */
1969 /*****************************************************************************/
1971 gl_view_move_selection (glView *view,
1976 glLabelObject *object;
1978 gl_debug (DEBUG_VIEW, "START");
1980 g_return_if_fail (view && GL_IS_VIEW (view));
1982 for (p = view->selected_object_list; p != NULL; p = p->next) {
1984 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
1985 gl_label_object_set_position_relative (object, dx, dy);
1989 gl_debug (DEBUG_VIEW, "END");
1992 /*****************************************************************************/
1993 /* Can text properties be set for selection? */
1994 /*****************************************************************************/
1996 gl_view_can_selection_text (glView *view)
1999 glLabelObject *object;
2001 gl_debug (DEBUG_VIEW, "");
2003 g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
2005 for (p = view->selected_object_list; p != NULL; p = p->next) {
2007 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2008 if (gl_label_object_can_text (object)) {
2017 /*****************************************************************************/
2018 /* Set font family for all text contained in selected objects. */
2019 /*****************************************************************************/
2021 gl_view_set_selection_font_family (glView *view,
2022 const gchar *font_family)
2025 glLabelObject *object;
2027 gl_debug (DEBUG_VIEW, "START");
2029 g_return_if_fail (view && GL_IS_VIEW (view));
2031 for (p = view->selected_object_list; p != NULL; p = p->next) {
2033 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2034 gl_label_object_set_font_family (object, font_family);
2038 gl_debug (DEBUG_VIEW, "END");
2041 /*****************************************************************************/
2042 /* Set font size for all text contained in selected objects. */
2043 /*****************************************************************************/
2045 gl_view_set_selection_font_size (glView *view,
2049 glLabelObject *object;
2051 gl_debug (DEBUG_VIEW, "START");
2053 g_return_if_fail (view && GL_IS_VIEW (view));
2055 for (p = view->selected_object_list; p != NULL; p = p->next) {
2057 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2058 gl_label_object_set_font_size (object, font_size);
2062 gl_debug (DEBUG_VIEW, "END");
2065 /*****************************************************************************/
2066 /* Set font weight for all text contained in selected objects. */
2067 /*****************************************************************************/
2069 gl_view_set_selection_font_weight (glView *view,
2070 PangoWeight font_weight)
2073 glLabelObject *object;
2075 gl_debug (DEBUG_VIEW, "START");
2077 g_return_if_fail (view && GL_IS_VIEW (view));
2079 for (p = view->selected_object_list; p != NULL; p = p->next) {
2081 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2082 gl_label_object_set_font_weight (object, font_weight);
2086 gl_debug (DEBUG_VIEW, "END");
2089 /*****************************************************************************/
2090 /* Set font italic flag for all text contained in selected objects. */
2091 /*****************************************************************************/
2093 gl_view_set_selection_font_italic_flag (glView *view,
2094 gboolean font_italic_flag)
2097 glLabelObject *object;
2099 gl_debug (DEBUG_VIEW, "START");
2101 g_return_if_fail (view && GL_IS_VIEW (view));
2103 for (p = view->selected_object_list; p != NULL; p = p->next) {
2105 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2106 gl_label_object_set_font_italic_flag (object, font_italic_flag);
2110 gl_debug (DEBUG_VIEW, "END");
2113 /*****************************************************************************/
2114 /* Set text alignment for all text contained in selected objects. */
2115 /*****************************************************************************/
2117 gl_view_set_selection_text_alignment (glView *view,
2118 PangoAlignment text_alignment)
2121 glLabelObject *object;
2123 gl_debug (DEBUG_VIEW, "START");
2125 g_return_if_fail (view && GL_IS_VIEW (view));
2127 for (p = view->selected_object_list; p != NULL; p = p->next) {
2129 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2130 gl_label_object_set_text_alignment (object, text_alignment);
2134 gl_debug (DEBUG_VIEW, "END");
2137 /*****************************************************************************/
2138 /* Set text line spacing for all text contained in selected objects. */
2139 /*****************************************************************************/
2141 gl_view_set_selection_text_line_spacing (glView *view,
2142 gdouble text_line_spacing)
2145 glLabelObject *object;
2147 gl_debug (DEBUG_VIEW, "START");
2149 g_return_if_fail (view && GL_IS_VIEW (view));
2151 for (p = view->selected_object_list; p != NULL; p = p->next) {
2153 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2154 gl_label_object_set_text_line_spacing (object, text_line_spacing);
2158 gl_debug (DEBUG_VIEW, "END");
2160 /*****************************************************************************/
2161 /* Set text color for all text contained in selected objects. */
2162 /*****************************************************************************/
2164 gl_view_set_selection_text_color (glView *view,
2165 glColorNode *text_color_node)
2168 glLabelObject *object;
2170 gl_debug (DEBUG_VIEW, "START");
2172 g_return_if_fail (view && GL_IS_VIEW (view));
2174 for (p = view->selected_object_list; p != NULL; p = p->next) {
2176 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2177 gl_label_object_set_text_color (object, text_color_node);
2181 gl_debug (DEBUG_VIEW, "END");
2184 /*****************************************************************************/
2185 /* Can fill properties be set for selection? */
2186 /*****************************************************************************/
2188 gl_view_can_selection_fill (glView *view)
2191 glLabelObject *object;
2193 gl_debug (DEBUG_VIEW, "");
2195 g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
2197 for (p = view->selected_object_list; p != NULL; p = p->next) {
2199 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2200 if (gl_label_object_can_fill (object)) {
2209 /*****************************************************************************/
2210 /* Set fill color for all selected objects. */
2211 /*****************************************************************************/
2213 gl_view_set_selection_fill_color (glView *view,
2214 glColorNode *fill_color_node)
2217 glLabelObject *object;
2219 gl_debug (DEBUG_VIEW, "START");
2221 g_return_if_fail (view && GL_IS_VIEW (view));
2223 for (p = view->selected_object_list; p != NULL; p = p->next) {
2225 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2226 gl_label_object_set_fill_color (object, fill_color_node);
2230 gl_debug (DEBUG_VIEW, "END");
2233 /*****************************************************************************/
2234 /* Can line color properties be set for selection? */
2235 /*****************************************************************************/
2237 gl_view_can_selection_line_color (glView *view)
2240 glLabelObject *object;
2242 gl_debug (DEBUG_VIEW, "");
2244 g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
2246 for (p = view->selected_object_list; p != NULL; p = p->next) {
2248 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2249 if (gl_label_object_can_line_color (object)) {
2258 /*****************************************************************************/
2259 /* Set line color for all selected objects. */
2260 /*****************************************************************************/
2262 gl_view_set_selection_line_color (glView *view,
2263 glColorNode *line_color_node)
2266 glLabelObject *object;
2268 gl_debug (DEBUG_VIEW, "START");
2270 g_return_if_fail (view && GL_IS_VIEW (view));
2272 for (p = view->selected_object_list; p != NULL; p = p->next) {
2274 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2275 gl_label_object_set_line_color (object, line_color_node);
2279 gl_debug (DEBUG_VIEW, "END");
2282 /*****************************************************************************/
2283 /* Can line width properties be set for selection? */
2284 /*****************************************************************************/
2286 gl_view_can_selection_line_width (glView *view)
2289 glLabelObject *object;
2291 gl_debug (DEBUG_VIEW, "");
2293 g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
2295 for (p = view->selected_object_list; p != NULL; p = p->next) {
2297 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2298 if (gl_label_object_can_line_width (object)) {
2307 /*****************************************************************************/
2308 /* Set line width for all selected objects. */
2309 /*****************************************************************************/
2311 gl_view_set_selection_line_width (glView *view,
2315 glLabelObject *object;
2317 gl_debug (DEBUG_VIEW, "START");
2319 g_return_if_fail (view && GL_IS_VIEW (view));
2321 for (p = view->selected_object_list; p != NULL; p = p->next) {
2323 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
2324 gl_label_object_set_line_width (object, line_width);
2328 gl_debug (DEBUG_VIEW, "END");
2331 /*****************************************************************************/
2332 /* "Cut" selected items and place in clipboard selections. */
2333 /*****************************************************************************/
2335 gl_view_cut (glView *view)
2337 gl_debug (DEBUG_VIEW, "START");
2339 g_return_if_fail (view && GL_IS_VIEW (view));
2341 gl_view_copy (view);
2342 gl_view_delete_selection (view);
2344 gl_debug (DEBUG_VIEW, "END");
2347 /*****************************************************************************/
2348 /* "Copy" selected items to clipboard selections. */
2349 /*****************************************************************************/
2351 gl_view_copy (glView *view)
2354 glViewObject *view_object;
2355 glLabelObject *object;
2357 gl_debug (DEBUG_VIEW, "START");
2359 g_return_if_fail (view && GL_IS_VIEW (view));
2361 if (view->selected_object_list) {
2363 if ( view->selection_data ) {
2364 g_object_unref (view->selection_data);
2366 view->selection_data = GL_LABEL(gl_label_new ());
2367 gl_label_set_template (view->selection_data, view->label->template);
2368 gl_label_set_rotate_flag (view->selection_data, view->label->rotate_flag);
2370 for (p = view->selected_object_list; p != NULL; p = p->next) {
2372 view_object = GL_VIEW_OBJECT (p->data);
2373 object = gl_view_object_get_object (view_object);
2375 gl_label_object_dup (object, view->selection_data);
2379 gtk_selection_owner_set (view->invisible,
2380 clipboard_atom, GDK_CURRENT_TIME);
2381 view->have_selection = TRUE;
2385 gl_debug (DEBUG_VIEW, "END");
2388 /*****************************************************************************/
2389 /* "Paste" from private clipboard selection. */
2390 /*****************************************************************************/
2392 gl_view_paste (glView *view)
2394 gl_debug (DEBUG_VIEW, "START");
2396 g_return_if_fail (view && GL_IS_VIEW (view));
2398 gtk_selection_convert (GTK_WIDGET (view->invisible),
2399 clipboard_atom, GDK_SELECTION_TYPE_STRING,
2402 gl_debug (DEBUG_VIEW, "END");
2405 /*****************************************************************************/
2406 /* Zoom in one "notch" */
2407 /*****************************************************************************/
2409 gl_view_zoom_in (glView *view)
2412 gdouble dist, dist_min;
2414 gl_debug (DEBUG_VIEW, "START");
2416 g_return_if_fail (view && GL_IS_VIEW (view));
2418 /* Find index of current scale (or best match) */
2419 i_min = 1; /* start with 2nd largest scale */
2420 dist_min = fabs (zooms[1] - view->zoom);
2421 for (i = 2; i < N_ZOOMS; i++) {
2422 dist = fabs (zooms[i] - view->zoom);
2423 if (dist < dist_min) {
2429 /* zoom in one "notch" */
2430 i = MAX (0, i_min - 1);
2431 gl_debug (DEBUG_VIEW, "zoom[%d] = %g", i, zooms[i]);
2432 set_zoom_real (view, zooms[i], FALSE);
2434 gl_debug (DEBUG_VIEW, "END");
2437 /*****************************************************************************/
2438 /* Zoom out one "notch" */
2439 /*****************************************************************************/
2441 gl_view_zoom_out (glView *view)
2444 gdouble dist, dist_min;
2446 gl_debug (DEBUG_VIEW, "START");
2448 g_return_if_fail (view && GL_IS_VIEW (view));
2450 /* Find index of current scale (or best match) */
2451 i_min = 0; /* start with largest scale */
2452 dist_min = fabs (zooms[0] - view->zoom);
2453 for (i = 1; i < N_ZOOMS; i++) {
2454 dist = fabs (zooms[i] - view->zoom);
2455 if (dist < dist_min) {
2461 /* zoom out one "notch" */
2462 if (i_min >= N_ZOOMS)
2467 set_zoom_real (view, zooms[i], FALSE);
2469 gl_debug (DEBUG_VIEW, "END");
2472 /*****************************************************************************/
2473 /* Set zoom to best fit. */
2474 /*****************************************************************************/
2476 gl_view_zoom_to_fit (glView *view)
2478 gint w_view, h_view;
2479 gdouble w_label, h_label;
2480 gdouble x_scale, y_scale, scale;
2482 gl_debug (DEBUG_VIEW, "");
2484 if ( ! GTK_WIDGET_VISIBLE(view)) {
2485 set_zoom_real (view, 1.0, TRUE);
2489 w_view = GTK_WIDGET(view)->allocation.width;
2490 h_view = GTK_WIDGET(view)->allocation.height;
2492 gl_label_get_size (GL_LABEL(view->label), &w_label, &h_label);
2494 gl_debug (DEBUG_VIEW, "View size: %d, %d", w_view, h_view);
2495 gl_debug (DEBUG_VIEW, "Label size: %g, %g", w_label, h_label);
2497 /* Calculate best scale */
2498 x_scale = (double)(w_view - ZOOMTOFIT_PAD) / w_label;
2499 y_scale = (double)(h_view - ZOOMTOFIT_PAD) / h_label;
2500 scale = MIN (x_scale, y_scale);
2501 gl_debug (DEBUG_VIEW, "Candidate zooms: %g, %g => %g", x_scale, y_scale, scale);
2504 gl_debug (DEBUG_VIEW, "Scale: %g", scale);
2505 scale = MIN (scale, zooms[0]*view->home_scale);
2506 scale = MAX (scale, zooms[N_ZOOMS-1]*view->home_scale);
2507 gl_debug (DEBUG_VIEW, "Limitted scale: %g", scale);
2509 set_zoom_real (view, scale/view->home_scale, TRUE);
2512 /*****************************************************************************/
2513 /* Set current zoom factor to explicit value. */
2514 /*****************************************************************************/
2516 gl_view_set_zoom (glView *view,
2519 gl_debug (DEBUG_VIEW, "START");
2521 set_zoom_real (view, zoom, FALSE);
2523 gl_debug (DEBUG_VIEW, "END");
2526 /*---------------------------------------------------------------------------*/
2527 /* PRIVATE. Set canvas scale. */
2528 /*---------------------------------------------------------------------------*/
2530 set_zoom_real (glView *view,
2532 gboolean zoom_to_fit_flag)
2534 gl_debug (DEBUG_VIEW, "START");
2536 g_return_if_fail (view && GL_IS_VIEW (view));
2537 g_return_if_fail (zoom > 0.0);
2539 /* Limit, if needed */
2540 gl_debug (DEBUG_VIEW, "Zoom requested: %g", zoom);
2541 zoom = MIN (zoom, zooms[0]);
2542 zoom = MAX (zoom, zooms[N_ZOOMS-1]);
2543 gl_debug (DEBUG_VIEW, "Limitted zoom: %g", zoom);
2545 if ( zoom != view->zoom ) {
2548 view->zoom_to_fit_flag = zoom_to_fit_flag;
2550 gl_view_update (view);
2552 g_signal_emit (G_OBJECT(view), signals[ZOOM_CHANGED], 0, zoom);
2556 gl_debug (DEBUG_VIEW, "END");
2561 /*****************************************************************************/
2562 /* Get current zoom factor. */
2563 /*****************************************************************************/
2565 gl_view_get_zoom (glView *view)
2567 gl_debug (DEBUG_VIEW, "");
2569 g_return_val_if_fail (view && GL_IS_VIEW (view), 1.0);
2574 /*****************************************************************************/
2575 /* Is this the maximum zoom level. */
2576 /*****************************************************************************/
2578 gl_view_is_zoom_max (glView *view)
2580 gl_debug (DEBUG_VIEW, "");
2582 g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
2584 return view->zoom >= zooms[0];
2587 /*****************************************************************************/
2588 /* Is this the minimum zoom level. */
2589 /*****************************************************************************/
2591 gl_view_is_zoom_min (glView *view)
2593 gl_debug (DEBUG_VIEW, "");
2595 g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
2597 return view->zoom <= zooms[N_ZOOMS-1];
2600 /*---------------------------------------------------------------------------*/
2601 /* PRIVATE. Handle "selection-clear" signal. */
2602 /*---------------------------------------------------------------------------*/
2604 selection_clear_cb (GtkWidget *widget,
2605 GdkEventSelection *event,
2608 gl_debug (DEBUG_VIEW, "START");
2610 g_return_if_fail (view && GL_IS_VIEW (view));
2612 view->have_selection = FALSE;
2613 g_object_unref (view->selection_data);
2614 view->selection_data = NULL;
2616 gl_debug (DEBUG_VIEW, "END");
2619 /*---------------------------------------------------------------------------*/
2620 /* PRIVATE. Handle "selection-get" signal. */
2621 /*---------------------------------------------------------------------------*/
2623 selection_get_cb (GtkWidget *widget,
2624 GtkSelectionData *selection_data,
2630 glXMLLabelStatus status;
2632 gl_debug (DEBUG_VIEW, "START");
2634 g_return_if_fail (view && GL_IS_VIEW (view));
2636 if (view->have_selection) {
2638 buffer = gl_xml_label_save_buffer (view->selection_data,
2640 gtk_selection_data_set (selection_data,
2641 GDK_SELECTION_TYPE_STRING, 8,
2642 (guchar *)buffer, strlen (buffer));
2646 gl_debug (DEBUG_VIEW, "END");
2649 /*---------------------------------------------------------------------------*/
2650 /* PRIVATE. Handle "selection-received" signal. (Result of Paste) */
2651 /*---------------------------------------------------------------------------*/
2653 selection_received_cb (GtkWidget *widget,
2654 GtkSelectionData *selection_data,
2658 glLabel *label = NULL;
2659 glXMLLabelStatus status;
2661 glLabelObject *object, *newobject;
2662 glViewObject *view_object;
2664 gl_debug (DEBUG_VIEW, "START");
2666 g_return_if_fail (view && GL_IS_VIEW (view));
2668 if (selection_data->length < 0) {
2671 if (selection_data->type != GDK_SELECTION_TYPE_STRING) {
2675 gl_view_unselect_all (view);
2677 label = gl_xml_label_open_buffer ((gchar *)selection_data->data, &status);
2678 for (p = label->objects; p != NULL; p = p_next) {
2681 object = (glLabelObject *) p->data;
2682 newobject = gl_label_object_dup (object, view->label);
2684 gl_debug (DEBUG_VIEW, "object pasted");
2686 if (GL_IS_LABEL_BOX (newobject)) {
2687 view_object = gl_view_box_new (GL_LABEL_BOX(newobject),
2689 } else if (GL_IS_LABEL_ELLIPSE (newobject)) {
2690 view_object = gl_view_ellipse_new (GL_LABEL_ELLIPSE(newobject),
2692 } else if (GL_IS_LABEL_LINE (newobject)) {
2693 view_object = gl_view_line_new (GL_LABEL_LINE(newobject),
2695 } else if (GL_IS_LABEL_IMAGE (newobject)) {
2696 view_object = gl_view_image_new (GL_LABEL_IMAGE(newobject),
2698 } else if (GL_IS_LABEL_TEXT (newobject)) {
2699 view_object = gl_view_text_new (GL_LABEL_TEXT(newobject),
2701 } else if (GL_IS_LABEL_BARCODE (newobject)) {
2702 view_object = gl_view_barcode_new (GL_LABEL_BARCODE(newobject),
2705 /* Should not happen! */
2707 g_message ("Invalid label object type.");
2709 gl_view_select_object (view, view_object);
2711 g_object_unref (label);
2713 gl_debug (DEBUG_VIEW, "END");
2716 /****************************************************************************/
2717 /* Set default font family. */
2718 /****************************************************************************/
2720 gl_view_set_default_font_family (glView *view,
2721 const gchar *font_family)
2723 gl_debug (DEBUG_VIEW, "START");
2725 g_return_if_fail (view && GL_IS_VIEW (view));
2727 if (view->default_font_family) {
2728 g_free (view->default_font_family);
2730 view->default_font_family = g_strdup (font_family);
2732 gl_debug (DEBUG_VIEW, "END");
2736 /****************************************************************************/
2737 /* Set default font size. */
2738 /****************************************************************************/
2740 gl_view_set_default_font_size (glView *view,
2743 gl_debug (DEBUG_VIEW, "START");
2745 g_return_if_fail (view && GL_IS_VIEW (view));
2747 view->default_font_size = font_size;
2749 gl_debug (DEBUG_VIEW, "END");
2753 /****************************************************************************/
2754 /* Set default font weight. */
2755 /****************************************************************************/
2757 gl_view_set_default_font_weight (glView *view,
2758 PangoWeight font_weight)
2760 gl_debug (DEBUG_VIEW, "START");
2762 g_return_if_fail (view && GL_IS_VIEW (view));
2764 view->default_font_weight = font_weight;
2766 gl_debug (DEBUG_VIEW, "END");
2770 /****************************************************************************/
2771 /* Set default font italic flag. */
2772 /****************************************************************************/
2774 gl_view_set_default_font_italic_flag (glView *view,
2775 gboolean font_italic_flag)
2777 gl_debug (DEBUG_VIEW, "START");
2779 g_return_if_fail (view && GL_IS_VIEW (view));
2781 view->default_font_italic_flag = font_italic_flag;
2783 gl_debug (DEBUG_VIEW, "END");
2787 /****************************************************************************/
2788 /* Set default text color. */
2789 /****************************************************************************/
2791 gl_view_set_default_text_color (glView *view,
2794 gl_debug (DEBUG_VIEW, "START");
2796 g_return_if_fail (view && GL_IS_VIEW (view));
2798 view->default_text_color = text_color;
2800 gl_debug (DEBUG_VIEW, "END");
2804 /****************************************************************************/
2805 /* Set default text alignment. */
2806 /****************************************************************************/
2808 gl_view_set_default_text_alignment (glView *view,
2809 PangoAlignment text_alignment)
2811 gl_debug (DEBUG_VIEW, "START");
2813 g_return_if_fail (view && GL_IS_VIEW (view));
2815 view->default_text_alignment = text_alignment;
2816 gl_debug (DEBUG_VIEW, "END");
2819 /****************************************************************************/
2820 /* Set default text line spacing. */
2821 /****************************************************************************/
2823 gl_view_set_default_text_line_spacing (glView *view,
2824 gdouble text_line_spacing)
2826 gl_debug (DEBUG_VIEW, "START");
2828 g_return_if_fail (view && GL_IS_VIEW (view));
2830 view->default_text_line_spacing = text_line_spacing;
2832 gl_debug (DEBUG_VIEW, "END");
2836 /****************************************************************************/
2837 /* Set default line width. */
2838 /****************************************************************************/
2840 gl_view_set_default_line_width (glView *view,
2843 gl_debug (DEBUG_VIEW, "START");
2845 g_return_if_fail (view && GL_IS_VIEW (view));
2847 view->default_line_width = line_width;
2849 gl_debug (DEBUG_VIEW, "END");
2853 /****************************************************************************/
2854 /* Set default line color. */
2855 /****************************************************************************/
2857 gl_view_set_default_line_color (glView *view,
2860 gl_debug (DEBUG_VIEW, "START");
2862 g_return_if_fail (view && GL_IS_VIEW (view));
2864 view->default_line_color = line_color;
2866 gl_debug (DEBUG_VIEW, "END");
2870 /****************************************************************************/
2871 /* Set default fill color. */
2872 /****************************************************************************/
2874 gl_view_set_default_fill_color (glView *view,
2877 gl_debug (DEBUG_VIEW, "START");
2879 g_return_if_fail (view && GL_IS_VIEW (view));
2881 view->default_fill_color = fill_color;
2883 gl_debug (DEBUG_VIEW, "END");
2888 /****************************************************************************/
2889 /* Get default font family. */
2890 /****************************************************************************/
2892 gl_view_get_default_font_family (glView *view)
2894 gl_debug (DEBUG_VIEW, "START");
2896 g_return_val_if_fail (view && GL_IS_VIEW (view), NULL);
2898 gl_debug (DEBUG_VIEW, "END");
2900 return g_strdup (view->default_font_family);
2904 /****************************************************************************/
2905 /* Get default font size. */
2906 /****************************************************************************/
2908 gl_view_get_default_font_size (glView *view)
2910 gl_debug (DEBUG_VIEW, "START");
2912 g_return_val_if_fail (view && GL_IS_VIEW (view), 12.0);
2914 gl_debug (DEBUG_VIEW, "END");
2916 return view->default_font_size;
2920 /****************************************************************************/
2921 /* Get default font weight. */
2922 /****************************************************************************/
2924 gl_view_get_default_font_weight (glView *view)
2926 gl_debug (DEBUG_VIEW, "START");
2928 g_return_val_if_fail (view && GL_IS_VIEW (view), PANGO_WEIGHT_NORMAL);
2930 gl_debug (DEBUG_VIEW, "END");
2932 return view->default_font_weight;
2936 /****************************************************************************/
2937 /* Get default font italic flag. */
2938 /****************************************************************************/
2940 gl_view_get_default_font_italic_flag (glView *view)
2942 gl_debug (DEBUG_VIEW, "START");
2944 g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
2946 gl_debug (DEBUG_VIEW, "END");
2948 return view->default_font_italic_flag;
2952 /****************************************************************************/
2953 /* Get default text color. */
2954 /****************************************************************************/
2956 gl_view_get_default_text_color (glView *view)
2958 gl_debug (DEBUG_VIEW, "START");
2960 g_return_val_if_fail (view && GL_IS_VIEW (view), 0);
2962 gl_debug (DEBUG_VIEW, "END");
2964 return view->default_text_color;
2968 /****************************************************************************/
2969 /* Get default text alignment. */
2970 /****************************************************************************/
2972 gl_view_get_default_text_alignment (glView *view)
2974 gl_debug (DEBUG_VIEW, "START");
2976 g_return_val_if_fail (view && GL_IS_VIEW (view), PANGO_ALIGN_LEFT);
2978 gl_debug (DEBUG_VIEW, "END");
2980 return view->default_text_alignment;
2983 /****************************************************************************/
2984 /* Get default text line spacing. */
2985 /****************************************************************************/
2987 gl_view_get_default_text_line_spacing (glView *view)
2989 gl_debug (DEBUG_VIEW, "START");
2991 g_return_val_if_fail (view && GL_IS_VIEW (view), 1.0);
2993 gl_debug (DEBUG_VIEW, "END");
2995 return view->default_text_line_spacing;
3000 /****************************************************************************/
3001 /* Get default line width. */
3002 /****************************************************************************/
3004 gl_view_get_default_line_width (glView *view)
3006 gl_debug (DEBUG_VIEW, "START");
3008 g_return_val_if_fail (view && GL_IS_VIEW (view), 1.0);
3010 gl_debug (DEBUG_VIEW, "END");
3012 return view->default_line_width;
3016 /****************************************************************************/
3017 /* Get default line color. */
3018 /****************************************************************************/
3020 gl_view_get_default_line_color (glView *view)
3022 gl_debug (DEBUG_VIEW, "START");
3024 g_return_val_if_fail (view && GL_IS_VIEW (view), 0);
3026 gl_debug (DEBUG_VIEW, "END");
3028 return view->default_line_color;
3032 /****************************************************************************/
3033 /* Get default fill color. */
3034 /****************************************************************************/
3036 gl_view_get_default_fill_color (glView *view)
3038 gl_debug (DEBUG_VIEW, "START");
3040 g_return_val_if_fail (view && GL_IS_VIEW (view), 0);
3042 gl_debug (DEBUG_VIEW, "END");
3044 return view->default_fill_color;
3047 /*---------------------------------------------------------------------------*/
3048 /* PRIVATE. Focus in event handler. */
3049 /*---------------------------------------------------------------------------*/
3051 focus_in_event_cb (glView *view,
3052 GdkEventFocus *event)
3054 GTK_WIDGET_SET_FLAGS (GTK_WIDGET (view->canvas), GTK_HAS_FOCUS);
3059 /*---------------------------------------------------------------------------*/
3060 /* PRIVATE. Focus out event handler. */
3061 /*---------------------------------------------------------------------------*/
3063 focus_out_event_cb (glView *view,
3064 GdkEventFocus *event)
3066 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (view->canvas), GTK_HAS_FOCUS);
3071 /*---------------------------------------------------------------------------*/
3072 /* PRIVATE. Enter notify event handler. */
3073 /*---------------------------------------------------------------------------*/
3075 enter_notify_event_cb (glView *view,
3076 GdkEventCrossing *event)
3078 gtk_widget_grab_focus(GTK_WIDGET (view->canvas));
3083 /*---------------------------------------------------------------------------*/
3084 /* PRIVATE. Leave notify event handler. */
3085 /*---------------------------------------------------------------------------*/
3087 leave_notify_event_cb (glView *view,
3088 GdkEventCrossing *event)
3091 g_signal_emit (G_OBJECT(view), signals[POINTER_EXIT], 0);
3096 /*---------------------------------------------------------------------------*/
3097 /* PRIVATE. Motion notify event handler. */
3098 /*---------------------------------------------------------------------------*/
3100 motion_notify_event_cb (glView *view,
3101 GdkEventMotion *event)
3103 gboolean return_value = FALSE;
3108 glViewObjectHandle handle;
3110 cr = gdk_cairo_create (GTK_LAYOUT (view->canvas)->bin_window);
3113 * Translate to label coordinates
3115 scale = view->zoom * view->home_scale;
3116 cairo_scale (cr, scale, scale);
3117 cairo_translate (cr, view->x0, view->y0);
3121 cairo_device_to_user (cr, &x, &y);
3124 * Emit signal regardless of mode
3126 g_signal_emit (G_OBJECT(view), signals[POINTER_MOVED], 0, x, y);
3129 * Handle event as appropriate for mode
3134 case GL_VIEW_MODE_ARROW:
3135 switch (view->state)
3139 if (view_handle_at (view, cr, event->x, event->y, &handle))
3141 cursor = gdk_cursor_new (GDK_CROSSHAIR);
3143 else if (view_view_object_at (view, cr, event->x, event->y))
3145 cursor = gdk_cursor_new (GDK_FLEUR);
3149 cursor = gdk_cursor_new (GDK_LEFT_PTR);
3151 gdk_window_set_cursor (view->canvas->window, cursor);
3152 gdk_cursor_unref (cursor);
3155 case GL_VIEW_ARROW_SELECT_REGION:
3156 view->select_region_x2 = x;
3157 view->select_region_y2 = y;
3158 gl_view_update (view);
3161 case GL_VIEW_ARROW_MOVE:
3162 gl_view_move_selection (view,
3163 (x - view->move_last_x),
3164 (y - view->move_last_y));
3165 view->move_last_x = x;
3166 view->move_last_y = y;
3169 case GL_VIEW_ARROW_RESIZE:
3170 gl_view_object_resize_event (view->resize_object,
3171 view->resize_handle,
3172 view->resize_honor_aspect,
3179 g_message ("Invalid arrow state."); /*Should not happen!*/
3181 return_value = TRUE;
3185 case GL_VIEW_MODE_OBJECT_CREATE:
3186 if (view->state != GL_VIEW_IDLE)
3188 switch (view->create_type)
3190 case GL_LABEL_OBJECT_BOX:
3191 gl_view_box_create_motion_event (view, x, y);
3193 case GL_LABEL_OBJECT_ELLIPSE:
3194 gl_view_ellipse_create_motion_event (view, x, y);
3196 case GL_LABEL_OBJECT_LINE:
3197 gl_view_line_create_motion_event (view, x, y);
3199 case GL_LABEL_OBJECT_IMAGE:
3200 gl_view_image_create_motion_event (view, x, y);
3202 case GL_LABEL_OBJECT_TEXT:
3203 gl_view_text_create_motion_event (view, x, y);
3205 case GL_LABEL_OBJECT_BARCODE:
3206 gl_view_barcode_create_motion_event (view, x, y);
3209 g_message ("Invalid create type."); /*Should not happen!*/
3216 g_message ("Invalid view mode."); /*Should not happen!*/
3223 * FIXME: we re-establish grabs here if the grab has been lost. We seem to be
3224 * losing grabs when we emit signals that lead to the manipulation of
3225 * the GtkUIManager. Needs more investigation
3227 if (view->grabbed_flag && !gdk_pointer_is_grabbed ())
3229 gdk_pointer_grab (GTK_LAYOUT (view->canvas)->bin_window,
3231 (GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK),
3237 return return_value;
3240 /*---------------------------------------------------------------------------*/
3241 /* PRIVATE. Button press event handler. */
3242 /*---------------------------------------------------------------------------*/
3244 button_press_event_cb (glView *view,
3245 GdkEventButton *event)
3247 gboolean return_value = FALSE;
3251 glViewObject *view_object;
3252 glViewObjectHandle handle;
3254 cr = gdk_cairo_create (GTK_LAYOUT (view->canvas)->bin_window);
3257 * Translate to label coordinates
3259 scale = view->zoom * view->home_scale;
3260 cairo_scale (cr, scale, scale);
3261 cairo_translate (cr, view->x0, view->y0);
3265 cairo_device_to_user (cr, &x, &y);
3267 switch (event->button)
3272 * Handle event as appropriate for mode
3276 case GL_VIEW_MODE_ARROW:
3277 if ((view_object = view_handle_at (view, cr, event->x, event->y, &handle)))
3279 view->resize_object = view_object;
3280 view->resize_handle = handle;
3281 view->resize_honor_aspect = event->state & GDK_CONTROL_MASK;
3283 view->state = GL_VIEW_ARROW_RESIZE;
3285 else if ((view_object = view_view_object_at (view, cr, event->x, event->y)))
3287 if (event->state & GDK_CONTROL_MASK)
3289 if (gl_view_is_object_selected (view, view_object))
3291 /* Un-selecting a selected item */
3292 gl_view_unselect_object (view, view_object);
3294 /* Add to current selection */
3295 gl_view_select_object (view, view_object);
3300 if (!gl_view_is_object_selected (view, view_object))
3302 /* remove any selections before adding */
3303 gl_view_unselect_all (view);
3304 /* Add to current selection */
3305 gl_view_select_object (view, view_object);
3308 view->move_last_x = x;
3309 view->move_last_y = y;
3311 view->state = GL_VIEW_ARROW_MOVE;
3315 if (!(event->state & GDK_CONTROL_MASK))
3317 gl_view_unselect_all (view);
3320 view->select_region_visible = TRUE;
3321 view->select_region_x1 = x;
3322 view->select_region_y1 = y;
3323 view->select_region_x2 = x;
3324 view->select_region_y2 = y;
3325 gl_view_update (view);
3327 view->state = GL_VIEW_ARROW_SELECT_REGION;
3331 return_value = TRUE;
3334 case GL_VIEW_MODE_OBJECT_CREATE:
3335 switch (view->create_type)
3337 case GL_LABEL_OBJECT_BOX:
3338 gl_view_box_create_button_press_event (view, x, y);
3340 case GL_LABEL_OBJECT_ELLIPSE:
3341 gl_view_ellipse_create_button_press_event (view, x, y);
3343 case GL_LABEL_OBJECT_LINE:
3344 gl_view_line_create_button_press_event (view, x, y);
3346 case GL_LABEL_OBJECT_IMAGE:
3347 gl_view_image_create_button_press_event (view, x, y);
3349 case GL_LABEL_OBJECT_TEXT:
3350 gl_view_text_create_button_press_event (view, x, y);
3352 case GL_LABEL_OBJECT_BARCODE:
3353 gl_view_barcode_create_button_press_event (view, x, y);
3356 g_message ("Invalid create type."); /*Should not happen!*/
3358 view->state = GL_VIEW_CREATE_DRAG;
3359 return_value = TRUE;
3363 g_message ("Invalid view mode."); /*Should not happen!*/
3366 view->grabbed_flag = TRUE;
3367 gdk_pointer_grab (GTK_LAYOUT (view->canvas)->bin_window,
3369 (GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK),
3376 g_signal_emit (G_OBJECT (view),
3377 signals[CONTEXT_MENU_ACTIVATE], 0,
3378 event->button, event->time);
3379 return_value = TRUE;
3386 return return_value;
3389 /*---------------------------------------------------------------------------*/
3390 /* PRIVATE. Button release event handler. */
3391 /*---------------------------------------------------------------------------*/
3393 button_release_event_cb (glView *view,
3394 GdkEventButton *event)
3396 gboolean return_value = FALSE;
3402 cr = gdk_cairo_create (GTK_LAYOUT (view->canvas)->bin_window);
3405 * Translate to label coordinates
3407 scale = view->zoom * view->home_scale;
3408 cairo_scale (cr, scale, scale);
3409 cairo_translate (cr, view->x0, view->y0);
3413 cairo_device_to_user (cr, &x, &y);
3415 switch (event->button)
3419 view->grabbed_flag = FALSE;
3420 gdk_pointer_ungrab (event->time);
3422 * Handle event as appropriate for mode
3426 case GL_VIEW_MODE_ARROW:
3427 switch (view->state)
3429 case GL_VIEW_ARROW_RESIZE:
3430 view->resize_object = NULL;
3432 view->state = GL_VIEW_IDLE;
3435 case GL_VIEW_ARROW_SELECT_REGION:
3436 view->select_region_visible = FALSE;
3437 view->select_region_x2 = x;
3438 view->select_region_y2 = y;
3440 gl_view_select_region (view,
3441 view->select_region_x1,
3442 view->select_region_y1,
3443 view->select_region_x2,
3444 view->select_region_y2);
3446 gl_view_update (view);
3448 view->state = GL_VIEW_IDLE;
3452 view->state = GL_VIEW_IDLE;
3457 return_value = TRUE;
3461 case GL_VIEW_MODE_OBJECT_CREATE:
3462 switch (view->create_type)
3464 case GL_LABEL_OBJECT_BOX:
3465 gl_view_box_create_button_release_event (view, x, y);
3467 case GL_LABEL_OBJECT_ELLIPSE:
3468 gl_view_ellipse_create_button_release_event (view, x, y);
3470 case GL_LABEL_OBJECT_LINE:
3471 gl_view_line_create_button_release_event (view, x, y);
3473 case GL_LABEL_OBJECT_IMAGE:
3474 gl_view_image_create_button_release_event (view, x, y);
3476 case GL_LABEL_OBJECT_TEXT:
3477 gl_view_text_create_button_release_event (view, x, y);
3479 case GL_LABEL_OBJECT_BARCODE:
3480 gl_view_barcode_create_button_release_event (view, x, y);
3483 g_message ("Invalid create type."); /*Should not happen!*/
3485 view->mode = GL_VIEW_MODE_ARROW;
3486 view->state = GL_VIEW_IDLE;
3487 cursor = gdk_cursor_new (GDK_LEFT_PTR);
3488 gdk_window_set_cursor (view->canvas->window, cursor);
3489 gdk_cursor_unref (cursor);
3494 g_message ("Invalid view mode."); /*Should not happen!*/
3501 return return_value;
3504 /*---------------------------------------------------------------------------*/
3505 /* PRIVATE. Key press event handler. */
3506 /*---------------------------------------------------------------------------*/
3508 key_press_event_cb (glView *view,
3513 gl_debug (DEBUG_VIEW, "");
3515 if ( (view->mode == GL_VIEW_MODE_ARROW) &&
3516 (view->state == GL_VIEW_IDLE) )
3518 switch (event->keyval) {
3522 gl_view_move_selection (view, -1.0 / (view->zoom), 0.0);
3526 gl_view_move_selection (view, 0.0, -1.0 / (view->zoom));
3530 gl_view_move_selection (view, 1.0 / (view->zoom), 0.0);
3534 gl_view_move_selection (view, 0.0, 1.0 / (view->zoom));
3538 gl_view_delete_selection (view);
3539 cursor = gdk_cursor_new (GDK_LEFT_PTR);
3540 gdk_window_set_cursor (GTK_WIDGET (view->canvas)->window
3542 gdk_cursor_unref (cursor);
3549 return TRUE; /* We handled this or we were dragging. */