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)
52 /*========================================================*/
54 /*========================================================*/
61 /*===========================================*/
63 /*===========================================*/
65 static GtkContainerClass *parent_class;
67 static guint signals[LAST_SIGNAL] = {0};
69 /* "CLIPBOARD" selection */
70 static GdkAtom clipboard_atom = GDK_NONE;
72 #define HOME_SCALE 2.0
73 static gdouble scales[] = {
80 /*===========================================*/
81 /* Local function prototypes */
82 /*===========================================*/
84 static void gl_view_class_init (glViewClass *class);
85 static void gl_view_init (glView *view);
86 static void gl_view_finalize (GObject *object);
88 static void gl_view_construct (glView *view);
89 static GtkWidget *gl_view_construct_canvas (glView *view);
90 static void gl_view_construct_selection (glView *view);
92 static gdouble get_apropriate_scale (gdouble w, gdouble h);
94 static void draw_bg_fg (glView *view);
95 static void draw_bg_fg_rect (glView *view);
96 static void draw_bg_fg_rounded_rect (glView *view);
97 static void draw_bg_fg_round (glView *view);
98 static void draw_bg_fg_cd (glView *view);
100 static void draw_markup (glView *view);
102 static void draw_markup_margin (glView *view,
103 glTemplateMarkupMargin *margin);
104 static void draw_markup_margin_rect (glView *view,
105 glTemplateMarkupMargin *margin);
106 static void draw_markup_margin_rounded_rect (glView *view,
107 glTemplateMarkupMargin *margin);
108 static void draw_markup_margin_round (glView *view,
109 glTemplateMarkupMargin *margin);
110 static void draw_markup_margin_cd (glView *view,
111 glTemplateMarkupMargin *margin);
114 static void select_object_real (glView *view,
115 glViewObject *view_object);
116 static void unselect_object_real (glView *view,
117 glViewObject *view_object);
119 static gboolean object_at (glView *view,
120 gdouble x, gdouble y);
121 static gboolean is_object_selected (glView *view,
122 glViewObject *view_object);
124 static void move_selection (glView *view,
125 gdouble dx, gdouble dy);
127 static int canvas_event (GnomeCanvas *canvas,
130 static int canvas_event_arrow_mode (GnomeCanvas *canvas,
134 static int item_event_arrow_mode (GnomeCanvasItem *item,
136 glViewObject *view_object);
138 static GtkWidget *new_selection_menu (glView *view);
140 static void popup_selection_menu (glView *view,
141 glViewObject *view_object,
144 static void selection_clear_cb (GtkWidget *widget,
145 GdkEventSelection *event,
148 static void selection_get_cb (GtkWidget *widget,
149 GtkSelectionData *selection_data,
154 static void selection_received_cb (GtkWidget *widget,
155 GtkSelectionData *selection_data,
159 /****************************************************************************/
160 /* Boilerplate Object stuff. */
161 /****************************************************************************/
163 gl_view_get_type (void)
165 static guint view_type = 0;
168 GTypeInfo view_info = {
169 sizeof (glViewClass),
172 (GClassInitFunc) gl_view_class_init,
177 (GInstanceInitFunc) gl_view_init,
181 g_type_register_static (gtk_vbox_get_type (),
182 "glView", &view_info, 0);
189 gl_view_class_init (glViewClass *class)
191 GObjectClass *object_class = (GObjectClass *) class;
193 gl_debug (DEBUG_VIEW, "START");
195 parent_class = g_type_class_peek_parent (class);
197 object_class->finalize = gl_view_finalize;
199 signals[SELECTION_CHANGED] =
200 g_signal_new ("selection_changed",
201 G_OBJECT_CLASS_TYPE (object_class),
203 G_STRUCT_OFFSET (glViewClass, selection_changed),
205 gl_marshal_VOID__VOID,
209 gl_debug (DEBUG_VIEW, "END");
213 gl_view_init (glView *view)
215 gl_debug (DEBUG_VIEW, "START");
219 gl_debug (DEBUG_VIEW, "END");
223 gl_view_finalize (GObject *object)
227 gl_debug (DEBUG_VIEW, "START");
229 g_return_if_fail (object != NULL);
230 g_return_if_fail (GL_IS_VIEW (object));
232 view = GL_VIEW (object);
234 G_OBJECT_CLASS (parent_class)->finalize (object);
236 gl_debug (DEBUG_VIEW, "END");
239 /****************************************************************************/
240 /* NEW view object. */
241 /****************************************************************************/
243 gl_view_new (glLabel *label)
245 glView *view = g_object_new (gl_view_get_type (), NULL);
247 gl_debug (DEBUG_VIEW, "START");
251 gl_view_construct (view);
253 gl_debug (DEBUG_VIEW, "END");
255 return GTK_WIDGET (view);
258 /*---------------------------------------------------------------------------*/
259 /* PRIVATE. Construct composite widget. */
260 /*---------------------------------------------------------------------------*/
262 gl_view_construct (glView *view)
264 GtkWidget *wvbox, *wscroll;
266 gl_debug (DEBUG_VIEW, "START");
268 g_return_if_fail (GL_IS_VIEW (view));
270 wvbox = GTK_WIDGET (view);
272 view->state = GL_VIEW_STATE_ARROW;
273 view->object_list = NULL;
275 gl_view_construct_canvas (view);
276 wscroll = gtk_scrolled_window_new (NULL, NULL);
277 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (wscroll),
278 GTK_POLICY_AUTOMATIC,
279 GTK_POLICY_AUTOMATIC);
280 gtk_box_pack_start (GTK_BOX (wvbox), wscroll, TRUE, TRUE, 0);
281 gtk_container_add (GTK_CONTAINER (wscroll), view->canvas);
283 gl_view_construct_selection (view);
285 view->menu = new_selection_menu (view);
287 gl_debug (DEBUG_VIEW, "END");
290 /*---------------------------------------------------------------------------*/
291 /* PRIVATE. Create canvas w/ a background in the shape of the label/card. */
292 /*---------------------------------------------------------------------------*/
294 gl_view_construct_canvas (glView *view)
297 glLabel *label = view->label;
298 gdouble label_width, label_height;
300 glLabelObject *object;
301 glViewObject *view_object;
303 gl_debug (DEBUG_VIEW, "START");
305 g_return_val_if_fail (GL_IS_VIEW (view), NULL);
306 g_return_val_if_fail (label != NULL, NULL);
308 gtk_widget_push_colormap (gdk_rgb_get_colormap ());
309 view->canvas = gnome_canvas_new_aa ();
310 gtk_widget_pop_colormap ();
312 gl_label_get_size (label, &label_width, &label_height);
313 gl_debug (DEBUG_VIEW, "Label size: w=%lf, h=%lf",
314 label_width, label_height);
316 scale = get_apropriate_scale (label_width, label_height);
317 gl_debug (DEBUG_VIEW, "scale =%lf", scale);
319 gl_debug (DEBUG_VIEW, "Canvas size: w=%lf, h=%lf",
320 scale * label_width + 40,
321 scale * label_height + 40);
322 gtk_widget_set_size_request (GTK_WIDGET(view->canvas),
323 scale * label_width + 40,
324 scale * label_height + 40);
325 gnome_canvas_set_pixels_per_unit (GNOME_CANVAS (view->canvas),
329 gnome_canvas_set_scroll_region (GNOME_CANVAS (view->canvas),
330 0.0, 0.0, label_width, label_height);
332 /* Draw background shape of label/card */
334 gl_debug (DEBUG_VIEW, "n_bg_items = %d, n_fg_items = %d",
335 view->n_bg_items, view->n_fg_items);
337 g_signal_connect (G_OBJECT (view->canvas), "event",
338 G_CALLBACK (canvas_event), view);
340 for (p_obj = label->objects; p_obj != NULL; p_obj = p_obj->next) {
341 object = (glLabelObject *) p_obj->data;
343 if (GL_IS_LABEL_BOX (object)) {
344 view_object = gl_view_box_new (GL_LABEL_BOX(object),
346 } else if (GL_IS_LABEL_ELLIPSE (object)) {
347 view_object = gl_view_ellipse_new (GL_LABEL_ELLIPSE(object),
349 } else if (GL_IS_LABEL_LINE (object)) {
350 view_object = gl_view_line_new (GL_LABEL_LINE(object),
352 } else if (GL_IS_LABEL_IMAGE (object)) {
353 view_object = gl_view_image_new (GL_LABEL_IMAGE(object),
355 } else if (GL_IS_LABEL_TEXT (object)) {
356 view_object = gl_view_text_new (GL_LABEL_TEXT(object),
358 } else if (GL_IS_LABEL_BARCODE (object)) {
359 view_object = gl_view_barcode_new (GL_LABEL_BARCODE(object),
362 /* Should not happen! */
364 g_warning ("Invalid label object type.");
368 gl_debug (DEBUG_VIEW, "END");
373 /*---------------------------------------------------------------------------*/
374 /* PRIVATE. Create clipboard selection targets. */
375 /*---------------------------------------------------------------------------*/
377 gl_view_construct_selection (glView *view)
379 gl_debug (DEBUG_VIEW, "START");
381 g_return_if_fail (GL_IS_VIEW (view));
383 view->have_selection = FALSE;
384 view->selection_data = NULL;
385 view->invisible = gtk_invisible_new ();
387 view->selected_object_list = NULL;
389 if (!clipboard_atom) {
390 clipboard_atom = gdk_atom_intern ("GLABELS_CLIPBOARD", FALSE);
393 gtk_selection_add_target (view->invisible,
394 clipboard_atom, GDK_SELECTION_TYPE_STRING, 1);
396 g_signal_connect (G_OBJECT (view->invisible),
397 "selection_clear_event",
398 G_CALLBACK (selection_clear_cb), view);
400 g_signal_connect (G_OBJECT (view->invisible), "selection_get",
401 G_CALLBACK (selection_get_cb), view);
403 g_signal_connect (G_OBJECT (view->invisible),
404 "selection_received",
405 G_CALLBACK (selection_received_cb), view);
407 gl_debug (DEBUG_VIEW, "END");
410 /*---------------------------------------------------------------------------*/
411 /* PRIVATE. Determine an apropriate scale for given label & screen size */
412 /*---------------------------------------------------------------------------*/
414 get_apropriate_scale (gdouble w, gdouble h)
416 gdouble w_screen, h_screen;
420 gl_debug (DEBUG_VIEW, "");
422 w_screen = (gdouble) gdk_screen_width ();
423 h_screen = (gdouble) gdk_screen_height ();
425 for (i = 0; scales[i] > 0.0; i++) {
427 if (k <= HOME_SCALE) {
428 if ((k * w < (w_screen - 256))
429 && (k * h < (h_screen - 256)))
437 /*---------------------------------------------------------------------------*/
438 /* PRIVATE. Draw background and foreground outlines. */
439 /*---------------------------------------------------------------------------*/
441 draw_bg_fg (glView *view)
444 glTemplate *template;
446 view->n_bg_items = 0;
447 view->bg_item_list = NULL;
448 view->n_fg_items = 0;
449 view->fg_item_list = NULL;
452 template = gl_label_get_template (label);
454 switch (template->label.style) {
456 case GL_TEMPLATE_STYLE_RECT:
457 if (template->label.rect.r == 0.0) {
458 /* Square corners. */
459 draw_bg_fg_rect (view);
461 /* Rounded corners. */
462 draw_bg_fg_rounded_rect (view);
466 case GL_TEMPLATE_STYLE_ROUND:
467 draw_bg_fg_round (view);
470 case GL_TEMPLATE_STYLE_CD:
471 draw_bg_fg_cd (view);
475 g_warning ("Unknown template label style");
480 /*---------------------------------------------------------------------------*/
481 /* PRIVATE. Draw simple recangular background. */
482 /*---------------------------------------------------------------------------*/
484 draw_bg_fg_rect (glView *view)
486 glLabel *label = view->label;
487 glTemplate *template;
489 GnomeCanvasItem *item;
490 GnomeCanvasGroup *group;
492 gl_debug (DEBUG_VIEW, "START");
494 g_return_if_fail (GL_IS_VIEW (view));
495 g_return_if_fail (label != NULL);
497 gl_label_get_size (label, &w, &h);
498 template = gl_label_get_template (label);
500 group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
503 item = gnome_canvas_item_new (group,
504 gnome_canvas_rect_get_type (),
509 "fill_color", "white",
512 view->bg_item_list = g_list_append (view->bg_item_list, item);
518 item = gnome_canvas_item_new (group,
519 gnome_canvas_rect_get_type (),
525 "outline_color", "light blue",
528 view->fg_item_list = g_list_append (view->fg_item_list, item);
530 gl_debug (DEBUG_VIEW, "END");
533 /*---------------------------------------------------------------------------*/
534 /* PRIVATE. Draw rounded recangular background. */
535 /*---------------------------------------------------------------------------*/
537 draw_bg_fg_rounded_rect (glView *view)
539 glLabel *label = view->label;
540 GnomeCanvasPoints *points;
541 gint i_coords, i_theta;
542 glTemplate *template;
544 GnomeCanvasItem *item;
545 GnomeCanvasGroup *group;
547 gl_debug (DEBUG_VIEW, "START");
549 g_return_if_fail (GL_IS_VIEW (view));
550 g_return_if_fail (label != NULL);
552 group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
554 gl_label_get_size (label, &w, &h);
555 template = gl_label_get_template (label);
556 r = template->label.rect.r;
558 points = gnome_canvas_points_new (4 * (1 + 90 / 5));
560 for (i_theta = 0; i_theta <= 90; i_theta += 5) {
561 points->coords[i_coords++] =
562 r - r * sin (i_theta * M_PI / 180.0);
563 points->coords[i_coords++] =
564 r - r * cos (i_theta * M_PI / 180.0);
566 for (i_theta = 0; i_theta <= 90; i_theta += 5) {
567 points->coords[i_coords++] =
568 r - r * cos (i_theta * M_PI / 180.0);
569 points->coords[i_coords++] =
570 (h - r) + r * sin (i_theta * M_PI / 180.0);
572 for (i_theta = 0; i_theta <= 90; i_theta += 5) {
573 points->coords[i_coords++] =
574 (w - r) + r * sin (i_theta * M_PI / 180.0);
575 points->coords[i_coords++] =
576 (h - r) + r * cos (i_theta * M_PI / 180.0);
578 for (i_theta = 0; i_theta <= 90; i_theta += 5) {
579 points->coords[i_coords++] =
580 (w - r) + r * cos (i_theta * M_PI / 180.0);
581 points->coords[i_coords++] =
582 r - r * sin (i_theta * M_PI / 180.0);
586 item = gnome_canvas_item_new (group,
587 gnome_canvas_polygon_get_type (),
589 "fill_color", "white",
592 view->bg_item_list = g_list_append (view->bg_item_list, item);
598 item = gnome_canvas_item_new (group,
599 gnome_canvas_polygon_get_type (),
602 "outline_color", "light blue",
605 view->fg_item_list = g_list_append (view->fg_item_list, item);
607 gnome_canvas_points_free (points);
609 gl_debug (DEBUG_VIEW, "END");
612 /*---------------------------------------------------------------------------*/
613 /* PRIVATE. Draw round background. */
614 /*---------------------------------------------------------------------------*/
616 draw_bg_fg_round (glView *view)
618 glLabel *label = view->label;
619 glTemplate *template;
621 GnomeCanvasItem *item;
622 GnomeCanvasGroup *group;
624 gl_debug (DEBUG_VIEW, "START");
626 g_return_if_fail (GL_IS_VIEW (view));
627 g_return_if_fail (label != NULL);
629 template = gl_label_get_template (label);
631 group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
633 r = template->label.round.r;
636 item = gnome_canvas_item_new (group,
637 gnome_canvas_ellipse_get_type (),
642 "fill_color", "white",
645 view->bg_item_list = g_list_append (view->bg_item_list, item);
651 item = gnome_canvas_item_new (group,
652 gnome_canvas_ellipse_get_type (),
658 "outline_color", "light blue",
661 view->fg_item_list = g_list_append (view->fg_item_list, item);
663 gl_debug (DEBUG_VIEW, "END");
666 /*---------------------------------------------------------------------------*/
667 /* PRIVATE. Draw CD style background, circular w/ concentric hole. */
668 /*---------------------------------------------------------------------------*/
670 draw_bg_fg_cd (glView *view)
672 glLabel *label = view->label;
673 glTemplate *template;
675 GnomeCanvasItem *item;
676 GnomeCanvasGroup *group;
678 gl_debug (DEBUG_VIEW, "START");
680 g_return_if_fail (GL_IS_VIEW (view));
681 g_return_if_fail (label != NULL);
683 template = gl_label_get_template (label);
685 group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
687 r1 = template->label.cd.r1;
688 r2 = template->label.cd.r2;
692 item = gnome_canvas_item_new (group,
693 gnome_canvas_ellipse_get_type (),
698 "fill_color", "white",
701 view->bg_item_list = g_list_append (view->bg_item_list, item);
703 item = gnome_canvas_item_new (group,
704 gnome_canvas_ellipse_get_type (),
709 "fill_color", "gray",
712 view->bg_item_list = g_list_append (view->bg_item_list, item);
719 item = gnome_canvas_item_new (group,
720 gnome_canvas_ellipse_get_type (),
726 "outline_color", "light blue",
729 view->fg_item_list = g_list_append (view->fg_item_list, item);
731 item = gnome_canvas_item_new (group,
732 gnome_canvas_ellipse_get_type (),
738 "outline_color", "light blue",
741 view->fg_item_list = g_list_append (view->fg_item_list, item);
743 gl_debug (DEBUG_VIEW, "END");
746 /*---------------------------------------------------------------------------*/
747 /* PRIVATE. Draw markup lines. */
748 /*---------------------------------------------------------------------------*/
750 draw_markup (glView *view)
753 glTemplate *template;
755 glTemplateMarkup *markup;
758 template = gl_label_get_template (label);
760 for ( p=template->label.any.markups; p != NULL; p=p->next ) {
761 markup = (glTemplateMarkup *)p->data;
763 switch (markup->type) {
764 case GL_TEMPLATE_MARKUP_MARGIN:
765 draw_markup_margin (view,
766 (glTemplateMarkupMargin *)markup);
769 g_warning ("Unknown template markup type");
775 /*---------------------------------------------------------------------------*/
776 /* PRIVATE. Draw margin markup. */
777 /*---------------------------------------------------------------------------*/
779 draw_markup_margin (glView *view,
780 glTemplateMarkupMargin *margin)
783 glTemplate *template;
786 template = gl_label_get_template (label);
788 switch (template->label.style) {
790 case GL_TEMPLATE_STYLE_RECT:
791 if (template->label.rect.r == 0.0) {
792 /* Square corners. */
793 draw_markup_margin_rect (view, margin);
795 if ( margin->size < template->label.rect.r) {
796 /* Rounded corners. */
797 draw_markup_margin_rounded_rect (view, margin);
799 /* Square corners. */
800 draw_markup_margin_rect (view, margin);
805 case GL_TEMPLATE_STYLE_ROUND:
806 draw_markup_margin_round (view, margin);
809 case GL_TEMPLATE_STYLE_CD:
810 draw_markup_margin_cd (view, margin);
814 g_warning ("Unknown template label style");
819 /*---------------------------------------------------------------------------*/
820 /* PRIVATE. Draw simple recangular margin. */
821 /*---------------------------------------------------------------------------*/
823 draw_markup_margin_rect (glView *view,
824 glTemplateMarkupMargin *margin)
826 glLabel *label = view->label;
827 glTemplate *template;
829 GnomeCanvasItem *item;
830 GnomeCanvasGroup *group;
832 gl_debug (DEBUG_VIEW, "START");
834 g_return_if_fail (GL_IS_VIEW (view));
835 g_return_if_fail (label != NULL);
837 gl_label_get_size (label, &w, &h);
838 template = gl_label_get_template (label);
841 group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
843 /* Bounding box @ margin */
844 gnome_canvas_item_new (group,
845 gnome_canvas_rect_get_type (),
851 "outline_color", "light blue",
854 view->bg_item_list = g_list_append (view->bg_item_list, item);
856 gl_debug (DEBUG_VIEW, "END");
859 /*---------------------------------------------------------------------------*/
860 /* PRIVATE. Draw rounded recangular markup. */
861 /*---------------------------------------------------------------------------*/
863 draw_markup_margin_rounded_rect (glView *view,
864 glTemplateMarkupMargin *margin)
866 glLabel *label = view->label;
867 GnomeCanvasPoints *points;
868 gint i_coords, i_theta;
869 glTemplate *template;
871 GnomeCanvasItem *item;
872 GnomeCanvasGroup *group;
874 gl_debug (DEBUG_VIEW, "START");
876 g_return_if_fail (GL_IS_VIEW (view));
877 g_return_if_fail (label != NULL);
879 group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
881 gl_label_get_size (label, &w, &h);
882 template = gl_label_get_template (label);
883 r = template->label.rect.r;
890 /* rectangle with rounded corners */
891 points = gnome_canvas_points_new (4 * (1 + 90 / 5));
893 for (i_theta = 0; i_theta <= 90; i_theta += 5) {
894 points->coords[i_coords++] =
895 m + r - r * sin (i_theta * M_PI / 180.0);
896 points->coords[i_coords++] =
897 m + r - r * cos (i_theta * M_PI / 180.0);
899 for (i_theta = 0; i_theta <= 90; i_theta += 5) {
900 points->coords[i_coords++] =
901 m + r - r * cos (i_theta * M_PI / 180.0);
902 points->coords[i_coords++] =
903 m + (h - r) + r * sin (i_theta * M_PI / 180.0);
905 for (i_theta = 0; i_theta <= 90; i_theta += 5) {
906 points->coords[i_coords++] =
907 m + (w - r) + r * sin (i_theta * M_PI / 180.0);
908 points->coords[i_coords++] =
909 m + (h - r) + r * cos (i_theta * M_PI / 180.0);
911 for (i_theta = 0; i_theta <= 90; i_theta += 5) {
912 points->coords[i_coords++] =
913 m + (w - r) + r * cos (i_theta * M_PI / 180.0);
914 points->coords[i_coords++] =
915 m + r - r * sin (i_theta * M_PI / 180.0);
917 item = gnome_canvas_item_new (group,
918 gnome_canvas_polygon_get_type (),
921 "outline_color", "light blue",
923 gnome_canvas_points_free (points);
925 view->bg_item_list = g_list_append (view->bg_item_list, item);
927 gl_debug (DEBUG_VIEW, "END");
930 /*---------------------------------------------------------------------------*/
931 /* PRIVATE. Draw round margin. */
932 /*---------------------------------------------------------------------------*/
934 draw_markup_margin_round (glView *view,
935 glTemplateMarkupMargin *margin)
937 glLabel *label = view->label;
938 glTemplate *template;
940 GnomeCanvasItem *item;
941 GnomeCanvasGroup *group;
943 gl_debug (DEBUG_VIEW, "START");
945 g_return_if_fail (GL_IS_VIEW (view));
946 g_return_if_fail (label != NULL);
948 template = gl_label_get_template (label);
950 group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
952 r = template->label.round.r;
956 item = gnome_canvas_item_new (group,
957 gnome_canvas_ellipse_get_type (),
963 "outline_color", "light blue", NULL);
965 view->bg_item_list = g_list_append (view->bg_item_list, item);
967 gl_debug (DEBUG_VIEW, "END");
970 /*---------------------------------------------------------------------------*/
971 /* PRIVATE. Draw CD margins. */
972 /*---------------------------------------------------------------------------*/
974 draw_markup_margin_cd (glView *view,
975 glTemplateMarkupMargin *margin)
977 glLabel *label = view->label;
978 glTemplate *template;
980 GnomeCanvasItem *item;
981 GnomeCanvasGroup *group;
983 gl_debug (DEBUG_VIEW, "START");
985 g_return_if_fail (GL_IS_VIEW (view));
986 g_return_if_fail (label != NULL);
988 template = gl_label_get_template (label);
990 group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
992 r1 = template->label.cd.r1;
993 r2 = template->label.cd.r2;
997 item = gnome_canvas_item_new (group,
998 gnome_canvas_ellipse_get_type (),
1004 "outline_color", "light blue", NULL);
1006 view->bg_item_list = g_list_append (view->bg_item_list, item);
1008 item = gnome_canvas_item_new (group,
1009 gnome_canvas_ellipse_get_type (),
1015 "outline_color", "light blue",
1018 view->bg_item_list = g_list_append (view->bg_item_list, item);
1020 gl_debug (DEBUG_VIEW, "END");
1023 /*****************************************************************************/
1024 /* Raise foreground items to top. */
1025 /*****************************************************************************/
1027 gl_view_raise_fg (glView *view)
1031 for (p = view->fg_item_list; p != NULL; p = p->next) {
1032 gnome_canvas_item_raise_to_top (GNOME_CANVAS_ITEM(p->data));
1036 /*****************************************************************************/
1037 /* Set arrow mode. */
1038 /*****************************************************************************/
1040 gl_view_arrow_mode (glView *view)
1042 static GdkCursor *cursor = NULL;
1044 gl_debug (DEBUG_VIEW, "START");
1046 g_return_if_fail (GL_IS_VIEW (view));
1049 cursor = gdk_cursor_new (GDK_LEFT_PTR);
1052 gdk_window_set_cursor (view->canvas->window, cursor);
1054 view->state = GL_VIEW_STATE_ARROW;
1056 gl_debug (DEBUG_VIEW, "END");
1059 /*****************************************************************************/
1060 /* Set create text object mode. */
1061 /*****************************************************************************/
1063 gl_view_object_create_mode (glView *view,
1064 glLabelObjectType type)
1068 gl_debug (DEBUG_VIEW, "START");
1070 g_return_if_fail (GL_IS_VIEW (view));
1073 case GL_LABEL_OBJECT_BOX:
1074 cursor = gl_view_box_get_create_cursor ();
1076 case GL_LABEL_OBJECT_ELLIPSE:
1077 cursor = gl_view_ellipse_get_create_cursor ();
1079 case GL_LABEL_OBJECT_LINE:
1080 cursor = gl_view_line_get_create_cursor ();
1082 case GL_LABEL_OBJECT_IMAGE:
1083 cursor = gl_view_image_get_create_cursor ();
1085 case GL_LABEL_OBJECT_TEXT:
1086 cursor = gl_view_text_get_create_cursor ();
1088 case GL_LABEL_OBJECT_BARCODE:
1089 cursor = gl_view_barcode_get_create_cursor ();
1092 g_warning ("Invalid label object type.");/*Should not happen!*/
1096 gdk_window_set_cursor (view->canvas->window, cursor);
1098 view->state = GL_VIEW_STATE_OBJECT_CREATE;
1099 view->create_type = type;
1101 gl_debug (DEBUG_VIEW, "END");
1104 /*****************************************************************************/
1105 /* Select given object (adding to current selection). */
1106 /*****************************************************************************/
1108 gl_view_select_object (glView *view,
1109 glViewObject *view_object)
1111 gl_debug (DEBUG_VIEW, "START");
1113 select_object_real (view, view_object);
1115 g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1117 gl_debug (DEBUG_VIEW, "END");
1120 /*****************************************************************************/
1121 /* Unselect given object (removing from current selection). */
1122 /*****************************************************************************/
1124 gl_view_unselect_object (glView *view,
1125 glViewObject *view_object)
1127 gl_debug (DEBUG_VIEW, "START");
1129 unselect_object_real (view, view_object);
1131 g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1133 gl_debug (DEBUG_VIEW, "END");
1136 /*****************************************************************************/
1137 /* Select all items. */
1138 /*****************************************************************************/
1140 gl_view_select_all (glView *view)
1144 gl_debug (DEBUG_VIEW, "START");
1146 g_return_if_fail (GL_IS_VIEW (view));
1148 /* 1st unselect anything already selected. */
1149 for (p = view->selected_object_list; p != NULL; p = p_next) {
1151 unselect_object_real (view, GL_VIEW_OBJECT (p->data));
1154 /* Finally select all objects. */
1155 for (p = view->object_list; p != NULL; p = p->next) {
1156 select_object_real (view, GL_VIEW_OBJECT (p->data));
1159 g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1161 gl_debug (DEBUG_VIEW, "END");
1164 /*****************************************************************************/
1165 /* Remove all selections */
1166 /*****************************************************************************/
1168 gl_view_unselect_all (glView *view)
1172 gl_debug (DEBUG_VIEW, "START");
1174 g_return_if_fail (GL_IS_VIEW (view));
1176 for (p = view->selected_object_list; p != NULL; p = p_next) {
1178 unselect_object_real (view, GL_VIEW_OBJECT (p->data));
1181 g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1183 gl_debug (DEBUG_VIEW, "END");
1186 /*****************************************************************************/
1187 /* Select all objects within given rectangular region (adding to selection). */
1188 /*****************************************************************************/
1190 gl_view_select_region (glView *view,
1197 glViewObject *view_object;
1198 glLabelObject *object;
1199 gdouble i_x1, i_y1, i_x2, i_y2, w, h;
1201 gl_debug (DEBUG_VIEW, "START");
1203 g_return_if_fail (GL_IS_VIEW (view));
1204 g_return_if_fail ((x1 <= x2) && (y1 <= y2));
1206 for (p = view->object_list; p != NULL; p = p->next) {
1207 view_object = GL_VIEW_OBJECT(p->data);
1208 if (!is_object_selected (view, view_object)) {
1210 object = gl_view_object_get_object (view_object);
1212 gl_label_object_get_position (object, &i_x1, &i_y1);
1213 gl_label_object_get_size (object, &w, &h);
1216 if ((i_x1 >= x1) && (i_x2 <= x2) && (i_y1 >= y1)
1218 select_object_real (view, view_object);
1224 g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1226 gl_debug (DEBUG_VIEW, "END");
1229 /*---------------------------------------------------------------------------*/
1230 /* PRIVATE. Select an object. */
1231 /*---------------------------------------------------------------------------*/
1233 select_object_real (glView *view,
1234 glViewObject *view_object)
1236 gl_debug (DEBUG_VIEW, "START");
1238 g_return_if_fail (GL_IS_VIEW (view));
1239 g_return_if_fail (GL_IS_VIEW_OBJECT (view_object));
1241 if (!is_object_selected (view, view_object)) {
1242 view->selected_object_list =
1243 g_list_prepend (view->selected_object_list, view_object);
1245 gl_view_object_show_highlight (view_object);
1246 gtk_widget_grab_focus (GTK_WIDGET (view->canvas));
1248 gl_debug (DEBUG_VIEW, "END");
1251 /*---------------------------------------------------------------------------*/
1252 /* PRIVATE. Un-select object. */
1253 /*---------------------------------------------------------------------------*/
1255 unselect_object_real (glView *view,
1256 glViewObject *view_object)
1258 gl_debug (DEBUG_VIEW, "START");
1260 g_return_if_fail (GL_IS_VIEW (view));
1261 g_return_if_fail (GL_IS_VIEW_OBJECT (view_object));
1263 gl_view_object_hide_highlight (view_object);
1265 view->selected_object_list =
1266 g_list_remove (view->selected_object_list, view_object);
1268 gl_debug (DEBUG_VIEW, "END");
1271 /*---------------------------------------------------------------------------*/
1272 /* PRIVATE. Return object at (x,y). */
1273 /*---------------------------------------------------------------------------*/
1275 object_at (glView *view,
1279 GnomeCanvasItem *item, *p_item;
1282 gl_debug (DEBUG_VIEW, "");
1284 g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
1286 item = gnome_canvas_get_item_at (GNOME_CANVAS (view->canvas), x, y);
1288 /* No item is at x, y */
1292 /* ignore our background items */
1293 if (g_list_find (view->bg_item_list, item) != NULL)
1299 /*---------------------------------------------------------------------------*/
1300 /* PRIVATE. Is the object in our current selection? */
1301 /*---------------------------------------------------------------------------*/
1303 is_object_selected (glView *view,
1304 glViewObject *view_object)
1306 gl_debug (DEBUG_VIEW, "");
1308 g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
1309 g_return_val_if_fail (GL_IS_VIEW_OBJECT (view_object), FALSE);
1311 if (g_list_find (view->selected_object_list, view_object) == NULL) {
1317 /*****************************************************************************/
1318 /* Is our current selection empty? */
1319 /*****************************************************************************/
1321 gl_view_is_selection_empty (glView *view)
1323 gl_debug (DEBUG_VIEW, "");
1325 g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
1327 if (view->selected_object_list == NULL) {
1334 /*****************************************************************************/
1335 /* Is our current selection atomic? I.e. only one item selected. */
1336 /*****************************************************************************/
1338 gl_view_is_selection_atomic (glView *view)
1340 gl_debug (DEBUG_VIEW, "");
1342 g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
1344 if (view->selected_object_list == NULL)
1346 if (view->selected_object_list->next == NULL)
1351 /*****************************************************************************/
1352 /* Delete selected objects. (Bypass clipboard) */
1353 /*****************************************************************************/
1355 gl_view_delete_selection (glView *view)
1359 gl_debug (DEBUG_VIEW, "START");
1361 g_return_if_fail (GL_IS_VIEW (view));
1363 for (p = view->selected_object_list; p != NULL; p = p_next) {
1365 g_object_unref (G_OBJECT (p->data));
1368 g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
1370 gl_debug (DEBUG_VIEW, "END");
1373 /*****************************************************************************/
1374 /* Edit properties of selected object. */
1375 /*****************************************************************************/
1377 gl_view_edit_object_props (glView *view)
1379 glViewObject *view_object;
1381 gl_debug (DEBUG_VIEW, "START");
1383 g_return_if_fail (GL_IS_VIEW (view));
1385 if (gl_view_is_selection_atomic (view)) {
1387 view_object = GL_VIEW_OBJECT(view->selected_object_list->data);
1388 gl_view_object_show_dialog (view_object);
1392 gl_debug (DEBUG_VIEW, "END");
1395 /*****************************************************************************/
1396 /* Raise selected items to top. */
1397 /*****************************************************************************/
1399 gl_view_raise_selection (glView *view)
1402 glViewObject *view_object;
1403 glLabelObject *label_object;
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) {
1410 view_object = GL_VIEW_OBJECT (p->data);
1411 label_object = gl_view_object_get_object (view_object);
1412 gl_label_object_raise_to_top (label_object);
1415 gl_debug (DEBUG_VIEW, "END");
1418 /*****************************************************************************/
1419 /* Lower selected items to bottom. */
1420 /*****************************************************************************/
1422 gl_view_lower_selection (glView *view)
1425 glViewObject *view_object;
1426 glLabelObject *label_object;
1428 gl_debug (DEBUG_VIEW, "START");
1430 g_return_if_fail (GL_IS_VIEW (view));
1432 for (p = view->selected_object_list; p != NULL; p = p->next) {
1433 view_object = GL_VIEW_OBJECT (p->data);
1434 label_object = gl_view_object_get_object (view_object);
1435 gl_label_object_lower_to_bottom (label_object);
1438 gl_debug (DEBUG_VIEW, "END");
1441 /*****************************************************************************/
1442 /* "Cut" selected items and place in clipboard selections. */
1443 /*****************************************************************************/
1445 gl_view_cut (glView *view)
1447 gl_debug (DEBUG_VIEW, "START");
1449 g_return_if_fail (GL_IS_VIEW (view));
1451 gl_view_copy (view);
1452 gl_view_delete_selection (view);
1454 gl_debug (DEBUG_VIEW, "END");
1457 /*****************************************************************************/
1458 /* "Copy" selected items to clipboard selections. */
1459 /*****************************************************************************/
1461 gl_view_copy (glView *view)
1464 glViewObject *view_object;
1465 glLabelObject *object;
1466 glTemplate *template;
1467 gboolean rotate_flag;
1469 gl_debug (DEBUG_VIEW, "START");
1471 g_return_if_fail (GL_IS_VIEW (view));
1473 if (view->selected_object_list) {
1475 if ( view->selection_data ) {
1476 g_object_unref (view->selection_data);
1478 template = gl_label_get_template (view->label);
1479 rotate_flag = gl_label_get_rotate_flag (view->label);
1480 view->selection_data = GL_LABEL(gl_label_new ());
1481 gl_label_set_template (view->selection_data, template);
1482 gl_label_set_rotate_flag (view->selection_data, rotate_flag);
1483 gl_template_free (&template);
1485 for (p = view->selected_object_list; p != NULL; p = p->next) {
1487 view_object = GL_VIEW_OBJECT (p->data);
1488 object = gl_view_object_get_object (view_object);
1490 gl_debug (DEBUG_VIEW, "Object copied");
1492 if (GL_IS_LABEL_BOX (object)) {
1493 gl_label_box_dup (GL_LABEL_BOX(object),
1494 view->selection_data);
1495 } else if (GL_IS_LABEL_ELLIPSE (object)) {
1496 gl_label_ellipse_dup (GL_LABEL_ELLIPSE(object),
1497 view->selection_data);
1498 } else if (GL_IS_LABEL_LINE (object)) {
1499 gl_label_line_dup (GL_LABEL_LINE(object),
1500 view->selection_data);
1501 } else if (GL_IS_LABEL_IMAGE (object)) {
1502 gl_label_image_dup (GL_LABEL_IMAGE(object),
1503 view->selection_data);
1504 } else if (GL_IS_LABEL_TEXT (object)) {
1505 gl_label_text_dup (GL_LABEL_TEXT(object),
1506 view->selection_data);
1507 } else if (GL_IS_LABEL_BARCODE (object)) {
1508 gl_label_barcode_dup (GL_LABEL_BARCODE(object),
1509 view->selection_data);
1511 /* Should not happen! */
1512 g_warning ("Invalid label object type.");
1518 gtk_selection_owner_set (view->invisible,
1519 clipboard_atom, GDK_CURRENT_TIME);
1520 view->have_selection = TRUE;
1524 gl_debug (DEBUG_VIEW, "END");
1527 /*****************************************************************************/
1528 /* "Paste" from private clipboard selection. */
1529 /*****************************************************************************/
1531 gl_view_paste (glView *view)
1533 gl_debug (DEBUG_VIEW, "START");
1535 g_return_if_fail (GL_IS_VIEW (view));
1537 gtk_selection_convert (GTK_WIDGET (view->invisible),
1538 clipboard_atom, GDK_SELECTION_TYPE_STRING,
1541 gl_debug (DEBUG_VIEW, "END");
1544 /*---------------------------------------------------------------------------*/
1545 /* PRIVATE. move selected objects */
1546 /*---------------------------------------------------------------------------*/
1548 move_selection (glView *view,
1553 glLabelObject *object;
1555 gl_debug (DEBUG_VIEW, "START");
1557 g_return_if_fail (GL_IS_VIEW (view));
1559 for (p = view->selected_object_list; p != NULL; p = p->next) {
1561 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
1562 gl_label_object_set_position_relative (object, dx, dy);
1566 gl_debug (DEBUG_VIEW, "END");
1569 /*****************************************************************************/
1570 /* Zoom in one "notch" */
1571 /*****************************************************************************/
1573 gl_view_zoom_in (glView *view)
1576 gdouble dist, dist_min;
1578 gl_debug (DEBUG_VIEW, "START");
1580 g_return_if_fail (GL_IS_VIEW (view));
1582 /* Find index of current scale (or best match) */
1583 i_min = 1; /* start with 2nd largest scale */
1584 dist_min = fabs (scales[1] - view->scale);
1585 for (i = 2; scales[i] != 0.0; i++) {
1586 dist = fabs (scales[i] - view->scale);
1587 if (dist < dist_min) {
1593 /* zoom in one "notch" */
1594 i = MAX (0, i_min - 1);
1595 gl_view_set_zoom (view, scales[i] / HOME_SCALE);
1597 gl_debug (DEBUG_VIEW, "END");
1600 /*****************************************************************************/
1601 /* Zoom out one "notch" */
1602 /*****************************************************************************/
1604 gl_view_zoom_out (glView *view)
1607 gdouble dist, dist_min;
1609 gl_debug (DEBUG_VIEW, "START");
1611 g_return_if_fail (GL_IS_VIEW (view));
1613 /* Find index of current scale (or best match) */
1614 i_min = 0; /* start with largest scale */
1615 dist_min = fabs (scales[0] - view->scale);
1616 for (i = 1; scales[i] != 0.0; i++) {
1617 dist = fabs (scales[i] - view->scale);
1618 if (dist < dist_min) {
1624 /* zoom out one "notch" */
1625 if (scales[i_min] == 0.0)
1628 if (scales[i] == 0.0)
1630 gl_view_set_zoom (view, scales[i] / HOME_SCALE);
1632 gl_debug (DEBUG_VIEW, "END");
1635 /*****************************************************************************/
1636 /* Set current zoom factor to explicit value. */
1637 /*****************************************************************************/
1639 gl_view_set_zoom (glView *view,
1642 gl_debug (DEBUG_VIEW, "START");
1644 g_return_if_fail (GL_IS_VIEW (view));
1645 g_return_if_fail (scale > 0.0);
1647 view->scale = scale * HOME_SCALE;
1648 gnome_canvas_set_pixels_per_unit (GNOME_CANVAS (view->canvas),
1649 scale * HOME_SCALE);
1651 gl_debug (DEBUG_VIEW, "END");
1654 /*****************************************************************************/
1655 /* Get current zoom factor. */
1656 /*****************************************************************************/
1658 gl_view_get_zoom (glView *view)
1660 gl_debug (DEBUG_VIEW, "");
1662 g_return_val_if_fail (GL_IS_VIEW (view), 1.0);
1664 return view->scale / HOME_SCALE;
1667 /*---------------------------------------------------------------------------*/
1668 /* PRIVATE. Canvas event handler. */
1669 /*---------------------------------------------------------------------------*/
1671 canvas_event (GnomeCanvas *canvas,
1675 gl_debug (DEBUG_VIEW, "");
1677 switch (view->state) {
1679 case GL_VIEW_STATE_ARROW:
1680 return canvas_event_arrow_mode (canvas, event, view);
1682 case GL_VIEW_STATE_OBJECT_CREATE:
1683 switch (view->create_type) {
1684 case GL_LABEL_OBJECT_BOX:
1685 return gl_view_box_create_event_handler (canvas,
1689 case GL_LABEL_OBJECT_ELLIPSE:
1690 return gl_view_ellipse_create_event_handler (canvas,
1694 case GL_LABEL_OBJECT_LINE:
1695 return gl_view_line_create_event_handler (canvas,
1699 case GL_LABEL_OBJECT_IMAGE:
1700 return gl_view_image_create_event_handler (canvas,
1704 case GL_LABEL_OBJECT_TEXT:
1705 return gl_view_text_create_event_handler (canvas,
1709 case GL_LABEL_OBJECT_BARCODE:
1710 return gl_view_barcode_create_event_handler (canvas,
1715 /*Should not happen!*/
1716 g_warning ("Invalid label object type.");
1721 g_warning ("Invalid view state."); /*Should not happen!*/
1727 /*---------------------------------------------------------------------------*/
1728 /* PRIVATE. Canvas event handler (arrow mode) */
1729 /*---------------------------------------------------------------------------*/
1731 canvas_event_arrow_mode (GnomeCanvas *canvas,
1735 static gdouble x0, y0;
1736 static gboolean dragging = FALSE;
1737 static GnomeCanvasItem *item;
1738 gdouble x, y, x1, y1, x2, y2;
1739 GnomeCanvasGroup *group;
1742 gl_debug (DEBUG_VIEW, "");
1744 switch (event->type) {
1746 case GDK_BUTTON_PRESS:
1747 gl_debug (DEBUG_VIEW, "BUTTON_PRESS");
1748 switch (event->button.button) {
1750 gnome_canvas_window_to_world (canvas,
1752 event->button.y, &x, &y);
1754 if (!object_at (view, x, y)) {
1755 if (!(event->button.state & GDK_CONTROL_MASK)) {
1756 gl_view_unselect_all (view);
1760 gdk_pointer_grab (GTK_WIDGET (view->canvas)->
1762 GDK_POINTER_MOTION_MASK |
1763 GDK_BUTTON_RELEASE_MASK |
1764 GDK_BUTTON_PRESS_MASK, NULL,
1765 NULL, event->button.time);
1767 gnome_canvas_root (GNOME_CANVAS
1770 gnome_canvas_item_new (group,
1771 gnome_canvas_rect_get_type (),
1775 "outline_color_rgba",
1790 case GDK_BUTTON_RELEASE:
1791 gl_debug (DEBUG_VIEW, "BUTTON_RELEASE");
1792 switch (event->button.button) {
1796 gdk_pointer_ungrab (event->button.time);
1797 gnome_canvas_window_to_world (canvas,
1805 gl_view_select_region (view, x1, y1, x2, y2);
1806 gtk_object_destroy (GTK_OBJECT (item));
1815 case GDK_MOTION_NOTIFY:
1816 gl_debug (DEBUG_VIEW, "MOTION_NOTIFY");
1817 if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
1818 gnome_canvas_window_to_world (canvas,
1820 event->button.y, &x, &y);
1822 gnome_canvas_item_set (item,
1826 "y2", MAX (y, y0), NULL);
1833 gl_debug (DEBUG_VIEW, "KEY_PRESS");
1835 switch (event->key.keyval) {
1838 move_selection (view,
1839 -1.0 / (view->scale), 0.0);
1843 move_selection (view,
1844 0.0, -1.0 / (view->scale));
1848 move_selection (view,
1849 1.0 / (view->scale), 0.0);
1853 move_selection (view,
1854 0.0, 1.0 / (view->scale));
1858 gl_view_delete_selection (view);
1859 cursor = gdk_cursor_new (GDK_LEFT_PTR);
1860 gdk_window_set_cursor (view->canvas->window,
1862 gdk_cursor_unref (cursor);
1868 return TRUE; /* We handled this or we were dragging. */
1871 gl_debug (DEBUG_VIEW, "default");
1877 /*****************************************************************************/
1878 /* Item event handler. */
1879 /*****************************************************************************/
1881 gl_view_item_event_handler (GnomeCanvasItem *item,
1883 glViewObject *view_object)
1887 gl_debug (DEBUG_VIEW, "");
1889 view = gl_view_object_get_view(view_object);
1890 switch (view->state) {
1892 case GL_VIEW_STATE_ARROW:
1893 return item_event_arrow_mode (item, event, view_object);
1902 /*---------------------------------------------------------------------------*/
1903 /* PRIVATE. Item event handler (arrow mode) */
1904 /*---------------------------------------------------------------------------*/
1906 item_event_arrow_mode (GnomeCanvasItem *item,
1908 glViewObject *view_object)
1910 static gdouble x, y;
1911 static gboolean dragging = FALSE;
1914 gdouble item_x, item_y;
1915 gdouble new_x, new_y;
1916 gboolean control_key_pressed;
1918 gl_debug (DEBUG_VIEW, "");
1920 item_x = event->button.x;
1921 item_y = event->button.y;
1922 gnome_canvas_item_w2i (item->parent, &item_x, &item_y);
1924 view = gl_view_object_get_view(view_object);
1926 switch (event->type) {
1928 case GDK_BUTTON_PRESS:
1929 gl_debug (DEBUG_VIEW, "BUTTON_PRESS");
1930 control_key_pressed = event->button.state & GDK_CONTROL_MASK;
1931 switch (event->button.button) {
1933 if (control_key_pressed) {
1934 if (is_object_selected (view, view_object)) {
1935 /* Un-selecting a selected item */
1936 gl_view_unselect_object (view,
1940 /* Add to current selection */
1941 gl_view_select_object (view,
1945 if (!is_object_selected (view, view_object)) {
1946 /* No control, key so remove any selections before adding */
1947 gl_view_unselect_all (view);
1948 /* Add to current selection */
1949 gl_view_select_object (view,
1953 /* Go into dragging mode while button remains pressed. */
1956 cursor = gdk_cursor_new (GDK_FLEUR);
1957 gnome_canvas_item_grab (item,
1958 GDK_POINTER_MOTION_MASK |
1959 GDK_BUTTON_RELEASE_MASK |
1960 GDK_BUTTON_PRESS_MASK,
1961 cursor, event->button.time);
1962 gdk_cursor_unref (cursor);
1967 if (!is_object_selected (view, view_object)) {
1968 if (!control_key_pressed) {
1969 /* No control, key so remove any selections before adding */
1970 gl_view_unselect_all (view);
1973 /* Add to current selection */
1974 gl_view_select_object (view, view_object);
1975 /* bring up apropriate menu for selection. */
1976 popup_selection_menu (view, view_object, event);
1983 case GDK_BUTTON_RELEASE:
1984 gl_debug (DEBUG_VIEW, "BUTTON_RELEASE");
1985 switch (event->button.button) {
1987 /* Exit dragging mode */
1988 gnome_canvas_item_ungrab (item, event->button.time);
1996 case GDK_MOTION_NOTIFY:
1997 gl_debug (DEBUG_VIEW, "MOTION_NOTIFY");
1998 if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
1999 /* Dragging mode, move selection */
2002 move_selection (view, (new_x - x), (new_y - y));
2010 case GDK_2BUTTON_PRESS:
2011 gl_debug (DEBUG_VIEW, "2BUTTON_PRESS");
2012 switch (event->button.button) {
2014 /* Also exit dragging mode w/ double-click, run dlg */
2015 gnome_canvas_item_ungrab (item, event->button.time);
2017 gl_view_select_object (view, view_object);
2018 gl_view_object_show_dialog (view_object);
2025 case GDK_ENTER_NOTIFY:
2026 gl_debug (DEBUG_VIEW, "ENTER_NOTIFY");
2027 cursor = gdk_cursor_new (GDK_FLEUR);
2028 gdk_window_set_cursor (view->canvas->window, cursor);
2029 gdk_cursor_unref (cursor);
2032 case GDK_LEAVE_NOTIFY:
2033 gl_debug (DEBUG_VIEW, "LEAVE_NOTIFY");
2034 cursor = gdk_cursor_new (GDK_LEFT_PTR);
2035 gdk_window_set_cursor (view->canvas->window, cursor);
2036 gdk_cursor_unref (cursor);
2040 gl_debug (DEBUG_VIEW, "default");
2046 /*---------------------------------------------------------------------------*/
2047 /* PRIVATE. create menu for multiple selections. */
2048 /*---------------------------------------------------------------------------*/
2050 new_selection_menu (glView *view)
2052 GtkWidget *menu, *menuitem;
2054 gl_debug (DEBUG_VIEW, "START");
2056 g_return_val_if_fail (GL_IS_VIEW (view), NULL);
2058 menu = gtk_menu_new ();
2060 menuitem = gtk_menu_item_new_with_label (_("Delete"));
2061 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
2062 gtk_widget_show (menuitem);
2063 g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
2064 G_CALLBACK (gl_view_delete_selection), view);
2066 menuitem = gtk_menu_item_new ();
2067 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
2068 gtk_widget_show (menuitem);
2070 menuitem = gtk_menu_item_new_with_label (_("Bring to front"));
2071 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
2072 gtk_widget_show (menuitem);
2073 g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
2074 G_CALLBACK (gl_view_raise_selection), view);
2076 menuitem = gtk_menu_item_new_with_label (_("Send to back"));
2077 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
2078 gtk_widget_show (menuitem);
2079 g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
2080 G_CALLBACK (gl_view_lower_selection), view);
2082 gl_debug (DEBUG_VIEW, "END");
2087 /*---------------------------------------------------------------------------*/
2088 /* PRIVATE. popup menu for given item. */
2089 /*---------------------------------------------------------------------------*/
2091 popup_selection_menu (glView *view,
2092 glViewObject *view_object,
2097 gl_debug (DEBUG_VIEW, "START");
2099 g_return_if_fail (GL_IS_VIEW (view));
2100 g_return_if_fail (GL_IS_VIEW_OBJECT (view_object));
2102 if (gl_view_is_selection_atomic (view)) {
2104 menu = gl_view_object_get_menu (view_object);
2106 gtk_menu_popup (GTK_MENU (menu),
2107 NULL, NULL, NULL, NULL,
2108 event->button.button,
2109 event->button.time);
2114 if (view->menu != NULL) {
2115 gtk_menu_popup (GTK_MENU (view->menu),
2116 NULL, NULL, NULL, NULL,
2117 event->button.button,
2118 event->button.time);
2123 gl_debug (DEBUG_VIEW, "END");
2126 /*---------------------------------------------------------------------------*/
2127 /* PRIVATE. Handle "selection-clear" signal. */
2128 /*---------------------------------------------------------------------------*/
2130 selection_clear_cb (GtkWidget *widget,
2131 GdkEventSelection *event,
2134 glView *view = GL_VIEW (data);
2136 gl_debug (DEBUG_VIEW, "START");
2138 g_return_if_fail (GL_IS_VIEW (view));
2140 view->have_selection = FALSE;
2141 g_object_unref (view->selection_data);
2142 view->selection_data = NULL;
2144 gl_debug (DEBUG_VIEW, "END");
2147 /*---------------------------------------------------------------------------*/
2148 /* PRIVATE. Handle "selection-get" signal. */
2149 /*---------------------------------------------------------------------------*/
2151 selection_get_cb (GtkWidget *widget,
2152 GtkSelectionData *selection_data,
2157 glView *view = GL_VIEW (data);
2159 glXMLLabelStatus status;
2161 gl_debug (DEBUG_VIEW, "START");
2163 g_return_if_fail (GL_IS_VIEW (view));
2165 if (view->have_selection) {
2167 buffer = gl_xml_label_save_buffer (view->selection_data,
2169 gtk_selection_data_set (selection_data,
2170 GDK_SELECTION_TYPE_STRING, 8, buffer,
2175 gl_debug (DEBUG_VIEW, "END");
2178 /*---------------------------------------------------------------------------*/
2179 /* PRIVATE. Handle "selection-received" signal. (Result of Paste) */
2180 /*---------------------------------------------------------------------------*/
2182 selection_received_cb (GtkWidget *widget,
2183 GtkSelectionData *selection_data,
2187 glView *view = GL_VIEW (data);
2188 glLabel *label = NULL;
2189 glXMLLabelStatus status;
2191 glLabelObject *object, *newobject;
2192 glViewObject *view_object;
2194 gl_debug (DEBUG_VIEW, "START");
2196 g_return_if_fail (GL_IS_VIEW (view));
2198 if (selection_data->length < 0) {
2201 if (selection_data->type != GDK_SELECTION_TYPE_STRING) {
2205 gl_view_unselect_all (view);
2207 label = gl_xml_label_open_buffer (selection_data->data, &status);
2208 for (p = label->objects; p != NULL; p = p_next) {
2211 object = (glLabelObject *) p->data;
2212 gl_label_object_set_parent (object, view->label);
2214 gl_debug (DEBUG_VIEW, "object pasted");
2216 if (GL_IS_LABEL_BOX (object)) {
2217 view_object = gl_view_box_new (GL_LABEL_BOX(object),
2219 } else if (GL_IS_LABEL_ELLIPSE (object)) {
2220 view_object = gl_view_ellipse_new (GL_LABEL_ELLIPSE(object),
2222 } else if (GL_IS_LABEL_LINE (object)) {
2223 view_object = gl_view_line_new (GL_LABEL_LINE(object),
2225 } else if (GL_IS_LABEL_IMAGE (object)) {
2226 view_object = gl_view_image_new (GL_LABEL_IMAGE(object),
2228 } else if (GL_IS_LABEL_TEXT (object)) {
2229 view_object = gl_view_text_new (GL_LABEL_TEXT(object),
2231 } else if (GL_IS_LABEL_BARCODE (object)) {
2232 view_object = gl_view_barcode_new (GL_LABEL_BARCODE(object),
2235 /* Should not happen! */
2237 g_warning ("Invalid label object type.");
2239 gl_view_select_object (view, view_object);
2241 g_object_unref (label);
2243 gl_debug (DEBUG_VIEW, "END");