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 SEL_LINE_COLOR GL_COLOR_A (0, 0, 255, 128)
50 #define SEL_FILL_COLOR GL_COLOR_A (192, 192, 255, 128)
53 /*==========================================================================*/
55 /*==========================================================================*/
67 /*==========================================================================*/
69 /*==========================================================================*/
71 static GtkContainerClass *parent_class;
73 static guint signals[LAST_SIGNAL] = {0};
75 /* "CLIPBOARD" selection */
76 static GdkAtom clipboard_atom = GDK_NONE;
78 static gdouble scales[] = {
83 #define N_SCALES G_N_ELEMENTS(scales)
84 #define HOME_SCALE 2.0
86 /*==========================================================================*/
87 /* Local function prototypes */
88 /*==========================================================================*/
90 static void gl_view_class_init (glViewClass *class);
91 static void gl_view_init (glView *view);
92 static void gl_view_finalize (GObject *object);
94 static void gl_view_construct (glView *view);
95 static GtkWidget *gl_view_construct_canvas (glView *view);
96 static void gl_view_construct_selection (glView *view);
98 static gdouble get_apropriate_scale (gdouble w, gdouble h);
100 static void draw_bg_fg (glView *view);
101 static void draw_bg_fg_rect (glView *view);
102 static void draw_bg_fg_rounded_rect (glView *view);
103 static void draw_bg_fg_round (glView *view);
104 static void draw_bg_fg_cd (glView *view);
106 static void draw_markup (glView *view);
108 static void draw_markup_margin (glView *view,
109 glTemplateMarkupMargin *margin);
110 static void draw_markup_margin_rect (glView *view,
111 glTemplateMarkupMargin *margin);
112 static void draw_markup_margin_rounded_rect (glView *view,
113 glTemplateMarkupMargin *margin);
114 static void draw_markup_margin_round (glView *view,
115 glTemplateMarkupMargin *margin);
116 static void draw_markup_margin_cd (glView *view,
117 glTemplateMarkupMargin *margin);
120 static void select_object_real (glView *view,
121 glViewObject *view_object);
122 static void unselect_object_real (glView *view,
123 glViewObject *view_object);
125 static gboolean object_at (glView *view,
126 gdouble x, gdouble y);
127 static gboolean is_object_selected (glView *view,
128 glViewObject *view_object);
130 static void move_selection (glView *view,
131 gdouble dx, gdouble dy);
133 static int canvas_event (GnomeCanvas *canvas,
136 static int canvas_event_arrow_mode (GnomeCanvas *canvas,
140 static int item_event_arrow_mode (GnomeCanvasItem *item,
142 glViewObject *view_object);
144 static GtkWidget *new_selection_menu (glView *view);
146 static void popup_selection_menu (glView *view,
147 glViewObject *view_object,
150 static void selection_clear_cb (GtkWidget *widget,
151 GdkEventSelection *event,
154 static void selection_get_cb (GtkWidget *widget,
155 GtkSelectionData *selection_data,
160 static void selection_received_cb (GtkWidget *widget,
161 GtkSelectionData *selection_data,
165 /****************************************************************************/
166 /* Boilerplate Object stuff. */
167 /****************************************************************************/
169 gl_view_get_type (void)
171 static guint view_type = 0;
174 GTypeInfo view_info = {
175 sizeof (glViewClass),
178 (GClassInitFunc) gl_view_class_init,
183 (GInstanceInitFunc) gl_view_init,
187 g_type_register_static (gtk_vbox_get_type (),
188 "glView", &view_info, 0);
195 gl_view_class_init (glViewClass *class)
197 GObjectClass *object_class = (GObjectClass *) class;
199 gl_debug (DEBUG_VIEW, "START");
201 parent_class = g_type_class_peek_parent (class);
203 object_class->finalize = gl_view_finalize;
205 signals[SELECTION_CHANGED] =
206 g_signal_new ("selection_changed",
207 G_OBJECT_CLASS_TYPE (object_class),
209 G_STRUCT_OFFSET (glViewClass, selection_changed),
211 gl_marshal_VOID__VOID,
215 signals[ZOOM_CHANGED] =
216 g_signal_new ("zoom_changed",
217 G_OBJECT_CLASS_TYPE (object_class),
219 G_STRUCT_OFFSET (glViewClass, zoom_changed),
221 gl_marshal_VOID__DOUBLE,
225 signals[POINTER_MOVED] =
226 g_signal_new ("pointer_moved",
227 G_OBJECT_CLASS_TYPE (object_class),
229 G_STRUCT_OFFSET (glViewClass, pointer_moved),
231 gl_marshal_VOID__DOUBLE_DOUBLE,
233 2, G_TYPE_DOUBLE, G_TYPE_DOUBLE);
235 signals[POINTER_EXIT] =
236 g_signal_new ("pointer_exit",
237 G_OBJECT_CLASS_TYPE (object_class),
239 G_STRUCT_OFFSET (glViewClass, pointer_exit),
241 gl_marshal_VOID__VOID,
245 signals[MODE_CHANGED] =
246 g_signal_new ("mode_changed",
247 G_OBJECT_CLASS_TYPE (object_class),
249 G_STRUCT_OFFSET (glViewClass, mode_changed),
251 gl_marshal_VOID__VOID,
255 gl_debug (DEBUG_VIEW, "END");
259 gl_view_init (glView *view)
261 gl_debug (DEBUG_VIEW, "START");
265 gl_debug (DEBUG_VIEW, "END");
269 gl_view_finalize (GObject *object)
273 gl_debug (DEBUG_VIEW, "START");
275 g_return_if_fail (object != NULL);
276 g_return_if_fail (GL_IS_VIEW (object));
278 view = GL_VIEW (object);
280 G_OBJECT_CLASS (parent_class)->finalize (object);
282 gl_debug (DEBUG_VIEW, "END");
285 /****************************************************************************/
286 /* NEW view object. */
287 /****************************************************************************/
289 gl_view_new (glLabel *label)
291 glView *view = g_object_new (gl_view_get_type (), NULL);
293 gl_debug (DEBUG_VIEW, "START");
297 gl_view_construct (view);
299 gl_debug (DEBUG_VIEW, "END");
301 return GTK_WIDGET (view);
304 /*---------------------------------------------------------------------------*/
305 /* PRIVATE. Construct composite widget. */
306 /*---------------------------------------------------------------------------*/
308 gl_view_construct (glView *view)
310 GtkWidget *wvbox, *wscroll;
312 gl_debug (DEBUG_VIEW, "START");
314 g_return_if_fail (GL_IS_VIEW (view));
316 wvbox = GTK_WIDGET (view);
318 view->state = GL_VIEW_STATE_ARROW;
319 view->object_list = NULL;
321 gl_view_construct_canvas (view);
322 wscroll = gtk_scrolled_window_new (NULL, NULL);
323 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (wscroll),
324 GTK_POLICY_AUTOMATIC,
325 GTK_POLICY_AUTOMATIC);
326 gtk_box_pack_start (GTK_BOX (wvbox), wscroll, TRUE, TRUE, 0);
327 gtk_container_add (GTK_CONTAINER (wscroll), view->canvas);
329 gl_view_construct_selection (view);
331 view->menu = new_selection_menu (view);
333 gl_debug (DEBUG_VIEW, "END");
336 /*---------------------------------------------------------------------------*/
337 /* PRIVATE. Create canvas w/ a background in the shape of the label/card. */
338 /*---------------------------------------------------------------------------*/
340 gl_view_construct_canvas (glView *view)
343 glLabel *label = view->label;
344 gdouble label_width, label_height;
346 glLabelObject *object;
347 glViewObject *view_object;
349 gl_debug (DEBUG_VIEW, "START");
351 g_return_val_if_fail (GL_IS_VIEW (view), NULL);
352 g_return_val_if_fail (label != NULL, NULL);
354 gtk_widget_push_colormap (gdk_rgb_get_colormap ());
355 view->canvas = gnome_canvas_new_aa ();
356 gtk_widget_pop_colormap ();
358 gl_label_get_size (label, &label_width, &label_height);
359 gl_debug (DEBUG_VIEW, "Label size: w=%lf, h=%lf",
360 label_width, label_height);
362 scale = get_apropriate_scale (label_width, label_height);
363 gl_debug (DEBUG_VIEW, "scale =%lf", scale);
365 gl_debug (DEBUG_VIEW, "Canvas size: w=%lf, h=%lf",
366 scale * label_width + 40,
367 scale * label_height + 40);
368 gtk_widget_set_size_request (GTK_WIDGET(view->canvas),
369 scale * label_width + 40,
370 scale * label_height + 40);
371 gnome_canvas_set_pixels_per_unit (GNOME_CANVAS (view->canvas),
375 gnome_canvas_set_scroll_region (GNOME_CANVAS (view->canvas),
376 0.0, 0.0, label_width, label_height);
378 /* Draw background shape of label/card */
380 gl_debug (DEBUG_VIEW, "n_bg_items = %d, n_fg_items = %d",
381 view->n_bg_items, view->n_fg_items);
383 g_signal_connect (G_OBJECT (view->canvas), "event",
384 G_CALLBACK (canvas_event), view);
386 for (p_obj = label->objects; p_obj != NULL; p_obj = p_obj->next) {
387 object = (glLabelObject *) p_obj->data;
389 if (GL_IS_LABEL_BOX (object)) {
390 view_object = gl_view_box_new (GL_LABEL_BOX(object),
392 } else if (GL_IS_LABEL_ELLIPSE (object)) {
393 view_object = gl_view_ellipse_new (GL_LABEL_ELLIPSE(object),
395 } else if (GL_IS_LABEL_LINE (object)) {
396 view_object = gl_view_line_new (GL_LABEL_LINE(object),
398 } else if (GL_IS_LABEL_IMAGE (object)) {
399 view_object = gl_view_image_new (GL_LABEL_IMAGE(object),
401 } else if (GL_IS_LABEL_TEXT (object)) {
402 view_object = gl_view_text_new (GL_LABEL_TEXT(object),
404 } else if (GL_IS_LABEL_BARCODE (object)) {
405 view_object = gl_view_barcode_new (GL_LABEL_BARCODE(object),
408 /* Should not happen! */
410 g_warning ("Invalid label object type.");
414 gl_debug (DEBUG_VIEW, "END");
419 /*---------------------------------------------------------------------------*/
420 /* PRIVATE. Create clipboard selection targets. */
421 /*---------------------------------------------------------------------------*/
423 gl_view_construct_selection (glView *view)
425 gl_debug (DEBUG_VIEW, "START");
427 g_return_if_fail (GL_IS_VIEW (view));
429 view->have_selection = FALSE;
430 view->selection_data = NULL;
431 view->invisible = gtk_invisible_new ();
433 view->selected_object_list = NULL;
435 if (!clipboard_atom) {
436 clipboard_atom = gdk_atom_intern ("GLABELS_CLIPBOARD", FALSE);
439 gtk_selection_add_target (view->invisible,
440 clipboard_atom, GDK_SELECTION_TYPE_STRING, 1);
442 g_signal_connect (G_OBJECT (view->invisible),
443 "selection_clear_event",
444 G_CALLBACK (selection_clear_cb), view);
446 g_signal_connect (G_OBJECT (view->invisible), "selection_get",
447 G_CALLBACK (selection_get_cb), view);
449 g_signal_connect (G_OBJECT (view->invisible),
450 "selection_received",
451 G_CALLBACK (selection_received_cb), view);
453 gl_debug (DEBUG_VIEW, "END");
456 /*---------------------------------------------------------------------------*/
457 /* PRIVATE. Determine an apropriate scale for given label & screen size */
458 /*---------------------------------------------------------------------------*/
460 get_apropriate_scale (gdouble w, gdouble h)
462 gdouble w_screen, h_screen;
466 gl_debug (DEBUG_VIEW, "");
468 w_screen = (gdouble) gdk_screen_width ();
469 h_screen = (gdouble) gdk_screen_height ();
471 for (i = 0; i < N_SCALES; i++) {
473 if (k <= HOME_SCALE) {
474 if ((k * w < (w_screen - 256))
475 && (k * h < (h_screen - 256)))
483 /*---------------------------------------------------------------------------*/
484 /* PRIVATE. Draw background and foreground outlines. */
485 /*---------------------------------------------------------------------------*/
487 draw_bg_fg (glView *view)
490 glTemplate *template;
492 view->n_bg_items = 0;
493 view->bg_item_list = NULL;
494 view->n_fg_items = 0;
495 view->fg_item_list = NULL;
498 template = gl_label_get_template (label);
500 switch (template->label.style) {
502 case GL_TEMPLATE_STYLE_RECT:
503 if (template->label.rect.r == 0.0) {
504 /* Square corners. */
505 draw_bg_fg_rect (view);
507 /* Rounded corners. */
508 draw_bg_fg_rounded_rect (view);
512 case GL_TEMPLATE_STYLE_ROUND:
513 draw_bg_fg_round (view);
516 case GL_TEMPLATE_STYLE_CD:
517 draw_bg_fg_cd (view);
521 g_warning ("Unknown template label style");
526 /*---------------------------------------------------------------------------*/
527 /* PRIVATE. Draw simple recangular background. */
528 /*---------------------------------------------------------------------------*/
530 draw_bg_fg_rect (glView *view)
532 glLabel *label = view->label;
533 glTemplate *template;
535 GnomeCanvasItem *item;
536 GnomeCanvasGroup *group;
538 gl_debug (DEBUG_VIEW, "START");
540 g_return_if_fail (GL_IS_VIEW (view));
541 g_return_if_fail (label != NULL);
543 gl_label_get_size (label, &w, &h);
544 template = gl_label_get_template (label);
546 group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
549 item = gnome_canvas_item_new (group,
550 gnome_canvas_rect_get_type (),
555 "fill_color", "white",
558 view->bg_item_list = g_list_append (view->bg_item_list, item);
564 item = gnome_canvas_item_new (group,
565 gnome_canvas_rect_get_type (),
571 "outline_color", "light blue",
574 view->fg_item_list = g_list_append (view->fg_item_list, item);
576 gl_debug (DEBUG_VIEW, "END");
579 /*---------------------------------------------------------------------------*/
580 /* PRIVATE. Draw rounded recangular background. */
581 /*---------------------------------------------------------------------------*/
583 draw_bg_fg_rounded_rect (glView *view)
585 glLabel *label = view->label;
586 GnomeCanvasPoints *points;
587 gint i_coords, i_theta;
588 glTemplate *template;
590 GnomeCanvasItem *item;
591 GnomeCanvasGroup *group;
593 gl_debug (DEBUG_VIEW, "START");
595 g_return_if_fail (GL_IS_VIEW (view));
596 g_return_if_fail (label != NULL);
598 group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
600 gl_label_get_size (label, &w, &h);
601 template = gl_label_get_template (label);
602 r = template->label.rect.r;
604 points = gnome_canvas_points_new (4 * (1 + 90 / 5));
606 for (i_theta = 0; i_theta <= 90; i_theta += 5) {
607 points->coords[i_coords++] =
608 r - r * sin (i_theta * M_PI / 180.0);
609 points->coords[i_coords++] =
610 r - r * cos (i_theta * M_PI / 180.0);
612 for (i_theta = 0; i_theta <= 90; i_theta += 5) {
613 points->coords[i_coords++] =
614 r - r * cos (i_theta * M_PI / 180.0);
615 points->coords[i_coords++] =
616 (h - r) + r * sin (i_theta * M_PI / 180.0);
618 for (i_theta = 0; i_theta <= 90; i_theta += 5) {
619 points->coords[i_coords++] =
620 (w - r) + r * sin (i_theta * M_PI / 180.0);
621 points->coords[i_coords++] =
622 (h - r) + r * cos (i_theta * M_PI / 180.0);
624 for (i_theta = 0; i_theta <= 90; i_theta += 5) {
625 points->coords[i_coords++] =
626 (w - r) + r * cos (i_theta * M_PI / 180.0);
627 points->coords[i_coords++] =
628 r - r * sin (i_theta * M_PI / 180.0);
632 item = gnome_canvas_item_new (group,
633 gnome_canvas_polygon_get_type (),
635 "fill_color", "white",
638 view->bg_item_list = g_list_append (view->bg_item_list, item);
644 item = gnome_canvas_item_new (group,
645 gnome_canvas_polygon_get_type (),
648 "outline_color", "light blue",
651 view->fg_item_list = g_list_append (view->fg_item_list, item);
653 gnome_canvas_points_free (points);
655 gl_debug (DEBUG_VIEW, "END");
658 /*---------------------------------------------------------------------------*/
659 /* PRIVATE. Draw round background. */
660 /*---------------------------------------------------------------------------*/
662 draw_bg_fg_round (glView *view)
664 glLabel *label = view->label;
665 glTemplate *template;
667 GnomeCanvasItem *item;
668 GnomeCanvasGroup *group;
670 gl_debug (DEBUG_VIEW, "START");
672 g_return_if_fail (GL_IS_VIEW (view));
673 g_return_if_fail (label != NULL);
675 template = gl_label_get_template (label);
677 group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
679 r = template->label.round.r;
682 item = gnome_canvas_item_new (group,
683 gnome_canvas_ellipse_get_type (),
688 "fill_color", "white",
691 view->bg_item_list = g_list_append (view->bg_item_list, item);
697 item = gnome_canvas_item_new (group,
698 gnome_canvas_ellipse_get_type (),
704 "outline_color", "light blue",
707 view->fg_item_list = g_list_append (view->fg_item_list, item);
709 gl_debug (DEBUG_VIEW, "END");
712 /*---------------------------------------------------------------------------*/
713 /* PRIVATE. Draw CD style background, circular w/ concentric hole. */
714 /*---------------------------------------------------------------------------*/
716 draw_bg_fg_cd (glView *view)
718 glLabel *label = view->label;
719 glTemplate *template;
721 GnomeCanvasItem *item;
722 GnomeCanvasGroup *group;
724 gl_debug (DEBUG_VIEW, "START");
726 g_return_if_fail (GL_IS_VIEW (view));
727 g_return_if_fail (label != NULL);
729 template = gl_label_get_template (label);
731 group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
733 r1 = template->label.cd.r1;
734 r2 = template->label.cd.r2;
738 item = gnome_canvas_item_new (group,
739 gnome_canvas_ellipse_get_type (),
744 "fill_color", "white",
747 view->bg_item_list = g_list_append (view->bg_item_list, item);
749 item = gnome_canvas_item_new (group,
750 gnome_canvas_ellipse_get_type (),
755 "fill_color", "gray",
758 view->bg_item_list = g_list_append (view->bg_item_list, item);
765 item = gnome_canvas_item_new (group,
766 gnome_canvas_ellipse_get_type (),
772 "outline_color", "light blue",
775 view->fg_item_list = g_list_append (view->fg_item_list, item);
777 item = gnome_canvas_item_new (group,
778 gnome_canvas_ellipse_get_type (),
784 "outline_color", "light blue",
787 view->fg_item_list = g_list_append (view->fg_item_list, item);
789 gl_debug (DEBUG_VIEW, "END");
792 /*---------------------------------------------------------------------------*/
793 /* PRIVATE. Draw markup lines. */
794 /*---------------------------------------------------------------------------*/
796 draw_markup (glView *view)
799 glTemplate *template;
801 glTemplateMarkup *markup;
804 template = gl_label_get_template (label);
806 for ( p=template->label.any.markups; p != NULL; p=p->next ) {
807 markup = (glTemplateMarkup *)p->data;
809 switch (markup->type) {
810 case GL_TEMPLATE_MARKUP_MARGIN:
811 draw_markup_margin (view,
812 (glTemplateMarkupMargin *)markup);
815 g_warning ("Unknown template markup type");
821 /*---------------------------------------------------------------------------*/
822 /* PRIVATE. Draw margin markup. */
823 /*---------------------------------------------------------------------------*/
825 draw_markup_margin (glView *view,
826 glTemplateMarkupMargin *margin)
829 glTemplate *template;
832 template = gl_label_get_template (label);
834 switch (template->label.style) {
836 case GL_TEMPLATE_STYLE_RECT:
837 if (template->label.rect.r == 0.0) {
838 /* Square corners. */
839 draw_markup_margin_rect (view, margin);
841 if ( margin->size < template->label.rect.r) {
842 /* Rounded corners. */
843 draw_markup_margin_rounded_rect (view, margin);
845 /* Square corners. */
846 draw_markup_margin_rect (view, margin);
851 case GL_TEMPLATE_STYLE_ROUND:
852 draw_markup_margin_round (view, margin);
855 case GL_TEMPLATE_STYLE_CD:
856 draw_markup_margin_cd (view, margin);
860 g_warning ("Unknown template label style");
865 /*---------------------------------------------------------------------------*/
866 /* PRIVATE. Draw simple recangular margin. */
867 /*---------------------------------------------------------------------------*/
869 draw_markup_margin_rect (glView *view,
870 glTemplateMarkupMargin *margin)
872 glLabel *label = view->label;
873 glTemplate *template;
875 GnomeCanvasItem *item;
876 GnomeCanvasGroup *group;
878 gl_debug (DEBUG_VIEW, "START");
880 g_return_if_fail (GL_IS_VIEW (view));
881 g_return_if_fail (label != NULL);
883 gl_label_get_size (label, &w, &h);
884 template = gl_label_get_template (label);
887 group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
889 /* Bounding box @ margin */
890 gnome_canvas_item_new (group,
891 gnome_canvas_rect_get_type (),
897 "outline_color", "light blue",
900 view->bg_item_list = g_list_append (view->bg_item_list, item);
902 gl_debug (DEBUG_VIEW, "END");
905 /*---------------------------------------------------------------------------*/
906 /* PRIVATE. Draw rounded recangular markup. */
907 /*---------------------------------------------------------------------------*/
909 draw_markup_margin_rounded_rect (glView *view,
910 glTemplateMarkupMargin *margin)
912 glLabel *label = view->label;
913 GnomeCanvasPoints *points;
914 gint i_coords, i_theta;
915 glTemplate *template;
917 GnomeCanvasItem *item;
918 GnomeCanvasGroup *group;
920 gl_debug (DEBUG_VIEW, "START");
922 g_return_if_fail (GL_IS_VIEW (view));
923 g_return_if_fail (label != NULL);
925 group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
927 gl_label_get_size (label, &w, &h);
928 template = gl_label_get_template (label);
929 r = template->label.rect.r;
936 /* rectangle with rounded corners */
937 points = gnome_canvas_points_new (4 * (1 + 90 / 5));
939 for (i_theta = 0; i_theta <= 90; i_theta += 5) {
940 points->coords[i_coords++] =
941 m + r - r * sin (i_theta * M_PI / 180.0);
942 points->coords[i_coords++] =
943 m + r - r * cos (i_theta * M_PI / 180.0);
945 for (i_theta = 0; i_theta <= 90; i_theta += 5) {
946 points->coords[i_coords++] =
947 m + r - r * cos (i_theta * M_PI / 180.0);
948 points->coords[i_coords++] =
949 m + (h - r) + r * sin (i_theta * M_PI / 180.0);
951 for (i_theta = 0; i_theta <= 90; i_theta += 5) {
952 points->coords[i_coords++] =
953 m + (w - r) + r * sin (i_theta * M_PI / 180.0);
954 points->coords[i_coords++] =
955 m + (h - r) + r * cos (i_theta * M_PI / 180.0);
957 for (i_theta = 0; i_theta <= 90; i_theta += 5) {
958 points->coords[i_coords++] =
959 m + (w - r) + r * cos (i_theta * M_PI / 180.0);
960 points->coords[i_coords++] =
961 m + r - r * sin (i_theta * M_PI / 180.0);
963 item = gnome_canvas_item_new (group,
964 gnome_canvas_polygon_get_type (),
967 "outline_color", "light blue",
969 gnome_canvas_points_free (points);
971 view->bg_item_list = g_list_append (view->bg_item_list, item);
973 gl_debug (DEBUG_VIEW, "END");
976 /*---------------------------------------------------------------------------*/
977 /* PRIVATE. Draw round margin. */
978 /*---------------------------------------------------------------------------*/
980 draw_markup_margin_round (glView *view,
981 glTemplateMarkupMargin *margin)
983 glLabel *label = view->label;
984 glTemplate *template;
986 GnomeCanvasItem *item;
987 GnomeCanvasGroup *group;
989 gl_debug (DEBUG_VIEW, "START");
991 g_return_if_fail (GL_IS_VIEW (view));
992 g_return_if_fail (label != NULL);
994 template = gl_label_get_template (label);
996 group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
998 r = template->label.round.r;
1001 /* Margin outline */
1002 item = gnome_canvas_item_new (group,
1003 gnome_canvas_ellipse_get_type (),
1009 "outline_color", "light blue", NULL);
1011 view->bg_item_list = g_list_append (view->bg_item_list, item);
1013 gl_debug (DEBUG_VIEW, "END");
1016 /*---------------------------------------------------------------------------*/
1017 /* PRIVATE. Draw CD margins. */
1018 /*---------------------------------------------------------------------------*/
1020 draw_markup_margin_cd (glView *view,
1021 glTemplateMarkupMargin *margin)
1023 glLabel *label = view->label;
1024 glTemplate *template;
1026 GnomeCanvasItem *item;
1027 GnomeCanvasGroup *group;
1029 gl_debug (DEBUG_VIEW, "START");
1031 g_return_if_fail (GL_IS_VIEW (view));
1032 g_return_if_fail (label != NULL);
1034 template = gl_label_get_template (label);
1036 group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
1038 r1 = template->label.cd.r1;
1039 r2 = template->label.cd.r2;
1043 item = gnome_canvas_item_new (group,
1044 gnome_canvas_ellipse_get_type (),
1050 "outline_color", "light blue", NULL);
1052 view->bg_item_list = g_list_append (view->bg_item_list, item);
1054 item = gnome_canvas_item_new (group,
1055 gnome_canvas_ellipse_get_type (),
1061 "outline_color", "light blue",
1064 view->bg_item_list = g_list_append (view->bg_item_list, item);
1066 gl_debug (DEBUG_VIEW, "END");
1069 /*****************************************************************************/
1070 /* Raise foreground items to top. */
1071 /*****************************************************************************/
1073 gl_view_raise_fg (glView *view)
1077 for (p = view->fg_item_list; p != NULL; p = p->next) {
1078 gnome_canvas_item_raise_to_top (GNOME_CANVAS_ITEM(p->data));
1082 /*****************************************************************************/
1083 /* Set arrow mode. */
1084 /*****************************************************************************/
1086 gl_view_arrow_mode (glView *view)
1088 static GdkCursor *cursor = NULL;
1090 gl_debug (DEBUG_VIEW, "START");
1092 g_return_if_fail (GL_IS_VIEW (view));
1095 cursor = gdk_cursor_new (GDK_LEFT_PTR);
1098 gdk_window_set_cursor (view->canvas->window, cursor);
1100 view->state = GL_VIEW_STATE_ARROW;
1102 gl_debug (DEBUG_VIEW, "END");
1105 /*****************************************************************************/
1106 /* Set create text object mode. */
1107 /*****************************************************************************/
1109 gl_view_object_create_mode (glView *view,
1110 glLabelObjectType type)
1114 gl_debug (DEBUG_VIEW, "START");
1116 g_return_if_fail (GL_IS_VIEW (view));
1119 case GL_LABEL_OBJECT_BOX:
1120 cursor = gl_view_box_get_create_cursor ();
1122 case GL_LABEL_OBJECT_ELLIPSE:
1123 cursor = gl_view_ellipse_get_create_cursor ();
1125 case GL_LABEL_OBJECT_LINE:
1126 cursor = gl_view_line_get_create_cursor ();
1128 case GL_LABEL_OBJECT_IMAGE:
1129 cursor = gl_view_image_get_create_cursor ();
1131 case GL_LABEL_OBJECT_TEXT:
1132 cursor = gl_view_text_get_create_cursor ();
1134 case GL_LABEL_OBJECT_BARCODE:
1135 cursor = gl_view_barcode_get_create_cursor ();
1138 g_warning ("Invalid label object type.");/*Should not happen!*/
1142 gdk_window_set_cursor (view->canvas->window, cursor);
1144 view->state = GL_VIEW_STATE_OBJECT_CREATE;
1145 view->create_type = type;
1147 gl_debug (DEBUG_VIEW, "END");
1150 /*****************************************************************************/
1151 /* Select given object (adding to current selection). */
1152 /*****************************************************************************/
1154 gl_view_select_object (glView *view,
1155 glViewObject *view_object)
1157 gl_debug (DEBUG_VIEW, "START");
1159 select_object_real (view, view_object);
1161 g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1163 gl_debug (DEBUG_VIEW, "END");
1166 /*****************************************************************************/
1167 /* Unselect given object (removing from current selection). */
1168 /*****************************************************************************/
1170 gl_view_unselect_object (glView *view,
1171 glViewObject *view_object)
1173 gl_debug (DEBUG_VIEW, "START");
1175 unselect_object_real (view, view_object);
1177 g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1179 gl_debug (DEBUG_VIEW, "END");
1182 /*****************************************************************************/
1183 /* Select all items. */
1184 /*****************************************************************************/
1186 gl_view_select_all (glView *view)
1190 gl_debug (DEBUG_VIEW, "START");
1192 g_return_if_fail (GL_IS_VIEW (view));
1194 /* 1st unselect anything already selected. */
1195 for (p = view->selected_object_list; p != NULL; p = p_next) {
1197 unselect_object_real (view, GL_VIEW_OBJECT (p->data));
1200 /* Finally select all objects. */
1201 for (p = view->object_list; p != NULL; p = p->next) {
1202 select_object_real (view, GL_VIEW_OBJECT (p->data));
1205 g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1207 gl_debug (DEBUG_VIEW, "END");
1210 /*****************************************************************************/
1211 /* Remove all selections */
1212 /*****************************************************************************/
1214 gl_view_unselect_all (glView *view)
1218 gl_debug (DEBUG_VIEW, "START");
1220 g_return_if_fail (GL_IS_VIEW (view));
1222 for (p = view->selected_object_list; p != NULL; p = p_next) {
1224 unselect_object_real (view, GL_VIEW_OBJECT (p->data));
1227 g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1229 gl_debug (DEBUG_VIEW, "END");
1232 /*****************************************************************************/
1233 /* Select all objects within given rectangular region (adding to selection). */
1234 /*****************************************************************************/
1236 gl_view_select_region (glView *view,
1243 glViewObject *view_object;
1244 glLabelObject *object;
1245 gdouble i_x1, i_y1, i_x2, i_y2, w, h;
1247 gl_debug (DEBUG_VIEW, "START");
1249 g_return_if_fail (GL_IS_VIEW (view));
1250 g_return_if_fail ((x1 <= x2) && (y1 <= y2));
1252 for (p = view->object_list; p != NULL; p = p->next) {
1253 view_object = GL_VIEW_OBJECT(p->data);
1254 if (!is_object_selected (view, view_object)) {
1256 object = gl_view_object_get_object (view_object);
1258 gl_label_object_get_position (object, &i_x1, &i_y1);
1259 gl_label_object_get_size (object, &w, &h);
1262 if ((i_x1 >= x1) && (i_x2 <= x2) && (i_y1 >= y1)
1264 select_object_real (view, view_object);
1270 g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1272 gl_debug (DEBUG_VIEW, "END");
1275 /*---------------------------------------------------------------------------*/
1276 /* PRIVATE. Select an object. */
1277 /*---------------------------------------------------------------------------*/
1279 select_object_real (glView *view,
1280 glViewObject *view_object)
1282 gl_debug (DEBUG_VIEW, "START");
1284 g_return_if_fail (GL_IS_VIEW (view));
1285 g_return_if_fail (GL_IS_VIEW_OBJECT (view_object));
1287 if (!is_object_selected (view, view_object)) {
1288 view->selected_object_list =
1289 g_list_prepend (view->selected_object_list, view_object);
1291 gl_view_object_show_highlight (view_object);
1292 gtk_widget_grab_focus (GTK_WIDGET (view->canvas));
1294 gl_debug (DEBUG_VIEW, "END");
1297 /*---------------------------------------------------------------------------*/
1298 /* PRIVATE. Un-select object. */
1299 /*---------------------------------------------------------------------------*/
1301 unselect_object_real (glView *view,
1302 glViewObject *view_object)
1304 gl_debug (DEBUG_VIEW, "START");
1306 g_return_if_fail (GL_IS_VIEW (view));
1307 g_return_if_fail (GL_IS_VIEW_OBJECT (view_object));
1309 gl_view_object_hide_highlight (view_object);
1311 view->selected_object_list =
1312 g_list_remove (view->selected_object_list, view_object);
1314 gl_debug (DEBUG_VIEW, "END");
1317 /*---------------------------------------------------------------------------*/
1318 /* PRIVATE. Return object at (x,y). */
1319 /*---------------------------------------------------------------------------*/
1321 object_at (glView *view,
1325 GnomeCanvasItem *item, *p_item;
1328 gl_debug (DEBUG_VIEW, "");
1330 g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
1332 item = gnome_canvas_get_item_at (GNOME_CANVAS (view->canvas), x, y);
1334 /* No item is at x, y */
1338 /* ignore our background items */
1339 if (g_list_find (view->bg_item_list, item) != NULL)
1345 /*---------------------------------------------------------------------------*/
1346 /* PRIVATE. Is the object in our current selection? */
1347 /*---------------------------------------------------------------------------*/
1349 is_object_selected (glView *view,
1350 glViewObject *view_object)
1352 gl_debug (DEBUG_VIEW, "");
1354 g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
1355 g_return_val_if_fail (GL_IS_VIEW_OBJECT (view_object), FALSE);
1357 if (g_list_find (view->selected_object_list, view_object) == NULL) {
1363 /*****************************************************************************/
1364 /* Is our current selection empty? */
1365 /*****************************************************************************/
1367 gl_view_is_selection_empty (glView *view)
1369 gl_debug (DEBUG_VIEW, "");
1371 g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
1373 if (view->selected_object_list == NULL) {
1380 /*****************************************************************************/
1381 /* Is our current selection atomic? I.e. only one item selected. */
1382 /*****************************************************************************/
1384 gl_view_is_selection_atomic (glView *view)
1386 gl_debug (DEBUG_VIEW, "");
1388 g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
1390 if (view->selected_object_list == NULL)
1392 if (view->selected_object_list->next == NULL)
1397 /*****************************************************************************/
1398 /* Delete selected objects. (Bypass clipboard) */
1399 /*****************************************************************************/
1401 gl_view_delete_selection (glView *view)
1405 gl_debug (DEBUG_VIEW, "START");
1407 g_return_if_fail (GL_IS_VIEW (view));
1409 for (p = view->selected_object_list; p != NULL; p = p_next) {
1411 g_object_unref (G_OBJECT (p->data));
1414 g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1416 gl_debug (DEBUG_VIEW, "END");
1419 /*****************************************************************************/
1420 /* Edit properties of selected object. */
1421 /*****************************************************************************/
1423 gl_view_edit_object_props (glView *view)
1425 glViewObject *view_object;
1427 gl_debug (DEBUG_VIEW, "START");
1429 g_return_if_fail (GL_IS_VIEW (view));
1431 if (gl_view_is_selection_atomic (view)) {
1433 view_object = GL_VIEW_OBJECT(view->selected_object_list->data);
1434 gl_view_object_show_dialog (view_object);
1438 gl_debug (DEBUG_VIEW, "END");
1441 /*****************************************************************************/
1442 /* Raise selected items to top. */
1443 /*****************************************************************************/
1445 gl_view_raise_selection (glView *view)
1448 glViewObject *view_object;
1449 glLabelObject *label_object;
1451 gl_debug (DEBUG_VIEW, "START");
1453 g_return_if_fail (GL_IS_VIEW (view));
1455 for (p = view->selected_object_list; p != NULL; p = p->next) {
1456 view_object = GL_VIEW_OBJECT (p->data);
1457 label_object = gl_view_object_get_object (view_object);
1458 gl_label_object_raise_to_top (label_object);
1461 gl_debug (DEBUG_VIEW, "END");
1464 /*****************************************************************************/
1465 /* Lower selected items to bottom. */
1466 /*****************************************************************************/
1468 gl_view_lower_selection (glView *view)
1471 glViewObject *view_object;
1472 glLabelObject *label_object;
1474 gl_debug (DEBUG_VIEW, "START");
1476 g_return_if_fail (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 label_object = gl_view_object_get_object (view_object);
1481 gl_label_object_lower_to_bottom (label_object);
1484 gl_debug (DEBUG_VIEW, "END");
1487 /*****************************************************************************/
1488 /* "Cut" selected items and place in clipboard selections. */
1489 /*****************************************************************************/
1491 gl_view_cut (glView *view)
1493 gl_debug (DEBUG_VIEW, "START");
1495 g_return_if_fail (GL_IS_VIEW (view));
1497 gl_view_copy (view);
1498 gl_view_delete_selection (view);
1500 gl_debug (DEBUG_VIEW, "END");
1503 /*****************************************************************************/
1504 /* "Copy" selected items to clipboard selections. */
1505 /*****************************************************************************/
1507 gl_view_copy (glView *view)
1510 glViewObject *view_object;
1511 glLabelObject *object;
1512 glTemplate *template;
1513 gboolean rotate_flag;
1515 gl_debug (DEBUG_VIEW, "START");
1517 g_return_if_fail (GL_IS_VIEW (view));
1519 if (view->selected_object_list) {
1521 if ( view->selection_data ) {
1522 g_object_unref (view->selection_data);
1524 template = gl_label_get_template (view->label);
1525 rotate_flag = gl_label_get_rotate_flag (view->label);
1526 view->selection_data = GL_LABEL(gl_label_new ());
1527 gl_label_set_template (view->selection_data, template);
1528 gl_label_set_rotate_flag (view->selection_data, rotate_flag);
1529 gl_template_free (&template);
1531 for (p = view->selected_object_list; p != NULL; p = p->next) {
1533 view_object = GL_VIEW_OBJECT (p->data);
1534 object = gl_view_object_get_object (view_object);
1536 gl_debug (DEBUG_VIEW, "Object copied");
1538 if (GL_IS_LABEL_BOX (object)) {
1539 gl_label_box_dup (GL_LABEL_BOX(object),
1540 view->selection_data);
1541 } else if (GL_IS_LABEL_ELLIPSE (object)) {
1542 gl_label_ellipse_dup (GL_LABEL_ELLIPSE(object),
1543 view->selection_data);
1544 } else if (GL_IS_LABEL_LINE (object)) {
1545 gl_label_line_dup (GL_LABEL_LINE(object),
1546 view->selection_data);
1547 } else if (GL_IS_LABEL_IMAGE (object)) {
1548 gl_label_image_dup (GL_LABEL_IMAGE(object),
1549 view->selection_data);
1550 } else if (GL_IS_LABEL_TEXT (object)) {
1551 gl_label_text_dup (GL_LABEL_TEXT(object),
1552 view->selection_data);
1553 } else if (GL_IS_LABEL_BARCODE (object)) {
1554 gl_label_barcode_dup (GL_LABEL_BARCODE(object),
1555 view->selection_data);
1557 /* Should not happen! */
1558 g_warning ("Invalid label object type.");
1564 gtk_selection_owner_set (view->invisible,
1565 clipboard_atom, GDK_CURRENT_TIME);
1566 view->have_selection = TRUE;
1570 gl_debug (DEBUG_VIEW, "END");
1573 /*****************************************************************************/
1574 /* "Paste" from private clipboard selection. */
1575 /*****************************************************************************/
1577 gl_view_paste (glView *view)
1579 gl_debug (DEBUG_VIEW, "START");
1581 g_return_if_fail (GL_IS_VIEW (view));
1583 gtk_selection_convert (GTK_WIDGET (view->invisible),
1584 clipboard_atom, GDK_SELECTION_TYPE_STRING,
1587 gl_debug (DEBUG_VIEW, "END");
1590 /*---------------------------------------------------------------------------*/
1591 /* PRIVATE. move selected objects */
1592 /*---------------------------------------------------------------------------*/
1594 move_selection (glView *view,
1599 glLabelObject *object;
1601 gl_debug (DEBUG_VIEW, "START");
1603 g_return_if_fail (GL_IS_VIEW (view));
1605 for (p = view->selected_object_list; p != NULL; p = p->next) {
1607 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
1608 gl_label_object_set_position_relative (object, dx, dy);
1612 gl_debug (DEBUG_VIEW, "END");
1615 /*****************************************************************************/
1616 /* Zoom in one "notch" */
1617 /*****************************************************************************/
1619 gl_view_zoom_in (glView *view)
1622 gdouble dist, dist_min;
1624 gl_debug (DEBUG_VIEW, "START");
1626 g_return_if_fail (GL_IS_VIEW (view));
1628 /* Find index of current scale (or best match) */
1629 i_min = 1; /* start with 2nd largest scale */
1630 dist_min = fabs (scales[1] - view->scale);
1631 for (i = 2; i < N_SCALES; i++) {
1632 dist = fabs (scales[i] - view->scale);
1633 if (dist < dist_min) {
1639 /* zoom in one "notch" */
1640 i = MAX (0, i_min - 1);
1641 gl_view_set_zoom (view, scales[i] / HOME_SCALE);
1643 gl_debug (DEBUG_VIEW, "END");
1646 /*****************************************************************************/
1647 /* Zoom out one "notch" */
1648 /*****************************************************************************/
1650 gl_view_zoom_out (glView *view)
1653 gdouble dist, dist_min;
1655 gl_debug (DEBUG_VIEW, "START");
1657 g_return_if_fail (GL_IS_VIEW (view));
1659 /* Find index of current scale (or best match) */
1660 i_min = 0; /* start with largest scale */
1661 dist_min = fabs (scales[0] - view->scale);
1662 for (i = 1; i < N_SCALES; i++) {
1663 dist = fabs (scales[i] - view->scale);
1664 if (dist < dist_min) {
1670 /* zoom out one "notch" */
1671 if (i_min >= N_SCALES)
1676 gl_view_set_zoom (view, scales[i] / HOME_SCALE);
1678 gl_debug (DEBUG_VIEW, "END");
1681 /*****************************************************************************/
1682 /* Set current zoom factor to explicit value. */
1683 /*****************************************************************************/
1685 gl_view_set_zoom (glView *view,
1688 gl_debug (DEBUG_VIEW, "START");
1690 g_return_if_fail (GL_IS_VIEW (view));
1691 g_return_if_fail (scale > 0.0);
1693 view->scale = scale * HOME_SCALE;
1694 gnome_canvas_set_pixels_per_unit (GNOME_CANVAS (view->canvas),
1695 scale * HOME_SCALE);
1697 g_signal_emit (G_OBJECT(view), signals[ZOOM_CHANGED], 0, scale);
1699 gl_debug (DEBUG_VIEW, "END");
1702 /*****************************************************************************/
1703 /* Get current zoom factor. */
1704 /*****************************************************************************/
1706 gl_view_get_zoom (glView *view)
1708 gl_debug (DEBUG_VIEW, "");
1710 g_return_val_if_fail (GL_IS_VIEW (view), 1.0);
1712 return view->scale / HOME_SCALE;
1715 /*****************************************************************************/
1716 /* Is this the maximum zoom level. */
1717 /*****************************************************************************/
1719 gl_view_is_zoom_max (glView *view)
1721 gl_debug (DEBUG_VIEW, "");
1723 g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
1725 return view->scale >= scales[0];
1728 /*****************************************************************************/
1729 /* Is this the minimum zoom level. */
1730 /*****************************************************************************/
1732 gl_view_is_zoom_min (glView *view)
1734 gl_debug (DEBUG_VIEW, "");
1736 g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
1738 return view->scale <= scales[N_SCALES-1];
1741 /*---------------------------------------------------------------------------*/
1742 /* PRIVATE. Canvas event handler. */
1743 /*---------------------------------------------------------------------------*/
1745 canvas_event (GnomeCanvas *canvas,
1749 gl_debug (DEBUG_VIEW, "");
1751 switch (view->state) {
1753 case GL_VIEW_STATE_ARROW:
1754 return canvas_event_arrow_mode (canvas, event, view);
1756 case GL_VIEW_STATE_OBJECT_CREATE:
1757 switch (view->create_type) {
1758 case GL_LABEL_OBJECT_BOX:
1759 return gl_view_box_create_event_handler (canvas,
1763 case GL_LABEL_OBJECT_ELLIPSE:
1764 return gl_view_ellipse_create_event_handler (canvas,
1768 case GL_LABEL_OBJECT_LINE:
1769 return gl_view_line_create_event_handler (canvas,
1773 case GL_LABEL_OBJECT_IMAGE:
1774 return gl_view_image_create_event_handler (canvas,
1778 case GL_LABEL_OBJECT_TEXT:
1779 return gl_view_text_create_event_handler (canvas,
1783 case GL_LABEL_OBJECT_BARCODE:
1784 return gl_view_barcode_create_event_handler (canvas,
1789 /*Should not happen!*/
1790 g_warning ("Invalid label object type.");
1795 g_warning ("Invalid view state."); /*Should not happen!*/
1801 /*---------------------------------------------------------------------------*/
1802 /* PRIVATE. Canvas event handler (arrow mode) */
1803 /*---------------------------------------------------------------------------*/
1805 canvas_event_arrow_mode (GnomeCanvas *canvas,
1809 static gdouble x0, y0;
1810 static gboolean dragging = FALSE;
1811 static GnomeCanvasItem *item;
1812 gdouble x, y, x1, y1, x2, y2;
1813 GnomeCanvasGroup *group;
1816 gl_debug (DEBUG_VIEW, "");
1818 switch (event->type) {
1820 case GDK_BUTTON_PRESS:
1821 gl_debug (DEBUG_VIEW, "BUTTON_PRESS");
1822 switch (event->button.button) {
1824 gnome_canvas_window_to_world (canvas,
1826 event->button.y, &x, &y);
1828 if (!object_at (view, x, y)) {
1829 if (!(event->button.state & GDK_CONTROL_MASK)) {
1830 gl_view_unselect_all (view);
1834 gdk_pointer_grab (GTK_WIDGET (view->canvas)->
1836 GDK_POINTER_MOTION_MASK |
1837 GDK_BUTTON_RELEASE_MASK |
1838 GDK_BUTTON_PRESS_MASK, NULL,
1839 NULL, event->button.time);
1841 gnome_canvas_root (GNOME_CANVAS
1844 gnome_canvas_item_new (group,
1845 gnome_canvas_rect_get_type (),
1849 "outline_color_rgba",
1864 case GDK_BUTTON_RELEASE:
1865 gl_debug (DEBUG_VIEW, "BUTTON_RELEASE");
1866 switch (event->button.button) {
1870 gdk_pointer_ungrab (event->button.time);
1871 gnome_canvas_window_to_world (canvas,
1879 gl_view_select_region (view, x1, y1, x2, y2);
1880 gtk_object_destroy (GTK_OBJECT (item));
1889 case GDK_MOTION_NOTIFY:
1890 gl_debug (DEBUG_VIEW, "MOTION_NOTIFY");
1891 gnome_canvas_window_to_world (canvas,
1893 event->motion.y, &x, &y);
1894 g_signal_emit (G_OBJECT(view), signals[POINTER_MOVED], 0, x, y);
1895 if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
1896 gnome_canvas_item_set (item,
1900 "y2", MAX (y, y0), NULL);
1906 case GDK_LEAVE_NOTIFY:
1907 gl_debug (DEBUG_VIEW, "LEAVEW_NOTIFY");
1908 g_signal_emit (G_OBJECT(view), signals[POINTER_EXIT], 0);
1912 gl_debug (DEBUG_VIEW, "KEY_PRESS");
1914 switch (event->key.keyval) {
1917 move_selection (view,
1918 -1.0 / (view->scale), 0.0);
1922 move_selection (view,
1923 0.0, -1.0 / (view->scale));
1927 move_selection (view,
1928 1.0 / (view->scale), 0.0);
1932 move_selection (view,
1933 0.0, 1.0 / (view->scale));
1937 gl_view_delete_selection (view);
1938 cursor = gdk_cursor_new (GDK_LEFT_PTR);
1939 gdk_window_set_cursor (view->canvas->window,
1941 gdk_cursor_unref (cursor);
1947 return TRUE; /* We handled this or we were dragging. */
1950 gl_debug (DEBUG_VIEW, "default");
1956 /*****************************************************************************/
1957 /* Item event handler. */
1958 /*****************************************************************************/
1960 gl_view_item_event_handler (GnomeCanvasItem *item,
1962 glViewObject *view_object)
1966 gl_debug (DEBUG_VIEW, "");
1968 view = gl_view_object_get_view(view_object);
1969 switch (view->state) {
1971 case GL_VIEW_STATE_ARROW:
1972 return item_event_arrow_mode (item, event, view_object);
1981 /*---------------------------------------------------------------------------*/
1982 /* PRIVATE. Item event handler (arrow mode) */
1983 /*---------------------------------------------------------------------------*/
1985 item_event_arrow_mode (GnomeCanvasItem *item,
1987 glViewObject *view_object)
1989 static gdouble x, y;
1990 static gboolean dragging = FALSE;
1993 gdouble item_x, item_y;
1994 gdouble new_x, new_y;
1995 gboolean control_key_pressed;
1997 gl_debug (DEBUG_VIEW, "");
1999 item_x = event->button.x;
2000 item_y = event->button.y;
2001 gnome_canvas_item_w2i (item->parent, &item_x, &item_y);
2003 view = gl_view_object_get_view(view_object);
2005 switch (event->type) {
2007 case GDK_BUTTON_PRESS:
2008 gl_debug (DEBUG_VIEW, "BUTTON_PRESS");
2009 control_key_pressed = event->button.state & GDK_CONTROL_MASK;
2010 switch (event->button.button) {
2012 if (control_key_pressed) {
2013 if (is_object_selected (view, view_object)) {
2014 /* Un-selecting a selected item */
2015 gl_view_unselect_object (view,
2019 /* Add to current selection */
2020 gl_view_select_object (view,
2024 if (!is_object_selected (view, view_object)) {
2025 /* No control, key so remove any selections before adding */
2026 gl_view_unselect_all (view);
2027 /* Add to current selection */
2028 gl_view_select_object (view,
2032 /* Go into dragging mode while button remains pressed. */
2035 cursor = gdk_cursor_new (GDK_FLEUR);
2036 gnome_canvas_item_grab (item,
2037 GDK_POINTER_MOTION_MASK |
2038 GDK_BUTTON_RELEASE_MASK |
2039 GDK_BUTTON_PRESS_MASK,
2040 cursor, event->button.time);
2041 gdk_cursor_unref (cursor);
2046 if (!is_object_selected (view, view_object)) {
2047 if (!control_key_pressed) {
2048 /* No control, key so remove any selections before adding */
2049 gl_view_unselect_all (view);
2052 /* Add to current selection */
2053 gl_view_select_object (view, view_object);
2054 /* bring up apropriate menu for selection. */
2055 popup_selection_menu (view, view_object, event);
2062 case GDK_BUTTON_RELEASE:
2063 gl_debug (DEBUG_VIEW, "BUTTON_RELEASE");
2064 switch (event->button.button) {
2066 /* Exit dragging mode */
2067 gnome_canvas_item_ungrab (item, event->button.time);
2075 case GDK_MOTION_NOTIFY:
2076 gl_debug (DEBUG_VIEW, "MOTION_NOTIFY");
2077 if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
2078 /* Dragging mode, move selection */
2081 move_selection (view, (new_x - x), (new_y - y));
2089 case GDK_2BUTTON_PRESS:
2090 gl_debug (DEBUG_VIEW, "2BUTTON_PRESS");
2091 switch (event->button.button) {
2093 /* Also exit dragging mode w/ double-click, run dlg */
2094 gnome_canvas_item_ungrab (item, event->button.time);
2096 gl_view_select_object (view, view_object);
2097 gl_view_object_show_dialog (view_object);
2104 case GDK_ENTER_NOTIFY:
2105 gl_debug (DEBUG_VIEW, "ENTER_NOTIFY");
2106 cursor = gdk_cursor_new (GDK_FLEUR);
2107 gdk_window_set_cursor (view->canvas->window, cursor);
2108 gdk_cursor_unref (cursor);
2111 case GDK_LEAVE_NOTIFY:
2112 gl_debug (DEBUG_VIEW, "LEAVE_NOTIFY");
2113 cursor = gdk_cursor_new (GDK_LEFT_PTR);
2114 gdk_window_set_cursor (view->canvas->window, cursor);
2115 gdk_cursor_unref (cursor);
2119 gl_debug (DEBUG_VIEW, "default");
2125 /*---------------------------------------------------------------------------*/
2126 /* PRIVATE. create menu for multiple selections. */
2127 /*---------------------------------------------------------------------------*/
2129 new_selection_menu (glView *view)
2131 GtkWidget *menu, *menuitem;
2133 gl_debug (DEBUG_VIEW, "START");
2135 g_return_val_if_fail (GL_IS_VIEW (view), NULL);
2137 menu = gtk_menu_new ();
2139 menuitem = gtk_menu_item_new_with_label (_("Delete"));
2140 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
2141 gtk_widget_show (menuitem);
2142 g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
2143 G_CALLBACK (gl_view_delete_selection), view);
2145 menuitem = gtk_menu_item_new ();
2146 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
2147 gtk_widget_show (menuitem);
2149 menuitem = gtk_menu_item_new_with_label (_("Bring to front"));
2150 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
2151 gtk_widget_show (menuitem);
2152 g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
2153 G_CALLBACK (gl_view_raise_selection), view);
2155 menuitem = gtk_menu_item_new_with_label (_("Send to back"));
2156 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
2157 gtk_widget_show (menuitem);
2158 g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
2159 G_CALLBACK (gl_view_lower_selection), view);
2161 gl_debug (DEBUG_VIEW, "END");
2166 /*---------------------------------------------------------------------------*/
2167 /* PRIVATE. popup menu for given item. */
2168 /*---------------------------------------------------------------------------*/
2170 popup_selection_menu (glView *view,
2171 glViewObject *view_object,
2176 gl_debug (DEBUG_VIEW, "START");
2178 g_return_if_fail (GL_IS_VIEW (view));
2179 g_return_if_fail (GL_IS_VIEW_OBJECT (view_object));
2181 if (gl_view_is_selection_atomic (view)) {
2183 menu = gl_view_object_get_menu (view_object);
2185 gtk_menu_popup (GTK_MENU (menu),
2186 NULL, NULL, NULL, NULL,
2187 event->button.button,
2188 event->button.time);
2193 if (view->menu != NULL) {
2194 gtk_menu_popup (GTK_MENU (view->menu),
2195 NULL, NULL, NULL, NULL,
2196 event->button.button,
2197 event->button.time);
2202 gl_debug (DEBUG_VIEW, "END");
2205 /*---------------------------------------------------------------------------*/
2206 /* PRIVATE. Handle "selection-clear" signal. */
2207 /*---------------------------------------------------------------------------*/
2209 selection_clear_cb (GtkWidget *widget,
2210 GdkEventSelection *event,
2213 glView *view = GL_VIEW (data);
2215 gl_debug (DEBUG_VIEW, "START");
2217 g_return_if_fail (GL_IS_VIEW (view));
2219 view->have_selection = FALSE;
2220 g_object_unref (view->selection_data);
2221 view->selection_data = NULL;
2223 gl_debug (DEBUG_VIEW, "END");
2226 /*---------------------------------------------------------------------------*/
2227 /* PRIVATE. Handle "selection-get" signal. */
2228 /*---------------------------------------------------------------------------*/
2230 selection_get_cb (GtkWidget *widget,
2231 GtkSelectionData *selection_data,
2236 glView *view = GL_VIEW (data);
2238 glXMLLabelStatus status;
2240 gl_debug (DEBUG_VIEW, "START");
2242 g_return_if_fail (GL_IS_VIEW (view));
2244 if (view->have_selection) {
2246 buffer = gl_xml_label_save_buffer (view->selection_data,
2248 gtk_selection_data_set (selection_data,
2249 GDK_SELECTION_TYPE_STRING, 8, buffer,
2254 gl_debug (DEBUG_VIEW, "END");
2257 /*---------------------------------------------------------------------------*/
2258 /* PRIVATE. Handle "selection-received" signal. (Result of Paste) */
2259 /*---------------------------------------------------------------------------*/
2261 selection_received_cb (GtkWidget *widget,
2262 GtkSelectionData *selection_data,
2266 glView *view = GL_VIEW (data);
2267 glLabel *label = NULL;
2268 glXMLLabelStatus status;
2270 glLabelObject *object, *newobject;
2271 glViewObject *view_object;
2273 gl_debug (DEBUG_VIEW, "START");
2275 g_return_if_fail (GL_IS_VIEW (view));
2277 if (selection_data->length < 0) {
2280 if (selection_data->type != GDK_SELECTION_TYPE_STRING) {
2284 gl_view_unselect_all (view);
2286 label = gl_xml_label_open_buffer (selection_data->data, &status);
2287 for (p = label->objects; p != NULL; p = p_next) {
2290 object = (glLabelObject *) p->data;
2291 gl_label_object_set_parent (object, view->label);
2293 gl_debug (DEBUG_VIEW, "object pasted");
2295 if (GL_IS_LABEL_BOX (object)) {
2296 view_object = gl_view_box_new (GL_LABEL_BOX(object),
2298 } else if (GL_IS_LABEL_ELLIPSE (object)) {
2299 view_object = gl_view_ellipse_new (GL_LABEL_ELLIPSE(object),
2301 } else if (GL_IS_LABEL_LINE (object)) {
2302 view_object = gl_view_line_new (GL_LABEL_LINE(object),
2304 } else if (GL_IS_LABEL_IMAGE (object)) {
2305 view_object = gl_view_image_new (GL_LABEL_IMAGE(object),
2307 } else if (GL_IS_LABEL_TEXT (object)) {
2308 view_object = gl_view_text_new (GL_LABEL_TEXT(object),
2310 } else if (GL_IS_LABEL_BARCODE (object)) {
2311 view_object = gl_view_barcode_new (GL_LABEL_BARCODE(object),
2314 /* Should not happen! */
2316 g_warning ("Invalid label object type.");
2318 gl_view_select_object (view, view_object);
2320 g_object_unref (label);
2322 gl_debug (DEBUG_VIEW, "END");