2 * (GLABELS) Label and Business Card Creation program for GNOME
4 * view.c: GLabels View module
6 * Copyright (C) 2001-2002 Jim Evins <evins@snaught.com>.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include <gtk/gtkinvisible.h>
32 #include "view-object.h"
34 #include "view-ellipse.h"
35 #include "view-line.h"
36 #include "view-image.h"
37 #include "view-text.h"
38 #include "view-barcode.h"
39 #include "xml-label.h"
45 /*==========================================================================*/
46 /* Private macros and constants. */
47 /*==========================================================================*/
49 #define BG_COLOR GL_COLOR (192, 192, 192)
50 #define OUTLINE_COLOR GL_COLOR (173, 216, 230)
51 #define PAPER_COLOR GL_COLOR (255, 255, 255)
52 #define GRID_COLOR BG_COLOR
53 #define MARKUP_COLOR GL_COLOR (240, 100, 100)
55 #define SEL_LINE_COLOR GL_COLOR_A (0, 0, 255, 128)
56 #define SEL_FILL_COLOR GL_COLOR_A (192, 192, 255, 128)
58 /*==========================================================================*/
60 /*==========================================================================*/
72 /*==========================================================================*/
74 /*==========================================================================*/
76 static GtkContainerClass *parent_class;
78 static guint signals[LAST_SIGNAL] = {0};
80 /* "CLIPBOARD" selection */
81 static GdkAtom clipboard_atom = GDK_NONE;
83 static gdouble scales[] = {
88 #define N_SCALES G_N_ELEMENTS(scales)
89 #define HOME_SCALE 2.0
91 /*==========================================================================*/
92 /* Local function prototypes */
93 /*==========================================================================*/
95 static void gl_view_class_init (glViewClass *class);
96 static void gl_view_init (glView *view);
97 static void gl_view_finalize (GObject *object);
99 static void gl_view_construct (glView *view);
100 static GtkWidget *gl_view_construct_canvas (glView *view);
101 static void gl_view_construct_selection (glView *view);
103 static gdouble get_apropriate_scale (gdouble w, gdouble h);
105 static void draw_layers (glView *view);
107 static void draw_label_layer (glView *view);
109 static void draw_bg_fg_layers (glView *view);
110 static void draw_bg_fg_rect (glView *view);
111 static void draw_bg_fg_rounded_rect (glView *view);
112 static void draw_bg_fg_round (glView *view);
113 static void draw_bg_fg_cd (glView *view);
115 static void draw_grid_layer (glView *view);
117 static void draw_markup_layer (glView *view);
119 static void draw_markup_margin (glView *view,
120 glTemplateMarkupMargin *margin);
121 static void draw_markup_margin_rect (glView *view,
122 glTemplateMarkupMargin *margin);
123 static void draw_markup_margin_rounded_rect (glView *view,
124 glTemplateMarkupMargin *margin);
125 static void draw_markup_margin_round (glView *view,
126 glTemplateMarkupMargin *margin);
127 static void draw_markup_margin_cd (glView *view,
128 glTemplateMarkupMargin *margin);
130 static void draw_markup_line (glView *view,
131 glTemplateMarkupLine *line);
134 static void select_object_real (glView *view,
135 glViewObject *view_object);
136 static void unselect_object_real (glView *view,
137 glViewObject *view_object);
139 static gboolean object_at (glView *view,
140 gdouble x, gdouble y);
142 static gboolean is_item_member_of_group (glView *view,
143 GnomeCanvasItem *item,
144 GnomeCanvasItem *group);
146 static gboolean is_object_selected (glView *view,
147 glViewObject *view_object);
149 static void move_selection (glView *view,
150 gdouble dx, gdouble dy);
152 static int canvas_event (GnomeCanvas *canvas,
155 static int canvas_event_arrow_mode (GnomeCanvas *canvas,
159 static int item_event_arrow_mode (GnomeCanvasItem *item,
161 glViewObject *view_object);
163 static GtkWidget *new_selection_menu (glView *view);
165 static void popup_selection_menu (glView *view,
166 glViewObject *view_object,
169 static void selection_clear_cb (GtkWidget *widget,
170 GdkEventSelection *event,
173 static void selection_get_cb (GtkWidget *widget,
174 GtkSelectionData *selection_data,
179 static void selection_received_cb (GtkWidget *widget,
180 GtkSelectionData *selection_data,
184 /****************************************************************************/
185 /* Boilerplate Object stuff. */
186 /****************************************************************************/
188 gl_view_get_type (void)
190 static guint view_type = 0;
193 GTypeInfo view_info = {
194 sizeof (glViewClass),
197 (GClassInitFunc) gl_view_class_init,
202 (GInstanceInitFunc) gl_view_init,
206 g_type_register_static (gtk_vbox_get_type (),
207 "glView", &view_info, 0);
214 gl_view_class_init (glViewClass *class)
216 GObjectClass *object_class = (GObjectClass *) class;
218 gl_debug (DEBUG_VIEW, "START");
220 parent_class = g_type_class_peek_parent (class);
222 object_class->finalize = gl_view_finalize;
224 signals[SELECTION_CHANGED] =
225 g_signal_new ("selection_changed",
226 G_OBJECT_CLASS_TYPE (object_class),
228 G_STRUCT_OFFSET (glViewClass, selection_changed),
230 gl_marshal_VOID__VOID,
234 signals[ZOOM_CHANGED] =
235 g_signal_new ("zoom_changed",
236 G_OBJECT_CLASS_TYPE (object_class),
238 G_STRUCT_OFFSET (glViewClass, zoom_changed),
240 gl_marshal_VOID__DOUBLE,
244 signals[POINTER_MOVED] =
245 g_signal_new ("pointer_moved",
246 G_OBJECT_CLASS_TYPE (object_class),
248 G_STRUCT_OFFSET (glViewClass, pointer_moved),
250 gl_marshal_VOID__DOUBLE_DOUBLE,
252 2, G_TYPE_DOUBLE, G_TYPE_DOUBLE);
254 signals[POINTER_EXIT] =
255 g_signal_new ("pointer_exit",
256 G_OBJECT_CLASS_TYPE (object_class),
258 G_STRUCT_OFFSET (glViewClass, pointer_exit),
260 gl_marshal_VOID__VOID,
264 signals[MODE_CHANGED] =
265 g_signal_new ("mode_changed",
266 G_OBJECT_CLASS_TYPE (object_class),
268 G_STRUCT_OFFSET (glViewClass, mode_changed),
270 gl_marshal_VOID__VOID,
274 gl_debug (DEBUG_VIEW, "END");
278 gl_view_init (glView *view)
280 gl_debug (DEBUG_VIEW, "START");
284 view->grid_spacing = 9;
286 gl_debug (DEBUG_VIEW, "END");
290 gl_view_finalize (GObject *object)
294 gl_debug (DEBUG_VIEW, "START");
296 g_return_if_fail (object != NULL);
297 g_return_if_fail (GL_IS_VIEW (object));
299 view = GL_VIEW (object);
301 G_OBJECT_CLASS (parent_class)->finalize (object);
303 gl_debug (DEBUG_VIEW, "END");
306 /****************************************************************************/
307 /* NEW view object. */
308 /****************************************************************************/
310 gl_view_new (glLabel *label)
312 glView *view = g_object_new (gl_view_get_type (), NULL);
314 gl_debug (DEBUG_VIEW, "START");
318 gl_view_construct (view);
320 gl_debug (DEBUG_VIEW, "END");
322 return GTK_WIDGET (view);
325 /*---------------------------------------------------------------------------*/
326 /* PRIVATE. Construct composite widget. */
327 /*---------------------------------------------------------------------------*/
329 gl_view_construct (glView *view)
331 GtkWidget *wvbox, *wscroll;
333 gl_debug (DEBUG_VIEW, "START");
335 g_return_if_fail (GL_IS_VIEW (view));
337 wvbox = GTK_WIDGET (view);
339 view->state = GL_VIEW_STATE_ARROW;
340 view->object_list = NULL;
342 gl_view_construct_canvas (view);
343 wscroll = gtk_scrolled_window_new (NULL, NULL);
344 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (wscroll),
345 GTK_POLICY_AUTOMATIC,
346 GTK_POLICY_AUTOMATIC);
347 gtk_box_pack_start (GTK_BOX (wvbox), wscroll, TRUE, TRUE, 0);
348 gtk_container_add (GTK_CONTAINER (wscroll), view->canvas);
350 gl_view_construct_selection (view);
352 view->menu = new_selection_menu (view);
354 gl_debug (DEBUG_VIEW, "END");
357 /*---------------------------------------------------------------------------*/
358 /* PRIVATE. Create canvas w/ a background in the shape of the label/card. */
359 /*---------------------------------------------------------------------------*/
361 gl_view_construct_canvas (glView *view)
364 glLabel *label = view->label;
365 gdouble label_width, label_height;
368 gl_debug (DEBUG_VIEW, "START");
370 g_return_val_if_fail (GL_IS_VIEW (view), NULL);
371 g_return_val_if_fail (label != NULL, NULL);
373 gtk_widget_push_colormap (gdk_rgb_get_colormap ());
374 view->canvas = gnome_canvas_new_aa ();
375 gtk_widget_pop_colormap ();
377 bg_color = gl_color_to_gdk_color (BG_COLOR);
378 gtk_widget_modify_bg (GTK_WIDGET(view->canvas), GTK_STATE_NORMAL, bg_color);
381 gl_label_get_size (label, &label_width, &label_height);
382 gl_debug (DEBUG_VIEW, "Label size: w=%lf, h=%lf",
383 label_width, label_height);
385 scale = get_apropriate_scale (label_width, label_height);
386 gl_debug (DEBUG_VIEW, "scale =%lf", scale);
388 gl_debug (DEBUG_VIEW, "Canvas size: w=%lf, h=%lf",
389 scale * label_width + 40,
390 scale * label_height + 40);
391 gtk_widget_set_size_request (GTK_WIDGET(view->canvas),
392 scale * label_width + 40,
393 scale * label_height + 40);
394 gnome_canvas_set_pixels_per_unit (GNOME_CANVAS (view->canvas),
398 gnome_canvas_set_scroll_region (GNOME_CANVAS (view->canvas),
399 0.0, 0.0, label_width, label_height);
403 g_signal_connect (G_OBJECT (view->canvas), "event",
404 G_CALLBACK (canvas_event), view);
406 gl_debug (DEBUG_VIEW, "END");
411 /*---------------------------------------------------------------------------*/
412 /* PRIVATE. Create clipboard selection targets. */
413 /*---------------------------------------------------------------------------*/
415 gl_view_construct_selection (glView *view)
417 gl_debug (DEBUG_VIEW, "START");
419 g_return_if_fail (GL_IS_VIEW (view));
421 view->have_selection = FALSE;
422 view->selection_data = NULL;
423 view->invisible = gtk_invisible_new ();
425 view->selected_object_list = NULL;
427 if (!clipboard_atom) {
428 clipboard_atom = gdk_atom_intern ("GLABELS_CLIPBOARD", FALSE);
431 gtk_selection_add_target (view->invisible,
432 clipboard_atom, GDK_SELECTION_TYPE_STRING, 1);
434 g_signal_connect (G_OBJECT (view->invisible),
435 "selection_clear_event",
436 G_CALLBACK (selection_clear_cb), view);
438 g_signal_connect (G_OBJECT (view->invisible), "selection_get",
439 G_CALLBACK (selection_get_cb), view);
441 g_signal_connect (G_OBJECT (view->invisible),
442 "selection_received",
443 G_CALLBACK (selection_received_cb), view);
445 gl_debug (DEBUG_VIEW, "END");
448 /*---------------------------------------------------------------------------*/
449 /* PRIVATE. Determine an apropriate scale for given label & screen size */
450 /*---------------------------------------------------------------------------*/
452 get_apropriate_scale (gdouble w, gdouble h)
454 gdouble w_screen, h_screen;
458 gl_debug (DEBUG_VIEW, "");
460 w_screen = (gdouble) gdk_screen_width ();
461 h_screen = (gdouble) gdk_screen_height ();
463 for (i = 0; i < N_SCALES; i++) {
465 if (k <= HOME_SCALE) {
466 if ((k * w < (w_screen - 256))
467 && (k * h < (h_screen - 256)))
475 /*---------------------------------------------------------------------------*/
476 /* PRIVATE. Create, draw and order layers. */
477 /*---------------------------------------------------------------------------*/
479 draw_layers (glView *view)
481 draw_bg_fg_layers (view);
482 draw_grid_layer (view);
483 draw_markup_layer (view);
484 draw_label_layer (view);
486 gnome_canvas_item_raise_to_top (GNOME_CANVAS_ITEM(view->fg_group));
489 /*---------------------------------------------------------------------------*/
490 /* PRIVATE. Draw label layer. */
491 /*---------------------------------------------------------------------------*/
493 draw_label_layer (glView *view)
495 GnomeCanvasGroup *group;
498 glLabelObject *object;
499 glViewObject *view_object;
501 group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
502 view->label_group = GNOME_CANVAS_GROUP(
503 gnome_canvas_item_new (group,
504 gnome_canvas_group_get_type (),
511 for (p_obj = label->objects; p_obj != NULL; p_obj = p_obj->next) {
512 object = (glLabelObject *) p_obj->data;
514 if (GL_IS_LABEL_BOX (object)) {
515 view_object = gl_view_box_new (GL_LABEL_BOX(object),
517 } else if (GL_IS_LABEL_ELLIPSE (object)) {
518 view_object = gl_view_ellipse_new (GL_LABEL_ELLIPSE(object),
520 } else if (GL_IS_LABEL_LINE (object)) {
521 view_object = gl_view_line_new (GL_LABEL_LINE(object),
523 } else if (GL_IS_LABEL_IMAGE (object)) {
524 view_object = gl_view_image_new (GL_LABEL_IMAGE(object),
526 } else if (GL_IS_LABEL_TEXT (object)) {
527 view_object = gl_view_text_new (GL_LABEL_TEXT(object),
529 } else if (GL_IS_LABEL_BARCODE (object)) {
530 view_object = gl_view_barcode_new (GL_LABEL_BARCODE(object),
533 /* Should not happen! */
535 g_warning ("Invalid label object type.");
540 /*---------------------------------------------------------------------------*/
541 /* PRIVATE. Draw background and foreground outlines. */
542 /*---------------------------------------------------------------------------*/
544 draw_bg_fg_layers (glView *view)
547 glTemplate *template;
548 GnomeCanvasGroup *group;
550 group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
551 view->bg_group = GNOME_CANVAS_GROUP(
552 gnome_canvas_item_new (group,
553 gnome_canvas_group_get_type (),
557 view->fg_group = GNOME_CANVAS_GROUP(
558 gnome_canvas_item_new (group,
559 gnome_canvas_group_get_type (),
565 template = gl_label_get_template (label);
567 switch (template->label.style) {
569 case GL_TEMPLATE_STYLE_RECT:
570 if (template->label.rect.r == 0.0) {
571 /* Square corners. */
572 draw_bg_fg_rect (view);
574 /* Rounded corners. */
575 draw_bg_fg_rounded_rect (view);
579 case GL_TEMPLATE_STYLE_ROUND:
580 draw_bg_fg_round (view);
583 case GL_TEMPLATE_STYLE_CD:
584 draw_bg_fg_cd (view);
588 g_warning ("Unknown template label style");
593 /*---------------------------------------------------------------------------*/
594 /* PRIVATE. Draw simple recangular background. */
595 /*---------------------------------------------------------------------------*/
597 draw_bg_fg_rect (glView *view)
599 glLabel *label = view->label;
600 glTemplate *template;
602 GnomeCanvasItem *item;
604 gl_debug (DEBUG_VIEW, "START");
606 g_return_if_fail (GL_IS_VIEW (view));
607 g_return_if_fail (label != NULL);
609 gl_label_get_size (label, &w, &h);
610 template = gl_label_get_template (label);
613 item = gnome_canvas_item_new (view->bg_group,
614 gnome_canvas_rect_get_type (),
619 "fill_color_rgba", PAPER_COLOR,
623 item = gnome_canvas_item_new (view->fg_group,
624 gnome_canvas_rect_get_type (),
630 "outline_color_rgba", OUTLINE_COLOR,
633 gl_debug (DEBUG_VIEW, "END");
636 /*---------------------------------------------------------------------------*/
637 /* PRIVATE. Draw rounded recangular background. */
638 /*---------------------------------------------------------------------------*/
640 draw_bg_fg_rounded_rect (glView *view)
642 glLabel *label = view->label;
643 GnomeCanvasPoints *points;
644 gint i_coords, i_theta;
645 glTemplate *template;
647 GnomeCanvasItem *item;
649 gl_debug (DEBUG_VIEW, "START");
651 g_return_if_fail (GL_IS_VIEW (view));
652 g_return_if_fail (label != NULL);
654 gl_label_get_size (label, &w, &h);
655 template = gl_label_get_template (label);
656 r = template->label.rect.r;
658 points = gnome_canvas_points_new (4 * (1 + 90 / 5));
660 for (i_theta = 0; i_theta <= 90; i_theta += 5) {
661 points->coords[i_coords++] =
662 r - r * sin (i_theta * M_PI / 180.0);
663 points->coords[i_coords++] =
664 r - r * cos (i_theta * M_PI / 180.0);
666 for (i_theta = 0; i_theta <= 90; i_theta += 5) {
667 points->coords[i_coords++] =
668 r - r * cos (i_theta * M_PI / 180.0);
669 points->coords[i_coords++] =
670 (h - r) + r * sin (i_theta * M_PI / 180.0);
672 for (i_theta = 0; i_theta <= 90; i_theta += 5) {
673 points->coords[i_coords++] =
674 (w - r) + r * sin (i_theta * M_PI / 180.0);
675 points->coords[i_coords++] =
676 (h - r) + r * cos (i_theta * M_PI / 180.0);
678 for (i_theta = 0; i_theta <= 90; i_theta += 5) {
679 points->coords[i_coords++] =
680 (w - r) + r * cos (i_theta * M_PI / 180.0);
681 points->coords[i_coords++] =
682 r - r * sin (i_theta * M_PI / 180.0);
686 item = gnome_canvas_item_new (view->bg_group,
687 gnome_canvas_polygon_get_type (),
689 "fill_color_rgba", PAPER_COLOR,
693 item = gnome_canvas_item_new (view->fg_group,
694 gnome_canvas_polygon_get_type (),
697 "outline_color_rgba", OUTLINE_COLOR,
700 gnome_canvas_points_free (points);
702 gl_debug (DEBUG_VIEW, "END");
705 /*---------------------------------------------------------------------------*/
706 /* PRIVATE. Draw round background. */
707 /*---------------------------------------------------------------------------*/
709 draw_bg_fg_round (glView *view)
711 glLabel *label = view->label;
712 glTemplate *template;
714 GnomeCanvasItem *item;
716 gl_debug (DEBUG_VIEW, "START");
718 g_return_if_fail (GL_IS_VIEW (view));
719 g_return_if_fail (label != NULL);
721 template = gl_label_get_template (label);
723 r = template->label.round.r;
726 item = gnome_canvas_item_new (view->bg_group,
727 gnome_canvas_ellipse_get_type (),
732 "fill_color_rgba", PAPER_COLOR,
736 item = gnome_canvas_item_new (view->fg_group,
737 gnome_canvas_ellipse_get_type (),
743 "outline_color_rgba", OUTLINE_COLOR,
746 gl_debug (DEBUG_VIEW, "END");
749 /*---------------------------------------------------------------------------*/
750 /* PRIVATE. Draw CD style background, circular w/ concentric hole. */
751 /*---------------------------------------------------------------------------*/
753 draw_bg_fg_cd (glView *view)
755 glLabel *label = view->label;
756 glTemplate *template;
758 GnomeCanvasItem *item;
760 gl_debug (DEBUG_VIEW, "START");
762 g_return_if_fail (GL_IS_VIEW (view));
763 g_return_if_fail (label != NULL);
765 template = gl_label_get_template (label);
767 r1 = template->label.cd.r1;
768 r2 = template->label.cd.r2;
772 item = gnome_canvas_item_new (view->bg_group,
773 gnome_canvas_ellipse_get_type (),
778 "fill_color_rgba", PAPER_COLOR,
781 item = gnome_canvas_item_new (view->bg_group,
782 gnome_canvas_ellipse_get_type (),
787 "fill_color_rgba", GRID_COLOR,
792 item = gnome_canvas_item_new (view->fg_group,
793 gnome_canvas_ellipse_get_type (),
799 "outline_color_rgba", OUTLINE_COLOR,
802 item = gnome_canvas_item_new (view->fg_group,
803 gnome_canvas_ellipse_get_type (),
809 "outline_color_rgba", OUTLINE_COLOR,
812 gl_debug (DEBUG_VIEW, "END");
815 /*---------------------------------------------------------------------------*/
816 /* PRIVATE. Draw grid lines. */
817 /*---------------------------------------------------------------------------*/
819 draw_grid_layer (glView *view)
822 GnomeCanvasPoints *points;
823 GnomeCanvasItem *item;
824 GnomeCanvasGroup *group;
826 gl_debug (DEBUG_VIEW, "START");
828 g_return_if_fail (view && GL_IS_VIEW (view));
829 g_return_if_fail (view->label && GL_IS_LABEL(view->label));
831 gl_label_get_size (view->label, &w, &h);
833 group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
834 view->grid_group = GNOME_CANVAS_GROUP(
835 gnome_canvas_item_new (group,
836 gnome_canvas_group_get_type (),
840 points = gnome_canvas_points_new (2);
842 points->coords[1] = 0.0;
843 points->coords[3] = h;
844 for ( x=0.0; x < w; x += view->grid_spacing ) {
845 points->coords[0] = points->coords[2] = x;
846 item = gnome_canvas_item_new (view->grid_group,
847 gnome_canvas_line_get_type (),
850 "fill_color_rgba", GRID_COLOR,
853 points->coords[0] = points->coords[2] = w;
854 item = gnome_canvas_item_new (view->grid_group,
855 gnome_canvas_line_get_type (),
858 "fill_color_rgba", GRID_COLOR,
861 points->coords[0] = 0.0;
862 points->coords[2] = w;
863 for ( y=0.0; y < h; y += view->grid_spacing ) {
864 points->coords[1] = points->coords[3] = y;
865 item = gnome_canvas_item_new (view->grid_group,
866 gnome_canvas_line_get_type (),
869 "fill_color_rgba", GRID_COLOR,
872 points->coords[1] = points->coords[3] = h;
873 item = gnome_canvas_item_new (view->grid_group,
874 gnome_canvas_line_get_type (),
877 "fill_color_rgba", GRID_COLOR,
880 gnome_canvas_points_free (points);
882 gl_debug (DEBUG_VIEW, "END");
885 /*---------------------------------------------------------------------------*/
886 /* PRIVATE. Draw markup lines. */
887 /*---------------------------------------------------------------------------*/
889 draw_markup_layer (glView *view)
891 GnomeCanvasGroup *group;
893 glTemplate *template;
895 glTemplateMarkup *markup;
897 group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
898 view->markup_group = GNOME_CANVAS_GROUP(
899 gnome_canvas_item_new (group,
900 gnome_canvas_group_get_type (),
905 template = gl_label_get_template (label);
907 for ( p=template->label.any.markups; p != NULL; p=p->next ) {
908 markup = (glTemplateMarkup *)p->data;
910 switch (markup->type) {
911 case GL_TEMPLATE_MARKUP_MARGIN:
912 draw_markup_margin (view,
913 (glTemplateMarkupMargin *)markup);
915 case GL_TEMPLATE_MARKUP_LINE:
916 draw_markup_line (view,
917 (glTemplateMarkupLine *)markup);
920 g_warning ("Unknown template markup type");
926 /*---------------------------------------------------------------------------*/
927 /* PRIVATE. Draw margin markup. */
928 /*---------------------------------------------------------------------------*/
930 draw_markup_margin (glView *view,
931 glTemplateMarkupMargin *margin)
934 glTemplate *template;
937 template = gl_label_get_template (label);
939 switch (template->label.style) {
941 case GL_TEMPLATE_STYLE_RECT:
942 if (template->label.rect.r == 0.0) {
943 /* Square corners. */
944 draw_markup_margin_rect (view, margin);
946 if ( margin->size < template->label.rect.r) {
947 /* Rounded corners. */
948 draw_markup_margin_rounded_rect (view, margin);
950 /* Square corners. */
951 draw_markup_margin_rect (view, margin);
956 case GL_TEMPLATE_STYLE_ROUND:
957 draw_markup_margin_round (view, margin);
960 case GL_TEMPLATE_STYLE_CD:
961 draw_markup_margin_cd (view, margin);
965 g_warning ("Unknown template label style");
970 /*---------------------------------------------------------------------------*/
971 /* PRIVATE. Draw simple recangular margin. */
972 /*---------------------------------------------------------------------------*/
974 draw_markup_margin_rect (glView *view,
975 glTemplateMarkupMargin *margin)
977 glLabel *label = view->label;
978 glTemplate *template;
980 GnomeCanvasItem *item;
982 gl_debug (DEBUG_VIEW, "START");
984 g_return_if_fail (GL_IS_VIEW (view));
985 g_return_if_fail (label != NULL);
987 gl_label_get_size (label, &w, &h);
988 template = gl_label_get_template (label);
991 /* Bounding box @ margin */
992 gnome_canvas_item_new (view->markup_group,
993 gnome_canvas_rect_get_type (),
999 "outline_color_rgba", MARKUP_COLOR,
1002 gl_debug (DEBUG_VIEW, "END");
1005 /*---------------------------------------------------------------------------*/
1006 /* PRIVATE. Draw rounded recangular markup. */
1007 /*---------------------------------------------------------------------------*/
1009 draw_markup_margin_rounded_rect (glView *view,
1010 glTemplateMarkupMargin *margin)
1012 glLabel *label = view->label;
1013 GnomeCanvasPoints *points;
1014 gint i_coords, i_theta;
1015 glTemplate *template;
1017 GnomeCanvasItem *item;
1019 gl_debug (DEBUG_VIEW, "START");
1021 g_return_if_fail (GL_IS_VIEW (view));
1022 g_return_if_fail (label != NULL);
1024 gl_label_get_size (label, &w, &h);
1025 template = gl_label_get_template (label);
1026 r = template->label.rect.r;
1033 /* rectangle with rounded corners */
1034 points = gnome_canvas_points_new (4 * (1 + 90 / 5));
1036 for (i_theta = 0; i_theta <= 90; i_theta += 5) {
1037 points->coords[i_coords++] =
1038 m + r - r * sin (i_theta * M_PI / 180.0);
1039 points->coords[i_coords++] =
1040 m + r - r * cos (i_theta * M_PI / 180.0);
1042 for (i_theta = 0; i_theta <= 90; i_theta += 5) {
1043 points->coords[i_coords++] =
1044 m + r - r * cos (i_theta * M_PI / 180.0);
1045 points->coords[i_coords++] =
1046 m + (h - r) + r * sin (i_theta * M_PI / 180.0);
1048 for (i_theta = 0; i_theta <= 90; i_theta += 5) {
1049 points->coords[i_coords++] =
1050 m + (w - r) + r * sin (i_theta * M_PI / 180.0);
1051 points->coords[i_coords++] =
1052 m + (h - r) + r * cos (i_theta * M_PI / 180.0);
1054 for (i_theta = 0; i_theta <= 90; i_theta += 5) {
1055 points->coords[i_coords++] =
1056 m + (w - r) + r * cos (i_theta * M_PI / 180.0);
1057 points->coords[i_coords++] =
1058 m + r - r * sin (i_theta * M_PI / 180.0);
1060 item = gnome_canvas_item_new (view->markup_group,
1061 gnome_canvas_polygon_get_type (),
1064 "outline_color_rgba", MARKUP_COLOR,
1066 gnome_canvas_points_free (points);
1068 gl_debug (DEBUG_VIEW, "END");
1071 /*---------------------------------------------------------------------------*/
1072 /* PRIVATE. Draw round margin. */
1073 /*---------------------------------------------------------------------------*/
1075 draw_markup_margin_round (glView *view,
1076 glTemplateMarkupMargin *margin)
1078 glLabel *label = view->label;
1079 glTemplate *template;
1081 GnomeCanvasItem *item;
1083 gl_debug (DEBUG_VIEW, "START");
1085 g_return_if_fail (GL_IS_VIEW (view));
1086 g_return_if_fail (label != NULL);
1088 template = gl_label_get_template (label);
1090 r = template->label.round.r;
1093 /* Margin outline */
1094 item = gnome_canvas_item_new (view->markup_group,
1095 gnome_canvas_ellipse_get_type (),
1101 "outline_color_rgba", MARKUP_COLOR,
1104 gl_debug (DEBUG_VIEW, "END");
1107 /*---------------------------------------------------------------------------*/
1108 /* PRIVATE. Draw CD margins. */
1109 /*---------------------------------------------------------------------------*/
1111 draw_markup_margin_cd (glView *view,
1112 glTemplateMarkupMargin *margin)
1114 glLabel *label = view->label;
1115 glTemplate *template;
1117 GnomeCanvasItem *item;
1119 gl_debug (DEBUG_VIEW, "START");
1121 g_return_if_fail (GL_IS_VIEW (view));
1122 g_return_if_fail (label != NULL);
1124 template = gl_label_get_template (label);
1126 r1 = template->label.cd.r1;
1127 r2 = template->label.cd.r2;
1131 item = gnome_canvas_item_new (view->markup_group,
1132 gnome_canvas_ellipse_get_type (),
1138 "outline_color_rgba", MARKUP_COLOR,
1141 item = gnome_canvas_item_new (view->markup_group,
1142 gnome_canvas_ellipse_get_type (),
1148 "outline_color_rgba", MARKUP_COLOR,
1151 gl_debug (DEBUG_VIEW, "END");
1154 /*---------------------------------------------------------------------------*/
1155 /* PRIVATE. Draw line markup. */
1156 /*---------------------------------------------------------------------------*/
1158 draw_markup_line (glView *view,
1159 glTemplateMarkupLine *line)
1161 GnomeCanvasPoints *points;
1163 gl_debug (DEBUG_VIEW, "START");
1165 g_return_if_fail (GL_IS_VIEW (view));
1167 points = gnome_canvas_points_new (2);
1168 points->coords[0] = line->x1;
1169 points->coords[1] = line->y1;
1170 points->coords[2] = line->x2;
1171 points->coords[3] = line->y2;
1173 /* Bounding box @ margin */
1174 gnome_canvas_item_new (view->markup_group,
1175 gnome_canvas_line_get_type (),
1178 "fill_color_rgba", MARKUP_COLOR,
1181 gnome_canvas_points_free (points);
1183 gl_debug (DEBUG_VIEW, "END");
1186 /*****************************************************************************/
1187 /* Raise foreground items to top. */
1188 /*****************************************************************************/
1190 gl_view_raise_fg (glView *view)
1194 gnome_canvas_item_raise_to_top (GNOME_CANVAS_ITEM(view->fg_group));
1197 /*****************************************************************************/
1199 /*****************************************************************************/
1200 void gl_view_show_grid (glView *view)
1202 gnome_canvas_item_show (GNOME_CANVAS_ITEM(view->grid_group));
1205 /*****************************************************************************/
1207 /*****************************************************************************/
1208 void gl_view_hide_grid (glView *view)
1210 gnome_canvas_item_hide (GNOME_CANVAS_ITEM(view->grid_group));
1213 /*****************************************************************************/
1214 /* Set grid spacing. */
1215 /*****************************************************************************/
1216 void gl_view_set_grid_spacing (glView *view,
1219 view->grid_spacing = spacing;
1221 gtk_object_destroy (GTK_OBJECT(view->grid_group));
1222 draw_grid_layer (view);
1225 /*****************************************************************************/
1227 /*****************************************************************************/
1228 void gl_view_show_markup (glView *view)
1230 gnome_canvas_item_show (GNOME_CANVAS_ITEM(view->markup_group));
1233 /*****************************************************************************/
1235 /*****************************************************************************/
1236 void gl_view_hide_markup (glView *view)
1238 gnome_canvas_item_hide (GNOME_CANVAS_ITEM(view->markup_group));
1241 /*****************************************************************************/
1242 /* Set arrow mode. */
1243 /*****************************************************************************/
1245 gl_view_arrow_mode (glView *view)
1247 static GdkCursor *cursor = NULL;
1249 gl_debug (DEBUG_VIEW, "START");
1251 g_return_if_fail (GL_IS_VIEW (view));
1254 cursor = gdk_cursor_new (GDK_LEFT_PTR);
1257 gdk_window_set_cursor (view->canvas->window, cursor);
1259 view->state = GL_VIEW_STATE_ARROW;
1261 gl_debug (DEBUG_VIEW, "END");
1264 /*****************************************************************************/
1265 /* Set create text object mode. */
1266 /*****************************************************************************/
1268 gl_view_object_create_mode (glView *view,
1269 glLabelObjectType type)
1273 gl_debug (DEBUG_VIEW, "START");
1275 g_return_if_fail (GL_IS_VIEW (view));
1278 case GL_LABEL_OBJECT_BOX:
1279 cursor = gl_view_box_get_create_cursor ();
1281 case GL_LABEL_OBJECT_ELLIPSE:
1282 cursor = gl_view_ellipse_get_create_cursor ();
1284 case GL_LABEL_OBJECT_LINE:
1285 cursor = gl_view_line_get_create_cursor ();
1287 case GL_LABEL_OBJECT_IMAGE:
1288 cursor = gl_view_image_get_create_cursor ();
1290 case GL_LABEL_OBJECT_TEXT:
1291 cursor = gl_view_text_get_create_cursor ();
1293 case GL_LABEL_OBJECT_BARCODE:
1294 cursor = gl_view_barcode_get_create_cursor ();
1297 g_warning ("Invalid label object type.");/*Should not happen!*/
1301 gdk_window_set_cursor (view->canvas->window, cursor);
1303 view->state = GL_VIEW_STATE_OBJECT_CREATE;
1304 view->create_type = type;
1306 gl_debug (DEBUG_VIEW, "END");
1309 /*****************************************************************************/
1310 /* Select given object (adding to current selection). */
1311 /*****************************************************************************/
1313 gl_view_select_object (glView *view,
1314 glViewObject *view_object)
1316 gl_debug (DEBUG_VIEW, "START");
1318 select_object_real (view, view_object);
1320 g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1322 gl_debug (DEBUG_VIEW, "END");
1325 /*****************************************************************************/
1326 /* Unselect given object (removing from current selection). */
1327 /*****************************************************************************/
1329 gl_view_unselect_object (glView *view,
1330 glViewObject *view_object)
1332 gl_debug (DEBUG_VIEW, "START");
1334 unselect_object_real (view, view_object);
1336 g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1338 gl_debug (DEBUG_VIEW, "END");
1341 /*****************************************************************************/
1342 /* Select all items. */
1343 /*****************************************************************************/
1345 gl_view_select_all (glView *view)
1349 gl_debug (DEBUG_VIEW, "START");
1351 g_return_if_fail (GL_IS_VIEW (view));
1353 /* 1st unselect anything already selected. */
1354 for (p = view->selected_object_list; p != NULL; p = p_next) {
1356 unselect_object_real (view, GL_VIEW_OBJECT (p->data));
1359 /* Finally select all objects. */
1360 for (p = view->object_list; p != NULL; p = p->next) {
1361 select_object_real (view, GL_VIEW_OBJECT (p->data));
1364 g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1366 gl_debug (DEBUG_VIEW, "END");
1369 /*****************************************************************************/
1370 /* Remove all selections */
1371 /*****************************************************************************/
1373 gl_view_unselect_all (glView *view)
1377 gl_debug (DEBUG_VIEW, "START");
1379 g_return_if_fail (GL_IS_VIEW (view));
1381 for (p = view->selected_object_list; p != NULL; p = p_next) {
1383 unselect_object_real (view, GL_VIEW_OBJECT (p->data));
1386 g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1388 gl_debug (DEBUG_VIEW, "END");
1391 /*****************************************************************************/
1392 /* Select all objects within given rectangular region (adding to selection). */
1393 /*****************************************************************************/
1395 gl_view_select_region (glView *view,
1402 glViewObject *view_object;
1403 glLabelObject *object;
1404 gdouble i_x1, i_y1, i_x2, i_y2, w, h;
1406 gl_debug (DEBUG_VIEW, "START");
1408 g_return_if_fail (GL_IS_VIEW (view));
1409 g_return_if_fail ((x1 <= x2) && (y1 <= y2));
1411 for (p = view->object_list; p != NULL; p = p->next) {
1412 view_object = GL_VIEW_OBJECT(p->data);
1413 if (!is_object_selected (view, view_object)) {
1415 object = gl_view_object_get_object (view_object);
1417 gl_label_object_get_position (object, &i_x1, &i_y1);
1418 gl_label_object_get_size (object, &w, &h);
1421 if ((i_x1 >= x1) && (i_x2 <= x2) && (i_y1 >= y1)
1423 select_object_real (view, view_object);
1429 g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1431 gl_debug (DEBUG_VIEW, "END");
1434 /*---------------------------------------------------------------------------*/
1435 /* PRIVATE. Select an object. */
1436 /*---------------------------------------------------------------------------*/
1438 select_object_real (glView *view,
1439 glViewObject *view_object)
1441 gl_debug (DEBUG_VIEW, "START");
1443 g_return_if_fail (GL_IS_VIEW (view));
1444 g_return_if_fail (GL_IS_VIEW_OBJECT (view_object));
1446 if (!is_object_selected (view, view_object)) {
1447 view->selected_object_list =
1448 g_list_prepend (view->selected_object_list, view_object);
1450 gl_view_object_show_highlight (view_object);
1451 gtk_widget_grab_focus (GTK_WIDGET (view->canvas));
1453 gl_debug (DEBUG_VIEW, "END");
1456 /*---------------------------------------------------------------------------*/
1457 /* PRIVATE. Un-select object. */
1458 /*---------------------------------------------------------------------------*/
1460 unselect_object_real (glView *view,
1461 glViewObject *view_object)
1463 gl_debug (DEBUG_VIEW, "START");
1465 g_return_if_fail (GL_IS_VIEW (view));
1466 g_return_if_fail (GL_IS_VIEW_OBJECT (view_object));
1468 gl_view_object_hide_highlight (view_object);
1470 view->selected_object_list =
1471 g_list_remove (view->selected_object_list, view_object);
1473 gl_debug (DEBUG_VIEW, "END");
1476 /*---------------------------------------------------------------------------*/
1477 /* PRIVATE. Return object at (x,y). */
1478 /*---------------------------------------------------------------------------*/
1480 object_at (glView *view,
1484 GnomeCanvasItem *item, *p_item;
1487 gl_debug (DEBUG_VIEW, "");
1489 g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
1491 item = gnome_canvas_get_item_at (GNOME_CANVAS (view->canvas), x, y);
1493 /* No item is at x, y */
1497 /* ignore items not in label group, e.g. background items */
1498 if (!is_item_member_of_group(view, item, GNOME_CANVAS_ITEM(view->label_group)))
1504 /*---------------------------------------------------------------------------*/
1505 /* PRIVATE. Is the item a child (or grandchild, etc.) of group. */
1506 /*---------------------------------------------------------------------------*/
1508 is_item_member_of_group (glView *view,
1509 GnomeCanvasItem *item,
1510 GnomeCanvasItem *group)
1512 GnomeCanvasItem *parent;
1513 GnomeCanvasItem *root_group;
1515 root_group = GNOME_CANVAS_ITEM(gnome_canvas_root (GNOME_CANVAS (view->canvas)));
1517 for ( parent=item->parent; parent && (parent!=root_group); parent=parent->parent) {
1518 if (parent == group) return TRUE;
1523 /*---------------------------------------------------------------------------*/
1524 /* PRIVATE. Is the object in our current selection? */
1525 /*---------------------------------------------------------------------------*/
1527 is_object_selected (glView *view,
1528 glViewObject *view_object)
1530 gl_debug (DEBUG_VIEW, "");
1532 g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
1533 g_return_val_if_fail (GL_IS_VIEW_OBJECT (view_object), FALSE);
1535 if (g_list_find (view->selected_object_list, view_object) == NULL) {
1541 /*****************************************************************************/
1542 /* Is our current selection empty? */
1543 /*****************************************************************************/
1545 gl_view_is_selection_empty (glView *view)
1547 gl_debug (DEBUG_VIEW, "");
1549 g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
1551 if (view->selected_object_list == NULL) {
1558 /*****************************************************************************/
1559 /* Is our current selection atomic? I.e. only one item selected. */
1560 /*****************************************************************************/
1562 gl_view_is_selection_atomic (glView *view)
1564 gl_debug (DEBUG_VIEW, "");
1566 g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
1568 if (view->selected_object_list == NULL)
1570 if (view->selected_object_list->next == NULL)
1575 /*****************************************************************************/
1576 /* Delete selected objects. (Bypass clipboard) */
1577 /*****************************************************************************/
1579 gl_view_delete_selection (glView *view)
1583 gl_debug (DEBUG_VIEW, "START");
1585 g_return_if_fail (GL_IS_VIEW (view));
1587 for (p = view->selected_object_list; p != NULL; p = p_next) {
1589 g_object_unref (G_OBJECT (p->data));
1592 g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1594 gl_debug (DEBUG_VIEW, "END");
1597 /*****************************************************************************/
1598 /* Edit properties of selected object. */
1599 /*****************************************************************************/
1601 gl_view_edit_object_props (glView *view)
1603 glViewObject *view_object;
1605 gl_debug (DEBUG_VIEW, "START");
1607 g_return_if_fail (GL_IS_VIEW (view));
1609 if (gl_view_is_selection_atomic (view)) {
1611 view_object = GL_VIEW_OBJECT(view->selected_object_list->data);
1612 gl_view_object_show_dialog (view_object);
1616 gl_debug (DEBUG_VIEW, "END");
1619 /*****************************************************************************/
1620 /* Raise selected items to top. */
1621 /*****************************************************************************/
1623 gl_view_raise_selection (glView *view)
1626 glViewObject *view_object;
1627 glLabelObject *label_object;
1629 gl_debug (DEBUG_VIEW, "START");
1631 g_return_if_fail (GL_IS_VIEW (view));
1633 for (p = view->selected_object_list; p != NULL; p = p->next) {
1634 view_object = GL_VIEW_OBJECT (p->data);
1635 label_object = gl_view_object_get_object (view_object);
1636 gl_label_object_raise_to_top (label_object);
1639 gl_debug (DEBUG_VIEW, "END");
1642 /*****************************************************************************/
1643 /* Lower selected items to bottom. */
1644 /*****************************************************************************/
1646 gl_view_lower_selection (glView *view)
1649 glViewObject *view_object;
1650 glLabelObject *label_object;
1652 gl_debug (DEBUG_VIEW, "START");
1654 g_return_if_fail (GL_IS_VIEW (view));
1656 for (p = view->selected_object_list; p != NULL; p = p->next) {
1657 view_object = GL_VIEW_OBJECT (p->data);
1658 label_object = gl_view_object_get_object (view_object);
1659 gl_label_object_lower_to_bottom (label_object);
1662 gl_debug (DEBUG_VIEW, "END");
1665 /*****************************************************************************/
1666 /* Flip selected objects horizontally. */
1667 /*****************************************************************************/
1669 gl_view_flip_selection_horiz (glView *view)
1672 glViewObject *view_object;
1673 glLabelObject *label_object;
1675 gl_debug (DEBUG_VIEW, "START");
1677 g_return_if_fail (GL_IS_VIEW (view));
1679 for (p = view->selected_object_list; p != NULL; p = p->next) {
1680 view_object = GL_VIEW_OBJECT (p->data);
1681 label_object = gl_view_object_get_object (view_object);
1682 gl_label_object_flip_horiz (label_object);
1685 gl_debug (DEBUG_VIEW, "END");
1688 /*****************************************************************************/
1689 /* Flip selected objects vertically. */
1690 /*****************************************************************************/
1692 gl_view_flip_selection_vert (glView *view)
1695 glViewObject *view_object;
1696 glLabelObject *label_object;
1698 gl_debug (DEBUG_VIEW, "START");
1700 g_return_if_fail (GL_IS_VIEW (view));
1702 for (p = view->selected_object_list; p != NULL; p = p->next) {
1703 view_object = GL_VIEW_OBJECT (p->data);
1704 label_object = gl_view_object_get_object (view_object);
1705 gl_label_object_flip_vert (label_object);
1708 gl_debug (DEBUG_VIEW, "END");
1711 /*****************************************************************************/
1712 /* "Cut" selected items and place in clipboard selections. */
1713 /*****************************************************************************/
1715 gl_view_cut (glView *view)
1717 gl_debug (DEBUG_VIEW, "START");
1719 g_return_if_fail (GL_IS_VIEW (view));
1721 gl_view_copy (view);
1722 gl_view_delete_selection (view);
1724 gl_debug (DEBUG_VIEW, "END");
1727 /*****************************************************************************/
1728 /* "Copy" selected items to clipboard selections. */
1729 /*****************************************************************************/
1731 gl_view_copy (glView *view)
1734 glViewObject *view_object;
1735 glLabelObject *object;
1736 glTemplate *template;
1737 gboolean rotate_flag;
1739 gl_debug (DEBUG_VIEW, "START");
1741 g_return_if_fail (GL_IS_VIEW (view));
1743 if (view->selected_object_list) {
1745 if ( view->selection_data ) {
1746 g_object_unref (view->selection_data);
1748 template = gl_label_get_template (view->label);
1749 rotate_flag = gl_label_get_rotate_flag (view->label);
1750 view->selection_data = GL_LABEL(gl_label_new ());
1751 gl_label_set_template (view->selection_data, template);
1752 gl_label_set_rotate_flag (view->selection_data, rotate_flag);
1753 gl_template_free (&template);
1755 for (p = view->selected_object_list; p != NULL; p = p->next) {
1757 view_object = GL_VIEW_OBJECT (p->data);
1758 object = gl_view_object_get_object (view_object);
1760 gl_debug (DEBUG_VIEW, "Object copied");
1762 if (GL_IS_LABEL_BOX (object)) {
1763 gl_label_box_dup (GL_LABEL_BOX(object),
1764 view->selection_data);
1765 } else if (GL_IS_LABEL_ELLIPSE (object)) {
1766 gl_label_ellipse_dup (GL_LABEL_ELLIPSE(object),
1767 view->selection_data);
1768 } else if (GL_IS_LABEL_LINE (object)) {
1769 gl_label_line_dup (GL_LABEL_LINE(object),
1770 view->selection_data);
1771 } else if (GL_IS_LABEL_IMAGE (object)) {
1772 gl_label_image_dup (GL_LABEL_IMAGE(object),
1773 view->selection_data);
1774 } else if (GL_IS_LABEL_TEXT (object)) {
1775 gl_label_text_dup (GL_LABEL_TEXT(object),
1776 view->selection_data);
1777 } else if (GL_IS_LABEL_BARCODE (object)) {
1778 gl_label_barcode_dup (GL_LABEL_BARCODE(object),
1779 view->selection_data);
1781 /* Should not happen! */
1782 g_warning ("Invalid label object type.");
1788 gtk_selection_owner_set (view->invisible,
1789 clipboard_atom, GDK_CURRENT_TIME);
1790 view->have_selection = TRUE;
1794 gl_debug (DEBUG_VIEW, "END");
1797 /*****************************************************************************/
1798 /* "Paste" from private clipboard selection. */
1799 /*****************************************************************************/
1801 gl_view_paste (glView *view)
1803 gl_debug (DEBUG_VIEW, "START");
1805 g_return_if_fail (GL_IS_VIEW (view));
1807 gtk_selection_convert (GTK_WIDGET (view->invisible),
1808 clipboard_atom, GDK_SELECTION_TYPE_STRING,
1811 gl_debug (DEBUG_VIEW, "END");
1814 /*---------------------------------------------------------------------------*/
1815 /* PRIVATE. move selected objects */
1816 /*---------------------------------------------------------------------------*/
1818 move_selection (glView *view,
1823 glLabelObject *object;
1825 gl_debug (DEBUG_VIEW, "START");
1827 g_return_if_fail (GL_IS_VIEW (view));
1829 for (p = view->selected_object_list; p != NULL; p = p->next) {
1831 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
1832 gl_label_object_set_position_relative (object, dx, dy);
1836 gl_debug (DEBUG_VIEW, "END");
1839 /*****************************************************************************/
1840 /* Zoom in one "notch" */
1841 /*****************************************************************************/
1843 gl_view_zoom_in (glView *view)
1846 gdouble dist, dist_min;
1848 gl_debug (DEBUG_VIEW, "START");
1850 g_return_if_fail (GL_IS_VIEW (view));
1852 /* Find index of current scale (or best match) */
1853 i_min = 1; /* start with 2nd largest scale */
1854 dist_min = fabs (scales[1] - view->scale);
1855 for (i = 2; i < N_SCALES; i++) {
1856 dist = fabs (scales[i] - view->scale);
1857 if (dist < dist_min) {
1863 /* zoom in one "notch" */
1864 i = MAX (0, i_min - 1);
1865 gl_view_set_zoom (view, scales[i] / HOME_SCALE);
1867 gl_debug (DEBUG_VIEW, "END");
1870 /*****************************************************************************/
1871 /* Zoom out one "notch" */
1872 /*****************************************************************************/
1874 gl_view_zoom_out (glView *view)
1877 gdouble dist, dist_min;
1879 gl_debug (DEBUG_VIEW, "START");
1881 g_return_if_fail (GL_IS_VIEW (view));
1883 /* Find index of current scale (or best match) */
1884 i_min = 0; /* start with largest scale */
1885 dist_min = fabs (scales[0] - view->scale);
1886 for (i = 1; i < N_SCALES; i++) {
1887 dist = fabs (scales[i] - view->scale);
1888 if (dist < dist_min) {
1894 /* zoom out one "notch" */
1895 if (i_min >= N_SCALES)
1900 gl_view_set_zoom (view, scales[i] / HOME_SCALE);
1902 gl_debug (DEBUG_VIEW, "END");
1905 /*****************************************************************************/
1906 /* Set current zoom factor to explicit value. */
1907 /*****************************************************************************/
1909 gl_view_set_zoom (glView *view,
1912 gl_debug (DEBUG_VIEW, "START");
1914 g_return_if_fail (GL_IS_VIEW (view));
1915 g_return_if_fail (scale > 0.0);
1917 view->scale = scale * HOME_SCALE;
1918 gnome_canvas_set_pixels_per_unit (GNOME_CANVAS (view->canvas),
1919 scale * HOME_SCALE);
1921 g_signal_emit (G_OBJECT(view), signals[ZOOM_CHANGED], 0, scale);
1923 gl_debug (DEBUG_VIEW, "END");
1926 /*****************************************************************************/
1927 /* Get current zoom factor. */
1928 /*****************************************************************************/
1930 gl_view_get_zoom (glView *view)
1932 gl_debug (DEBUG_VIEW, "");
1934 g_return_val_if_fail (GL_IS_VIEW (view), 1.0);
1936 return view->scale / HOME_SCALE;
1939 /*****************************************************************************/
1940 /* Is this the maximum zoom level. */
1941 /*****************************************************************************/
1943 gl_view_is_zoom_max (glView *view)
1945 gl_debug (DEBUG_VIEW, "");
1947 g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
1949 return view->scale >= scales[0];
1952 /*****************************************************************************/
1953 /* Is this the minimum zoom level. */
1954 /*****************************************************************************/
1956 gl_view_is_zoom_min (glView *view)
1958 gl_debug (DEBUG_VIEW, "");
1960 g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
1962 return view->scale <= scales[N_SCALES-1];
1965 /*---------------------------------------------------------------------------*/
1966 /* PRIVATE. Canvas event handler. */
1967 /*---------------------------------------------------------------------------*/
1969 canvas_event (GnomeCanvas *canvas,
1975 gl_debug (DEBUG_VIEW, "");
1977 /* emit pointer signals regardless of state */
1978 switch (event->type) {
1979 case GDK_MOTION_NOTIFY:
1980 gl_debug (DEBUG_VIEW, "MOTION_NOTIFY");
1981 gnome_canvas_window_to_world (canvas,
1983 event->motion.y, &x, &y);
1984 g_signal_emit (G_OBJECT(view), signals[POINTER_MOVED], 0, x, y);
1985 break; /* fall through */
1987 case GDK_LEAVE_NOTIFY:
1988 gl_debug (DEBUG_VIEW, "LEAVEW_NOTIFY");
1989 g_signal_emit (G_OBJECT(view), signals[POINTER_EXIT], 0);
1990 break; /* fall through */
1993 break; /* fall through */
1997 switch (view->state) {
1999 case GL_VIEW_STATE_ARROW:
2000 return canvas_event_arrow_mode (canvas, event, view);
2002 case GL_VIEW_STATE_OBJECT_CREATE:
2003 switch (view->create_type) {
2004 case GL_LABEL_OBJECT_BOX:
2005 return gl_view_box_create_event_handler (canvas,
2009 case GL_LABEL_OBJECT_ELLIPSE:
2010 return gl_view_ellipse_create_event_handler (canvas,
2014 case GL_LABEL_OBJECT_LINE:
2015 return gl_view_line_create_event_handler (canvas,
2019 case GL_LABEL_OBJECT_IMAGE:
2020 return gl_view_image_create_event_handler (canvas,
2024 case GL_LABEL_OBJECT_TEXT:
2025 return gl_view_text_create_event_handler (canvas,
2029 case GL_LABEL_OBJECT_BARCODE:
2030 return gl_view_barcode_create_event_handler (canvas,
2035 /*Should not happen!*/
2036 g_warning ("Invalid label object type.");
2041 g_warning ("Invalid view state."); /*Should not happen!*/
2047 /*---------------------------------------------------------------------------*/
2048 /* PRIVATE. Canvas event handler (arrow mode) */
2049 /*---------------------------------------------------------------------------*/
2051 canvas_event_arrow_mode (GnomeCanvas *canvas,
2055 static gdouble x0, y0;
2056 static gboolean dragging = FALSE;
2057 static GnomeCanvasItem *item;
2058 gdouble x, y, x1, y1, x2, y2;
2059 GnomeCanvasGroup *group;
2062 gl_debug (DEBUG_VIEW, "");
2064 switch (event->type) {
2066 case GDK_BUTTON_PRESS:
2067 gl_debug (DEBUG_VIEW, "BUTTON_PRESS");
2068 switch (event->button.button) {
2070 gnome_canvas_window_to_world (canvas,
2072 event->button.y, &x, &y);
2074 if (!object_at (view, x, y)) {
2075 if (!(event->button.state & GDK_CONTROL_MASK)) {
2076 gl_view_unselect_all (view);
2080 gdk_pointer_grab (GTK_WIDGET (view->canvas)->
2082 GDK_POINTER_MOTION_MASK |
2083 GDK_BUTTON_RELEASE_MASK |
2084 GDK_BUTTON_PRESS_MASK, NULL,
2085 NULL, event->button.time);
2087 gnome_canvas_root (GNOME_CANVAS
2090 gnome_canvas_item_new (group,
2091 gnome_canvas_rect_get_type (),
2095 "outline_color_rgba",
2110 case GDK_BUTTON_RELEASE:
2111 gl_debug (DEBUG_VIEW, "BUTTON_RELEASE");
2112 switch (event->button.button) {
2116 gdk_pointer_ungrab (event->button.time);
2117 gnome_canvas_window_to_world (canvas,
2125 gl_view_select_region (view, x1, y1, x2, y2);
2126 gtk_object_destroy (GTK_OBJECT (item));
2135 case GDK_MOTION_NOTIFY:
2136 gl_debug (DEBUG_VIEW, "MOTION_NOTIFY");
2137 gnome_canvas_window_to_world (canvas,
2139 event->motion.y, &x, &y);
2140 if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
2141 gnome_canvas_item_set (item,
2145 "y2", MAX (y, y0), NULL);
2152 gl_debug (DEBUG_VIEW, "KEY_PRESS");
2154 switch (event->key.keyval) {
2157 move_selection (view,
2158 -1.0 / (view->scale), 0.0);
2162 move_selection (view,
2163 0.0, -1.0 / (view->scale));
2167 move_selection (view,
2168 1.0 / (view->scale), 0.0);
2172 move_selection (view,
2173 0.0, 1.0 / (view->scale));
2177 gl_view_delete_selection (view);
2178 cursor = gdk_cursor_new (GDK_LEFT_PTR);
2179 gdk_window_set_cursor (view->canvas->window,
2181 gdk_cursor_unref (cursor);
2187 return TRUE; /* We handled this or we were dragging. */
2190 gl_debug (DEBUG_VIEW, "default");
2196 /*****************************************************************************/
2197 /* Item event handler. */
2198 /*****************************************************************************/
2200 gl_view_item_event_handler (GnomeCanvasItem *item,
2202 glViewObject *view_object)
2206 gl_debug (DEBUG_VIEW, "");
2208 view = gl_view_object_get_view(view_object);
2209 switch (view->state) {
2211 case GL_VIEW_STATE_ARROW:
2212 return item_event_arrow_mode (item, event, view_object);
2221 /*---------------------------------------------------------------------------*/
2222 /* PRIVATE. Item event handler (arrow mode) */
2223 /*---------------------------------------------------------------------------*/
2225 item_event_arrow_mode (GnomeCanvasItem *item,
2227 glViewObject *view_object)
2229 static gdouble x, y;
2230 static gboolean dragging = FALSE;
2233 gdouble item_x, item_y;
2234 gdouble new_x, new_y;
2235 gboolean control_key_pressed;
2237 gl_debug (DEBUG_VIEW, "");
2239 item_x = event->button.x;
2240 item_y = event->button.y;
2241 gnome_canvas_item_w2i (item->parent, &item_x, &item_y);
2243 view = gl_view_object_get_view(view_object);
2245 switch (event->type) {
2247 case GDK_BUTTON_PRESS:
2248 gl_debug (DEBUG_VIEW, "BUTTON_PRESS");
2249 control_key_pressed = event->button.state & GDK_CONTROL_MASK;
2250 switch (event->button.button) {
2252 if (control_key_pressed) {
2253 if (is_object_selected (view, view_object)) {
2254 /* Un-selecting a selected item */
2255 gl_view_unselect_object (view,
2259 /* Add to current selection */
2260 gl_view_select_object (view,
2264 if (!is_object_selected (view, view_object)) {
2265 /* No control, key so remove any selections before adding */
2266 gl_view_unselect_all (view);
2267 /* Add to current selection */
2268 gl_view_select_object (view,
2272 /* Go into dragging mode while button remains pressed. */
2275 cursor = gdk_cursor_new (GDK_FLEUR);
2276 gnome_canvas_item_grab (item,
2277 GDK_POINTER_MOTION_MASK |
2278 GDK_BUTTON_RELEASE_MASK |
2279 GDK_BUTTON_PRESS_MASK,
2280 cursor, event->button.time);
2281 gdk_cursor_unref (cursor);
2286 if (!is_object_selected (view, view_object)) {
2287 if (!control_key_pressed) {
2288 /* No control, key so remove any selections before adding */
2289 gl_view_unselect_all (view);
2292 /* Add to current selection */
2293 gl_view_select_object (view, view_object);
2294 /* bring up apropriate menu for selection. */
2295 popup_selection_menu (view, view_object, event);
2302 case GDK_BUTTON_RELEASE:
2303 gl_debug (DEBUG_VIEW, "BUTTON_RELEASE");
2304 switch (event->button.button) {
2306 /* Exit dragging mode */
2307 gnome_canvas_item_ungrab (item, event->button.time);
2315 case GDK_MOTION_NOTIFY:
2316 gl_debug (DEBUG_VIEW, "MOTION_NOTIFY");
2317 if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
2318 /* Dragging mode, move selection */
2321 move_selection (view, (new_x - x), (new_y - y));
2329 case GDK_2BUTTON_PRESS:
2330 gl_debug (DEBUG_VIEW, "2BUTTON_PRESS");
2331 switch (event->button.button) {
2333 /* Also exit dragging mode w/ double-click, run dlg */
2334 gnome_canvas_item_ungrab (item, event->button.time);
2336 gl_view_select_object (view, view_object);
2337 gl_view_object_show_dialog (view_object);
2344 case GDK_ENTER_NOTIFY:
2345 gl_debug (DEBUG_VIEW, "ENTER_NOTIFY");
2346 cursor = gdk_cursor_new (GDK_FLEUR);
2347 gdk_window_set_cursor (view->canvas->window, cursor);
2348 gdk_cursor_unref (cursor);
2351 case GDK_LEAVE_NOTIFY:
2352 gl_debug (DEBUG_VIEW, "LEAVE_NOTIFY");
2353 cursor = gdk_cursor_new (GDK_LEFT_PTR);
2354 gdk_window_set_cursor (view->canvas->window, cursor);
2355 gdk_cursor_unref (cursor);
2359 gl_debug (DEBUG_VIEW, "default");
2365 /*---------------------------------------------------------------------------*/
2366 /* PRIVATE. create menu for multiple selections. */
2367 /*---------------------------------------------------------------------------*/
2369 new_selection_menu (glView *view)
2371 GtkWidget *menu, *menuitem;
2373 gl_debug (DEBUG_VIEW, "START");
2375 g_return_val_if_fail (GL_IS_VIEW (view), NULL);
2377 menu = gtk_menu_new ();
2379 menuitem = gtk_menu_item_new_with_label (_("Delete"));
2380 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
2381 gtk_widget_show (menuitem);
2382 g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
2383 G_CALLBACK (gl_view_delete_selection), view);
2385 menuitem = gtk_menu_item_new ();
2386 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
2387 gtk_widget_show (menuitem);
2389 menuitem = gtk_menu_item_new_with_label (_("Bring to front"));
2390 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
2391 gtk_widget_show (menuitem);
2392 g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
2393 G_CALLBACK (gl_view_raise_selection), view);
2395 menuitem = gtk_menu_item_new_with_label (_("Send to back"));
2396 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
2397 gtk_widget_show (menuitem);
2398 g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
2399 G_CALLBACK (gl_view_lower_selection), view);
2401 gl_debug (DEBUG_VIEW, "END");
2406 /*---------------------------------------------------------------------------*/
2407 /* PRIVATE. popup menu for given item. */
2408 /*---------------------------------------------------------------------------*/
2410 popup_selection_menu (glView *view,
2411 glViewObject *view_object,
2416 gl_debug (DEBUG_VIEW, "START");
2418 g_return_if_fail (GL_IS_VIEW (view));
2419 g_return_if_fail (GL_IS_VIEW_OBJECT (view_object));
2421 if (gl_view_is_selection_atomic (view)) {
2423 menu = gl_view_object_get_menu (view_object);
2425 gtk_menu_popup (GTK_MENU (menu),
2426 NULL, NULL, NULL, NULL,
2427 event->button.button,
2428 event->button.time);
2433 if (view->menu != NULL) {
2434 gtk_menu_popup (GTK_MENU (view->menu),
2435 NULL, NULL, NULL, NULL,
2436 event->button.button,
2437 event->button.time);
2442 gl_debug (DEBUG_VIEW, "END");
2445 /*---------------------------------------------------------------------------*/
2446 /* PRIVATE. Handle "selection-clear" signal. */
2447 /*---------------------------------------------------------------------------*/
2449 selection_clear_cb (GtkWidget *widget,
2450 GdkEventSelection *event,
2453 glView *view = GL_VIEW (data);
2455 gl_debug (DEBUG_VIEW, "START");
2457 g_return_if_fail (GL_IS_VIEW (view));
2459 view->have_selection = FALSE;
2460 g_object_unref (view->selection_data);
2461 view->selection_data = NULL;
2463 gl_debug (DEBUG_VIEW, "END");
2466 /*---------------------------------------------------------------------------*/
2467 /* PRIVATE. Handle "selection-get" signal. */
2468 /*---------------------------------------------------------------------------*/
2470 selection_get_cb (GtkWidget *widget,
2471 GtkSelectionData *selection_data,
2476 glView *view = GL_VIEW (data);
2478 glXMLLabelStatus status;
2480 gl_debug (DEBUG_VIEW, "START");
2482 g_return_if_fail (GL_IS_VIEW (view));
2484 if (view->have_selection) {
2486 buffer = gl_xml_label_save_buffer (view->selection_data,
2488 gtk_selection_data_set (selection_data,
2489 GDK_SELECTION_TYPE_STRING, 8, buffer,
2494 gl_debug (DEBUG_VIEW, "END");
2497 /*---------------------------------------------------------------------------*/
2498 /* PRIVATE. Handle "selection-received" signal. (Result of Paste) */
2499 /*---------------------------------------------------------------------------*/
2501 selection_received_cb (GtkWidget *widget,
2502 GtkSelectionData *selection_data,
2506 glView *view = GL_VIEW (data);
2507 glLabel *label = NULL;
2508 glXMLLabelStatus status;
2510 glLabelObject *object, *newobject;
2511 glViewObject *view_object;
2513 gl_debug (DEBUG_VIEW, "START");
2515 g_return_if_fail (GL_IS_VIEW (view));
2517 if (selection_data->length < 0) {
2520 if (selection_data->type != GDK_SELECTION_TYPE_STRING) {
2524 gl_view_unselect_all (view);
2526 label = gl_xml_label_open_buffer (selection_data->data, &status);
2527 for (p = label->objects; p != NULL; p = p_next) {
2530 object = (glLabelObject *) p->data;
2531 gl_label_object_set_parent (object, view->label);
2533 gl_debug (DEBUG_VIEW, "object pasted");
2535 if (GL_IS_LABEL_BOX (object)) {
2536 view_object = gl_view_box_new (GL_LABEL_BOX(object),
2538 } else if (GL_IS_LABEL_ELLIPSE (object)) {
2539 view_object = gl_view_ellipse_new (GL_LABEL_ELLIPSE(object),
2541 } else if (GL_IS_LABEL_LINE (object)) {
2542 view_object = gl_view_line_new (GL_LABEL_LINE(object),
2544 } else if (GL_IS_LABEL_IMAGE (object)) {
2545 view_object = gl_view_image_new (GL_LABEL_IMAGE(object),
2547 } else if (GL_IS_LABEL_TEXT (object)) {
2548 view_object = gl_view_text_new (GL_LABEL_TEXT(object),
2550 } else if (GL_IS_LABEL_BARCODE (object)) {
2551 view_object = gl_view_barcode_new (GL_LABEL_BARCODE(object),
2554 /* Should not happen! */
2556 g_warning ("Invalid label object type.");
2558 gl_view_select_object (view, view_object);
2560 g_object_unref (label);
2562 gl_debug (DEBUG_VIEW, "END");