]> git.sur5r.net Git - glabels/blob - glabels2/src/view-highlight.c
View_highlight is now a full-fledged object that tracks its corresponding label objec...
[glabels] / glabels2 / src / view-highlight.c
1 /*
2  *  (GLABELS) Label and Business Card Creation program for GNOME
3  *
4  *  view_highlight.c:  GLabels Resizable Highlight module
5  *
6  *  Copyright (C) 2001-2002  Jim Evins <evins@snaught.com>.
7  *
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.
12  *
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.
17  *
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
21  */
22
23 #include <config.h>
24
25 #include <math.h>
26
27 #include "view-highlight.h"
28
29 #include "debug.h"
30
31 #define MIN_ITEM_SIZE 1.0
32 #define FG_COLOR GNOME_CANVAS_COLOR_A (0, 0, 255, 255)
33 #define BG_COLOR GNOME_CANVAS_COLOR_A (255, 255, 255, 255)
34
35 /*===========================================*/
36 /* Private data types                        */
37 /*===========================================*/
38 struct _glViewHighlightPrivate {
39         glViewHighlightStyle     style;
40         glLabelObject           *object;
41         glView                  *view;
42
43         GnomeCanvasItem         *group;
44         GnomeCanvasItem         *outline;
45         GnomeCanvasItem         *tl, *tr, *bl, *br; /* Corner handles */
46         GnomeCanvasItem         *sl, *sr, *st, *sb; /* Side handles */
47         GnomeCanvasItem         *p1, *p2;           /* Line endpoint handles */
48 };
49
50 /*===========================================*/
51 /* Private globals                           */
52 /*===========================================*/
53
54 static GObjectClass *parent_class = NULL;
55
56 /*===========================================*/
57 /* Local function prototypes                 */
58 /*===========================================*/
59
60 static void   gl_view_highlight_class_init       (glViewHighlightClass   *klass);
61 static void   gl_view_highlight_instance_init    (glViewHighlight        *view_highlight);
62 static void   gl_view_highlight_finalize         (GObject                *object);
63
64
65 static void   highlight_resizable_box_construct  (glViewHighlight        *view_highlight,
66                                                   glViewObject           *view_object,
67                                                   glViewHighlightStyle    style);
68
69 static void   highlight_resizable_line_construct (glViewHighlight        *view_highlight,
70                                                   glViewObject           *view_object);
71
72 static void   highlight_simple_construct         (glViewHighlight        *view_highlight,
73                                                   glViewObject           *view_object);
74
75 static void   object_moved_cb                    (glLabelObject          *object,
76                                                   gdouble                 x,
77                                                   gdouble                 y,
78                                                   glViewHighlight        *view_highlight);
79
80 static void   object_changed_cb                  (glLabelObject          *object,
81                                                   glViewHighlight        *view_highlight);
82
83
84 static void   update_resizable_box               (glViewHighlight        *view_highlight);
85
86 static void   update_resizable_line              (glViewHighlight        *view_highlight);
87
88 static void   update_simple                      (glViewHighlight        *view_highlight);
89
90
91 static int tl_resize_event_handler (GnomeCanvasItem *handle_item,
92                                     GdkEvent        *event,
93                                     glViewHighlight *view_highlight);
94 static int tr_resize_event_handler (GnomeCanvasItem *handle_item,
95                                     GdkEvent        *event,
96                                     glViewHighlight *view_highlight);
97 static int bl_resize_event_handler (GnomeCanvasItem *handle_item,
98                                     GdkEvent        *event,
99                                     glViewHighlight *view_highlight);
100 static int br_resize_event_handler (GnomeCanvasItem *handle_item,
101                                     GdkEvent        *event,
102                                     glViewHighlight *view_highlight);
103
104 static int sl_resize_event_handler (GnomeCanvasItem *handle_item,
105                                     GdkEvent        *event,
106                                     glViewHighlight *view_highlight);
107 static int sr_resize_event_handler (GnomeCanvasItem *handle_item,
108                                     GdkEvent        *event,
109                                     glViewHighlight *view_highlight);
110 static int st_resize_event_handler (GnomeCanvasItem *handle_item,
111                                     GdkEvent        *event,
112                                     glViewHighlight *view_highlight);
113 static int sb_resize_event_handler (GnomeCanvasItem *handle_item,
114                                     GdkEvent        *event,
115                                     glViewHighlight *view_highlight);
116
117 static int p1_resize_event_handler (GnomeCanvasItem *handle_item,
118                                     GdkEvent        *event,
119                                     glViewHighlight *view_highlight);
120 static int p2_resize_event_handler (GnomeCanvasItem *handle_item,
121                                     GdkEvent        *event,
122                                     glViewHighlight *view_highlight);
123
124 static int passthrough_event_handler (GnomeCanvasItem *handle_item,
125                                       GdkEvent        *event,
126                                       glViewObject    *view_object);
127 \f
128 /*****************************************************************************/
129 /* Boilerplate object stuff.                                                 */
130 /*****************************************************************************/
131 GType
132 gl_view_highlight_get_type (void)
133 {
134         static GType type = 0;
135
136         if (!type) {
137                 GTypeInfo info = {
138                         sizeof (glViewHighlightClass),
139                         NULL,
140                         NULL,
141                         (GClassInitFunc) gl_view_highlight_class_init,
142                         NULL,
143                         NULL,
144                         sizeof (glViewHighlight),
145                         0,
146                         (GInstanceInitFunc) gl_view_highlight_instance_init,
147                 };
148
149                 type = g_type_register_static (G_TYPE_OBJECT,
150                                                "glViewHighlight", &info, 0);
151         }
152
153         return type;
154 }
155
156 static void
157 gl_view_highlight_class_init (glViewHighlightClass *klass)
158 {
159         GObjectClass *object_class = (GObjectClass *) klass;
160
161         gl_debug (DEBUG_VIEW, "START");
162
163         parent_class = g_type_class_peek_parent (klass);
164
165         object_class->finalize = gl_view_highlight_finalize;
166
167         gl_debug (DEBUG_VIEW, "END");
168 }
169
170 static void
171 gl_view_highlight_instance_init (glViewHighlight *view_highlight)
172 {
173         gl_debug (DEBUG_VIEW, "START");
174
175         view_highlight->private = g_new0 (glViewHighlightPrivate, 1);
176
177         gl_debug (DEBUG_VIEW, "END");
178 }
179
180 static void
181 gl_view_highlight_finalize (GObject *object)
182 {
183         glLabel       *parent;
184         glView        *view;
185
186         gl_debug (DEBUG_VIEW, "START");
187
188         g_return_if_fail (object && GL_IS_VIEW_HIGHLIGHT (object));
189
190         g_object_unref (GL_VIEW_HIGHLIGHT(object)->private->object);
191
192         gtk_object_destroy (GTK_OBJECT(GL_VIEW_HIGHLIGHT(object)->private->group));
193
194         G_OBJECT_CLASS (parent_class)->finalize (object);
195
196         gl_debug (DEBUG_VIEW, "END");
197 }
198
199 /*****************************************************************************/
200 /* Create a resizable highlight for given object.                            */
201 /*****************************************************************************/
202 GObject *
203 gl_view_highlight_new (glViewObject         *view_object,
204                        glViewHighlightStyle  style)
205 {
206         glViewHighlight *view_highlight;
207
208         gl_debug (DEBUG_VIEW, "START");
209
210         g_return_if_fail (view_object && GL_IS_VIEW_OBJECT(view_object));
211
212         view_highlight = g_object_new (gl_view_highlight_get_type (), NULL);
213
214         view_highlight->private->style = style;
215
216         switch (style) {
217
218         case GL_VIEW_HIGHLIGHT_BOX_RESIZABLE:
219         case GL_VIEW_HIGHLIGHT_ELLIPSE_RESIZABLE:
220                 highlight_resizable_box_construct (view_highlight, view_object, style);
221                 break;
222
223         case GL_VIEW_HIGHLIGHT_LINE_RESIZABLE:
224                 highlight_resizable_line_construct (view_highlight, view_object);
225                 break;
226
227         case GL_VIEW_HIGHLIGHT_SIMPLE:
228                 highlight_simple_construct (view_highlight, view_object);
229                 break;
230
231         default:
232                 g_warning ("Invalid resizable highlight style");
233
234         }
235
236         g_signal_connect (G_OBJECT (view_highlight->private->object), "moved",
237                           G_CALLBACK (object_moved_cb), view_highlight);
238
239         g_signal_connect (G_OBJECT (view_highlight->private->object), "changed",
240                           G_CALLBACK (object_changed_cb), view_highlight);
241
242         gl_debug (DEBUG_VIEW, "END");
243
244         return G_OBJECT (view_highlight);
245 }
246
247 /*---------------------------------------------------------------------------*/
248 /* PRIVATE.  Create a resizable box highlight.                               */
249 /*---------------------------------------------------------------------------*/
250 static void
251 highlight_resizable_box_construct (glViewHighlight        *view_highlight,
252                                    glViewObject           *view_object,
253                                    glViewHighlightStyle    style)
254 {
255         gdouble x, y, w, h;
256         GnomeCanvasItem *group;
257         glView *view;
258         glLabelObject *object;
259
260         gl_debug (DEBUG_VIEW, "START");
261
262         g_return_if_fail (view_highlight && GL_IS_VIEW_HIGHLIGHT (view_highlight));
263         g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
264
265         view   = gl_view_object_get_view (view_object);
266         view_highlight->private->view = view;
267
268         object = gl_view_object_get_object (view_object);
269         view_highlight->private->object = object;
270
271         g_return_if_fail (view && GL_IS_VIEW (view));
272         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
273
274         gl_label_object_get_position (object, &x, &y);
275         gl_label_object_get_size (object, &w, &h);
276
277         view_highlight->private->group =
278                 gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (view->canvas)),
279                                        gnome_canvas_group_get_type (),
280                                        "x", x, "y", y, NULL);
281         gnome_canvas_item_hide (view_highlight->private->group);
282         group = view_highlight->private->group;
283
284         switch (style) {
285         case GL_VIEW_HIGHLIGHT_BOX_RESIZABLE:
286                 view_highlight->private->outline =
287                         gnome_canvas_item_new (GNOME_CANVAS_GROUP(group),
288                                                gnome_canvas_rect_get_type (),
289                                                "x1", -0.5,
290                                                "y1", -0.5,
291                                                "x2", w + 0.5,
292                                                "y2", h + 0.5,
293                                                "width_pixels", 2,
294                                                "outline_color_rgba", FG_COLOR,
295                                                NULL);
296                 break;
297         case GL_VIEW_HIGHLIGHT_ELLIPSE_RESIZABLE:
298                 view_highlight->private->outline =
299                         gnome_canvas_item_new (GNOME_CANVAS_GROUP(group),
300                                                gnome_canvas_ellipse_get_type (),
301                                                "x1", -0.5,
302                                                "y1", -0.5,
303                                                "x2", w + 0.5,
304                                                "y2", h + 0.5,
305                                                "width_pixels", 2,
306                                                "outline_color_rgba", FG_COLOR,
307                                                NULL);
308                 break;
309         default:
310                 view_highlight->private->outline = NULL;
311                 g_warning ("Invalid resizable highlight style");
312         }
313
314         view_highlight->private->tl =
315                 gnome_canvas_item_new (GNOME_CANVAS_GROUP(group),
316                                        gnome_canvas_rect_get_type (),
317                                        "x1", -1.0,
318                                        "y1", -1.0,
319                                        "x2", +1.0,
320                                        "y2", +1.0,
321                                        "fill_color_rgba", FG_COLOR,
322                                        "outline_color_rgba", BG_COLOR,
323                                        NULL);
324
325         view_highlight->private->tr =
326                 gnome_canvas_item_new (GNOME_CANVAS_GROUP(group),
327                                        gnome_canvas_rect_get_type (),
328                                        "x1", w - 1.0,
329                                        "y1", -1.0,
330                                        "x2", w + 1.0,
331                                        "y2", +1.0,
332                                        "fill_color_rgba", FG_COLOR,
333                                        "outline_color_rgba", BG_COLOR,
334                                        NULL);
335
336         view_highlight->private->bl =
337                 gnome_canvas_item_new (GNOME_CANVAS_GROUP(group),
338                                        gnome_canvas_rect_get_type (),
339                                        "x1", -1.0,
340                                        "y1", h - 1.0,
341                                        "x2", +1.0,
342                                        "y2", h + 1.0,
343                                        "fill_color_rgba", FG_COLOR,
344                                        "outline_color_rgba", BG_COLOR,
345                                        NULL);
346
347         view_highlight->private->br =
348                 gnome_canvas_item_new (GNOME_CANVAS_GROUP(group),
349                                        gnome_canvas_rect_get_type (),
350                                        "x1", w - 1.0,
351                                        "y1", h - 1.0,
352                                        "x2", w + 1.0,
353                                        "y2", h + 1.0,
354                                        "fill_color_rgba", FG_COLOR,
355                                        "outline_color_rgba", BG_COLOR,
356                                        NULL);
357
358         view_highlight->private->sl =
359                 gnome_canvas_item_new (GNOME_CANVAS_GROUP(group),
360                                        gnome_canvas_rect_get_type (),
361                                        "x1", -1.0,
362                                        "y1", h / 2.0 - 1.0,
363                                        "x2", +1.0,
364                                        "y2", h / 2.0 + 1.0,
365                                        "fill_color_rgba", FG_COLOR,
366                                        "outline_color_rgba", BG_COLOR,
367                                        NULL);
368
369         view_highlight->private->sr =
370                 gnome_canvas_item_new (GNOME_CANVAS_GROUP(group),
371                                        gnome_canvas_rect_get_type (),
372                                        "x1", w - 1.0,
373                                        "y1", h / 2.0 - 1.0,
374                                        "x2", w + 1.0,
375                                        "y2", h / 2.0 + 1.0,
376                                        "fill_color_rgba", FG_COLOR,
377                                        "outline_color_rgba", BG_COLOR,
378                                        NULL);
379
380         view_highlight->private->st =
381                 gnome_canvas_item_new (GNOME_CANVAS_GROUP(group),
382                                        gnome_canvas_rect_get_type (),
383                                        "x1", w / 2.0 - 1.0,
384                                        "y1", -1.0,
385                                        "x2", w / 2.0 + 1.0,
386                                        "y2", +1.0,
387                                        "fill_color_rgba", FG_COLOR,
388                                        "outline_color_rgba", BG_COLOR,
389                                        NULL);
390
391         view_highlight->private->sb =
392                 gnome_canvas_item_new (GNOME_CANVAS_GROUP(group),
393                                        gnome_canvas_rect_get_type (),
394                                        "x1", w / 2.0 - 1.0,
395                                        "y1", h - 1.0,
396                                        "x2", w / 2.0 + 1.0,
397                                        "y2", h + 1.0,
398                                        "fill_color_rgba", FG_COLOR,
399                                        "outline_color_rgba", BG_COLOR,
400                                        NULL);
401
402         g_signal_connect (G_OBJECT (view_highlight->private->tl), "event",
403                           G_CALLBACK (tl_resize_event_handler), view_highlight);
404         g_signal_connect (G_OBJECT (view_highlight->private->tr), "event",
405                           G_CALLBACK (tr_resize_event_handler), view_highlight);
406         g_signal_connect (G_OBJECT (view_highlight->private->bl), "event",
407                           G_CALLBACK (bl_resize_event_handler), view_highlight);
408         g_signal_connect (G_OBJECT (view_highlight->private->br), "event",
409                           G_CALLBACK (br_resize_event_handler), view_highlight);
410         g_signal_connect (G_OBJECT (view_highlight->private->sl), "event",
411                           G_CALLBACK (sl_resize_event_handler), view_highlight);
412         g_signal_connect (G_OBJECT (view_highlight->private->sr), "event",
413                           G_CALLBACK (sr_resize_event_handler), view_highlight);
414         g_signal_connect (G_OBJECT (view_highlight->private->st), "event",
415                           G_CALLBACK (st_resize_event_handler), view_highlight);
416         g_signal_connect (G_OBJECT (view_highlight->private->sb), "event",
417                           G_CALLBACK (sb_resize_event_handler), view_highlight);
418
419         g_signal_connect (G_OBJECT (view_highlight->private->outline), "event",
420                           G_CALLBACK (passthrough_event_handler), view_object);
421
422         /* send to top, then lower below all items that form the foregound */
423         gnome_canvas_item_raise_to_top (group);
424         gl_view_raise_fg (view);
425
426         gl_debug (DEBUG_VIEW, "END");
427 }
428
429 /*---------------------------------------------------------------------------*/
430 /* PRIVATE.  Create a resizable line highlight.                              */
431 /*---------------------------------------------------------------------------*/
432 static void
433 highlight_resizable_line_construct (glViewHighlight        *view_highlight,
434                                     glViewObject           *view_object)
435 {
436         gdouble x, y, dx, dy;
437         GnomeCanvasItem *group;
438         GnomeCanvasPoints *points;
439         glView *view;
440         glLabelObject *object;
441
442         gl_debug (DEBUG_VIEW, "START");
443
444         g_return_if_fail (view_highlight && GL_IS_VIEW_HIGHLIGHT (view_highlight));
445         g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
446
447         view   = gl_view_object_get_view (view_object);
448         view_highlight->private->view = view;
449
450         object = gl_view_object_get_object (view_object);
451         view_highlight->private->object = object;
452
453         g_return_if_fail (view && GL_IS_VIEW (view));
454         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
455
456         gl_label_object_get_position (object, &x, &y);
457         gl_label_object_get_size (object, &dx, &dy);
458
459         points = gnome_canvas_points_new (2);
460
461         view_highlight->private->group =
462                 gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (view->canvas)),
463                                        gnome_canvas_group_get_type (),
464                                        "x", x, "y", y, NULL);
465         gnome_canvas_item_hide (view_highlight->private->group);
466         group = view_highlight->private->group;
467
468         points->coords[0] = 0.0;
469         points->coords[1] = 0.0;
470         points->coords[2] = dx;
471         points->coords[3] = dy;
472         view_highlight->private->outline =
473                 gnome_canvas_item_new (GNOME_CANVAS_GROUP(group),
474                                        gnome_canvas_line_get_type (),
475                                        "points", points,
476                                        "width_pixels", 3,
477                                        "fill_color_rgba", FG_COLOR,
478                                        NULL);
479
480         view_highlight->private->p1 =
481                 gnome_canvas_item_new (GNOME_CANVAS_GROUP(group),
482                                        gnome_canvas_rect_get_type (),
483                                        "x1", -1.0,
484                                        "y1", -1.0,
485                                        "x2", +1.0,
486                                        "y2", +1.0,
487                                        "fill_color_rgba", FG_COLOR,
488                                        "outline_color_rgba", BG_COLOR,
489                                        NULL);
490
491         view_highlight->private->p2 =
492                 gnome_canvas_item_new (GNOME_CANVAS_GROUP(group),
493                                        gnome_canvas_rect_get_type (),
494                                        "x1", dx - 1.0,
495                                        "y1", dy - 1.0,
496                                        "x2", dx + 1.0,
497                                        "y2", dy + 1.0,
498                                        "fill_color_rgba", FG_COLOR,
499                                        "outline_color_rgba", BG_COLOR,
500                                        NULL);
501
502         g_signal_connect (G_OBJECT (view_highlight->private->p1), "event",
503                           G_CALLBACK (p1_resize_event_handler), view_highlight);
504         g_signal_connect (G_OBJECT (view_highlight->private->p2), "event",
505                           G_CALLBACK (p2_resize_event_handler), view_highlight);
506
507         g_signal_connect (G_OBJECT (view_highlight->private->outline), "event",
508                           G_CALLBACK (passthrough_event_handler), view_object);
509
510         gnome_canvas_points_free (points);
511
512         /* send to top, then lower below all items that form the foregound */
513         gnome_canvas_item_raise_to_top (group);
514         gl_view_raise_fg (view);
515
516         gl_debug (DEBUG_VIEW, "END");
517 }
518
519 /*---------------------------------------------------------------------------*/
520 /* PRIVATE.  Create a simple box highlight.                                  */
521 /*---------------------------------------------------------------------------*/
522 static void
523 highlight_simple_construct (glViewHighlight        *view_highlight,
524                             glViewObject           *view_object)
525 {
526         gdouble x, y, w, h;
527         GnomeCanvasItem *group;
528         glView *view;
529         glLabelObject *object;
530
531         gl_debug (DEBUG_VIEW, "START");
532
533         g_return_if_fail (view_highlight && GL_IS_VIEW_HIGHLIGHT (view_highlight));
534         g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
535
536         view   = gl_view_object_get_view (view_object);
537         view_highlight->private->view = view;
538
539         object = gl_view_object_get_object (view_object);
540         view_highlight->private->object = object;
541
542         g_return_if_fail (view && GL_IS_VIEW (view));
543         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
544
545         gl_label_object_get_position (object, &x, &y);
546         gl_label_object_get_size (object, &w, &h);
547
548
549         view_highlight->private->group =
550                 gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (view->canvas)),
551                                        gnome_canvas_group_get_type (),
552                                        "x", x, "y", y, NULL);
553         gnome_canvas_item_hide (view_highlight->private->group);
554         group = view_highlight->private->group;
555
556         view_highlight->private->outline =
557                 gnome_canvas_item_new (GNOME_CANVAS_GROUP(group),
558                                        gnome_canvas_rect_get_type (),
559                                        "x1", -0.5,
560                                        "y1", -0.5,
561                                        "x2", w + 0.5,
562                                        "y2", h + 0.5,
563                                        "width_pixels", 2,
564                                        "outline_color_rgba", FG_COLOR,
565                                        NULL);
566
567
568         g_signal_connect (G_OBJECT (view_highlight->private->outline), "event",
569                           G_CALLBACK (passthrough_event_handler), view_object);
570
571         /* send to top, then lower below all items that form the foregound */
572         gnome_canvas_item_raise_to_top (group);
573         gl_view_raise_fg (view);
574
575         gl_debug (DEBUG_VIEW, "END");
576 }
577
578 /****************************************************************************/
579 /* Show highlight.                                                          */
580 /****************************************************************************/
581 void
582 gl_view_highlight_show (glViewHighlight *view_highlight)
583 {
584         gnome_canvas_item_show (view_highlight->private->group);
585
586         gnome_canvas_item_raise_to_top (view_highlight->private->group);
587         gl_view_raise_fg (view_highlight->private->view);
588 }
589
590 /****************************************************************************/
591 /* Hide highlight.                                                          */
592 /****************************************************************************/
593 void
594 gl_view_highlight_hide (glViewHighlight *view_highlight)
595 {
596         gnome_canvas_item_hide (view_highlight->private->group);
597 }
598
599 /*---------------------------------------------------------------------------*/
600 /* PRIVATE.  Object moved callback.                                          */
601 /*---------------------------------------------------------------------------*/
602 static void
603 object_moved_cb (glLabelObject    *object,
604                  gdouble           dx,
605                  gdouble           dy,
606                  glViewHighlight  *view_highlight)
607 {
608         GnomeCanvasItem    *item, *highlight;
609
610         gl_debug (DEBUG_VIEW, "START");
611
612         g_return_if_fail (view_highlight && GL_IS_VIEW_HIGHLIGHT (view_highlight));
613         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
614
615         /* Adjust location of highlight group */
616         gnome_canvas_item_move (view_highlight->private->group, dx, dy);
617
618         gl_debug (DEBUG_VIEW, "END");
619 }
620
621 /*---------------------------------------------------------------------------*/
622 /* PRIVATE. label object "changed" callback.                                 */
623 /*---------------------------------------------------------------------------*/
624 static void
625 object_changed_cb (glLabelObject   *object,
626                    glViewHighlight *view_highlight)
627 {
628         gl_debug (DEBUG_VIEW, "START");
629
630         g_return_if_fail (view_highlight && GL_IS_VIEW_HIGHLIGHT (view_highlight));
631         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
632
633         switch (view_highlight->private->style) {
634
635         case GL_VIEW_HIGHLIGHT_BOX_RESIZABLE:
636         case GL_VIEW_HIGHLIGHT_ELLIPSE_RESIZABLE:
637                 update_resizable_box (view_highlight);
638                 break;
639
640         case GL_VIEW_HIGHLIGHT_LINE_RESIZABLE:
641                 update_resizable_line (view_highlight);
642                 break;
643
644         case GL_VIEW_HIGHLIGHT_SIMPLE:
645                 update_simple (view_highlight);
646                 break;
647
648         default:
649                 g_warning ("Invalid resizable highlight style");
650
651         }
652
653         gl_debug (DEBUG_VIEW, "END");
654 }
655
656 /*---------------------------------------------------------------------------*/
657 /* PRIVATE.  Update a resizable box highlight.                               */
658 /*---------------------------------------------------------------------------*/
659 static void
660 update_resizable_box  (glViewHighlight *view_highlight)
661 {
662         gdouble w, h;
663
664         gl_debug (DEBUG_VIEW, "START");
665
666         g_return_if_fail (view_highlight && GL_IS_VIEW_HIGHLIGHT (view_highlight));
667
668         gl_label_object_get_size (view_highlight->private->object, &w, &h);
669
670
671         gnome_canvas_item_set (view_highlight->private->outline,
672                                "x1", -0.5,
673                                "y1", -0.5,
674                                "x2", w + 0.5,
675                                "y2", h + 0.5,
676                                NULL);
677
678         gnome_canvas_item_set (view_highlight->private->tl,
679                                "x1", -1.0,
680                                "y1", -1.0,
681                                "x2", +1.0,
682                                "y2", +1.0,
683                                NULL);
684
685         gnome_canvas_item_set (view_highlight->private->tr,
686                                "x1", w - 1.0,
687                                "y1", -1.0,
688                                "x2", w + 1.0,
689                                "y2", +1.0,
690                                NULL);
691
692         gnome_canvas_item_set (view_highlight->private->bl,
693                                "x1", -1.0,
694                                "y1", h - 1.0,
695                                "x2", +1.0,
696                                "y2", h + 1.0,
697                                NULL);
698
699         gnome_canvas_item_set (view_highlight->private->br,
700                                "x1", w - 1.0,
701                                "y1", h - 1.0,
702                                "x2", w + 1.0,
703                                "y2", h + 1.0,
704                                NULL);
705
706         gnome_canvas_item_set (view_highlight->private->sl,
707                                "x1", -1.0,
708                                "y1", h / 2.0 - 1.0,
709                                "x2", +1.0,
710                                "y2", h / 2.0 + 1.0,
711                                NULL);
712
713         gnome_canvas_item_set (view_highlight->private->sr,
714                                "x1", w - 1.0,
715                                "y1", h / 2.0 - 1.0,
716                                "x2", w + 1.0,
717                                "y2", h / 2.0 + 1.0,
718                                NULL);
719
720         gnome_canvas_item_set (view_highlight->private->st,
721                                "x1", w / 2.0 - 1.0,
722                                "y1", -1.0,
723                                "x2", w / 2.0 + 1.0,
724                                "y2", +1.0,
725                                NULL);
726
727         gnome_canvas_item_set (view_highlight->private->sb,
728                                "x1", w / 2.0 - 1.0,
729                                "y1", h - 1.0,
730                                "x2", w / 2.0 + 1.0,
731                                "y2", h + 1.0,
732                                NULL);
733
734         /* send to top, then lower below all items that form the foregound */
735         gnome_canvas_item_raise_to_top (view_highlight->private->group);
736         gl_view_raise_fg (view_highlight->private->view);
737
738         gl_debug (DEBUG_VIEW, "END");
739 }
740
741 /*---------------------------------------------------------------------------*/
742 /* PRIVATE.  Update a resizable line highlight.                              */
743 /*---------------------------------------------------------------------------*/
744 static void
745 update_resizable_line (glViewHighlight *view_highlight)
746 {
747         gdouble dx, dy;
748         GnomeCanvasPoints *points;
749
750         gl_debug (DEBUG_VIEW, "START");
751
752         g_return_if_fail (view_highlight && GL_IS_VIEW_HIGHLIGHT (view_highlight));
753
754         gl_label_object_get_size (view_highlight->private->object, &dx, &dy);
755
756         points = gnome_canvas_points_new (2);
757
758         points->coords[0] = 0.0;
759         points->coords[1] = 0.0;
760         points->coords[2] = dx;
761         points->coords[3] = dy;
762         gnome_canvas_item_set (view_highlight->private->outline, "points", points, NULL);
763
764         gnome_canvas_item_set (view_highlight->private->p1,
765                                "x1", -1.0,
766                                "y1", -1.0,
767                                "x2", +1.0,
768                                "y2", +1.0,
769                                NULL);
770
771         gnome_canvas_item_set (view_highlight->private->p2,
772                                "x1", dx - 1.0,
773                                "y1", dy - 1.0,
774                                "x2", dx + 1.0,
775                                "y2", dy + 1.0,
776                                NULL);
777
778         gnome_canvas_points_free (points);
779
780         /* send to top, then lower below all items that form the foregound */
781         gnome_canvas_item_raise_to_top (view_highlight->private->group);
782         gl_view_raise_fg (view_highlight->private->view);
783
784         gl_debug (DEBUG_VIEW, "END");
785 }
786
787 /*---------------------------------------------------------------------------*/
788 /* PRIVATE.  Update a simple box highlight.                                  */
789 /*---------------------------------------------------------------------------*/
790 static void
791 update_simple (glViewHighlight *view_highlight)
792 {
793         gdouble w, h;
794
795         gl_debug (DEBUG_VIEW, "START");
796
797         g_return_if_fail (view_highlight && GL_IS_VIEW_HIGHLIGHT (view_highlight));
798
799         gl_label_object_get_size (view_highlight->private->object, &w, &h);
800
801         gnome_canvas_item_set (view_highlight->private->outline,
802                                "x2", w + 0.5,
803                                "y2", h + 0.5,
804                                NULL);
805
806         /* send to top, then lower below all items that form the foregound */
807         gnome_canvas_item_raise_to_top (view_highlight->private->group);
808         gl_view_raise_fg (view_highlight->private->view);
809
810         gl_debug (DEBUG_VIEW, "END");
811 }
812
813 /*---------------------------------------------------------------------------*/
814 /* PRIVATE.  "Top-left" Resize event handler.                    */
815 /*---------------------------------------------------------------------------*/
816 static int
817 tl_resize_event_handler (GnomeCanvasItem *handle_item,
818                          GdkEvent        *event,
819                          glViewHighlight *view_highlight)
820 {
821         gdouble x, y, w, h;
822         static gdouble x2, y2;
823         static gboolean dragging = FALSE;
824         glLabelObject *object;
825         GdkCursor *cursor;
826
827         if ( view_highlight->private->view->state != GL_VIEW_STATE_ARROW ) {
828                 /* don't interfere with object creation modes */
829                 return FALSE;
830         }
831
832         object = view_highlight->private->object;;
833         gl_label_object_get_position (object, &x, &y);
834         gl_label_object_get_size (object, &w, &h);
835
836         switch (event->type) {
837
838         case GDK_BUTTON_PRESS:
839                 switch (event->button.button) {
840                 case 1:
841                         dragging = TRUE;
842                         gnome_canvas_item_grab (handle_item,
843                                                 GDK_POINTER_MOTION_MASK |
844                                                 GDK_BUTTON_RELEASE_MASK |
845                                                 GDK_BUTTON_PRESS_MASK,
846                                                 NULL, event->button.time);
847                         /* Anchor to bottom-right corner */
848                         x2 = x + w;
849                         y2 = y + h;
850                         return TRUE;
851
852                 default:
853                         return FALSE;
854                 }
855
856         case GDK_BUTTON_RELEASE:
857                 switch (event->button.button) {
858                 case 1:
859                         dragging = FALSE;
860                         gnome_canvas_item_ungrab (handle_item,
861                                                   event->button.time);
862                         x = MIN (event->button.x, x2 - MIN_ITEM_SIZE);
863                         y = MIN (event->button.y, y2 - MIN_ITEM_SIZE);
864                         w = MAX (x2 - event->button.x, MIN_ITEM_SIZE);
865                         h = MAX (y2 - event->button.y, MIN_ITEM_SIZE);
866                         gl_label_object_set_position (object, x, y);
867                         gl_label_object_set_size (object, w, h);
868                         return TRUE;
869
870                 default:
871                         return FALSE;
872                 }
873
874         case GDK_MOTION_NOTIFY:
875                 if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
876                         x = MIN (event->motion.x, x2 - MIN_ITEM_SIZE);
877                         y = MIN (event->motion.y, y2 - MIN_ITEM_SIZE);
878                         w = MAX (x2 - event->motion.x, MIN_ITEM_SIZE);
879                         h = MAX (y2 - event->motion.y, MIN_ITEM_SIZE);
880                         gl_label_object_set_position (object, x, y);
881                         gl_label_object_set_size (object, w, h);
882                         return TRUE;
883                 } else {
884                         return FALSE;
885                 }
886
887         case GDK_ENTER_NOTIFY:
888                 cursor = gdk_cursor_new (GDK_CROSSHAIR);
889                 gdk_window_set_cursor (view_highlight->private->view->canvas->window,
890                                        cursor);
891                 gdk_cursor_unref (cursor);
892                 return TRUE;
893
894         case GDK_LEAVE_NOTIFY:
895                 cursor = gdk_cursor_new (GDK_LEFT_PTR);
896                 gdk_window_set_cursor (view_highlight->private->view->canvas->window,
897                                        cursor);
898                 gdk_cursor_unref (cursor);
899                 return TRUE;
900
901         default:
902                 return FALSE;
903         }
904
905 }
906
907 /*---------------------------------------------------------------------------*/
908 /* PRIVATE.  "Top-right" Resize event handler.                               */
909 /*---------------------------------------------------------------------------*/
910 static int
911 tr_resize_event_handler (GnomeCanvasItem *handle_item,
912                          GdkEvent        *event,
913                          glViewHighlight *view_highlight)
914 {
915         gdouble x, y, w, h;
916         static gdouble x1, y2;
917         static gboolean dragging = FALSE;
918         glLabelObject *object;
919         GdkCursor *cursor;
920
921         if ( view_highlight->private->view->state != GL_VIEW_STATE_ARROW ) {
922                 /* don't interfere with object creation modes */
923                 return FALSE;
924         }
925
926         object = view_highlight->private->object;;
927         gl_label_object_get_position (object, &x, &y);
928         gl_label_object_get_size (object, &w, &h);
929
930         switch (event->type) {
931
932         case GDK_BUTTON_PRESS:
933                 switch (event->button.button) {
934                 case 1:
935                         dragging = TRUE;
936                         gnome_canvas_item_grab (handle_item,
937                                                 GDK_POINTER_MOTION_MASK |
938                                                 GDK_BUTTON_RELEASE_MASK |
939                                                 GDK_BUTTON_PRESS_MASK,
940                                                 NULL, event->button.time);
941                         /* Anchor to bottom-left corner */
942                         x1 = x;
943                         y2 = y + h;
944                         return TRUE;
945
946                 default:
947                         return FALSE;
948                 }
949
950         case GDK_BUTTON_RELEASE:
951                 switch (event->button.button) {
952                 case 1:
953                         dragging = FALSE;
954                         gnome_canvas_item_ungrab (handle_item,
955                                                   event->button.time);
956                         x = x1;
957                         y = MIN (event->button.y, y2 - MIN_ITEM_SIZE);
958                         w = MAX (event->button.x - x1, MIN_ITEM_SIZE);
959                         h = MAX (y2 - event->button.y, MIN_ITEM_SIZE);
960                         gl_label_object_set_position (object, x, y);
961                         gl_label_object_set_size (object, w, h);
962                         return TRUE;
963
964                 default:
965                         return FALSE;
966                 }
967
968         case GDK_MOTION_NOTIFY:
969                 if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
970                         x = x1;
971                         y = MIN (event->motion.y, y2 - MIN_ITEM_SIZE);
972                         w = MAX (event->motion.x - x1, MIN_ITEM_SIZE);
973                         h = MAX (y2 - event->motion.y, MIN_ITEM_SIZE);
974                         gl_label_object_set_position (object, x, y);
975                         gl_label_object_set_size (object, w, h);
976                         return TRUE;
977                 } else {
978                         return FALSE;
979                 }
980
981         case GDK_ENTER_NOTIFY:
982                 cursor = gdk_cursor_new (GDK_CROSSHAIR);
983                 gdk_window_set_cursor (view_highlight->private->view->canvas->window,
984                                        cursor);
985                 gdk_cursor_unref (cursor);
986                 return TRUE;
987
988         case GDK_LEAVE_NOTIFY:
989                 cursor = gdk_cursor_new (GDK_LEFT_PTR);
990                 gdk_window_set_cursor (view_highlight->private->view->canvas->window,
991                                        cursor);
992                 gdk_cursor_unref (cursor);
993                 return TRUE;
994
995         default:
996                 return FALSE;
997         }
998
999 }
1000
1001 /*---------------------------------------------------------------------------*/
1002 /* PRIVATE.  "Bottom-left" Resize event handler.                             */
1003 /*---------------------------------------------------------------------------*/
1004 static int
1005 bl_resize_event_handler (GnomeCanvasItem *handle_item,
1006                          GdkEvent        *event,
1007                          glViewHighlight *view_highlight)
1008 {
1009         gdouble x, y, w, h;
1010         static gdouble x2, y1;
1011         static gboolean dragging = FALSE;
1012         glLabelObject *object;
1013         GdkCursor *cursor;
1014
1015         if ( view_highlight->private->view->state != GL_VIEW_STATE_ARROW ) {
1016                 /* don't interfere with object creation modes */
1017                 return FALSE;
1018         }
1019
1020         object = view_highlight->private->object;;
1021         gl_label_object_get_position (object, &x, &y);
1022         gl_label_object_get_size (object, &w, &h);
1023
1024         switch (event->type) {
1025
1026         case GDK_BUTTON_PRESS:
1027                 switch (event->button.button) {
1028                 case 1:
1029                         dragging = TRUE;
1030                         gnome_canvas_item_grab (handle_item,
1031                                                 GDK_POINTER_MOTION_MASK |
1032                                                 GDK_BUTTON_RELEASE_MASK |
1033                                                 GDK_BUTTON_PRESS_MASK,
1034                                                 NULL, event->button.time);
1035                         /* Anchor to top-right corner */
1036                         x2 = x + w;
1037                         y1 = y;
1038                         return TRUE;
1039
1040                 default:
1041                         return FALSE;
1042                 }
1043
1044         case GDK_BUTTON_RELEASE:
1045                 switch (event->button.button) {
1046                 case 1:
1047                         dragging = FALSE;
1048                         gnome_canvas_item_ungrab (handle_item,
1049                                                   event->button.time);
1050                         x = MIN (event->button.x, x2 - MIN_ITEM_SIZE);
1051                         y = y1;
1052                         w = MAX (x2 - event->button.x, MIN_ITEM_SIZE);
1053                         h = MAX (event->button.y - y1, MIN_ITEM_SIZE);
1054                         gl_label_object_set_position (object, x, y);
1055                         gl_label_object_set_size (object, w, h);
1056                         return TRUE;
1057
1058                 default:
1059                         return FALSE;
1060                 }
1061
1062         case GDK_MOTION_NOTIFY:
1063                 if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
1064                         x = MIN (event->motion.x, x2 - MIN_ITEM_SIZE);
1065                         y = y1;
1066                         w = MAX (x2 - event->motion.x, MIN_ITEM_SIZE);
1067                         h = MAX (event->motion.y - y1, MIN_ITEM_SIZE);
1068                         gl_label_object_set_position (object, x, y);
1069                         gl_label_object_set_size (object, w, h);
1070                         return TRUE;
1071                 } else {
1072                         return FALSE;
1073                 }
1074
1075         case GDK_ENTER_NOTIFY:
1076                 cursor = gdk_cursor_new (GDK_CROSSHAIR);
1077                 gdk_window_set_cursor (view_highlight->private->view->canvas->window,
1078                                        cursor);
1079                 gdk_cursor_unref (cursor);
1080                 return TRUE;
1081
1082         case GDK_LEAVE_NOTIFY:
1083                 cursor = gdk_cursor_new (GDK_LEFT_PTR);
1084                 gdk_window_set_cursor (view_highlight->private->view->canvas->window,
1085                                        cursor);
1086                 gdk_cursor_unref (cursor);
1087                 return TRUE;
1088
1089         default:
1090                 return FALSE;
1091         }
1092
1093 }
1094
1095 /*---------------------------------------------------------------------------*/
1096 /* PRIVATE.  "Bottom-right" Resize event handler.                            */
1097 /*---------------------------------------------------------------------------*/
1098 static int
1099 br_resize_event_handler (GnomeCanvasItem *handle_item,
1100                          GdkEvent        *event,
1101                          glViewHighlight *view_highlight)
1102 {
1103         gdouble x, y, w, h;
1104         static gdouble x1, y1;
1105         static gboolean dragging = FALSE;
1106         glLabelObject *object;
1107         GdkCursor *cursor;
1108
1109         if ( view_highlight->private->view->state != GL_VIEW_STATE_ARROW ) {
1110                 /* don't interfere with object creation modes */
1111                 return FALSE;
1112         }
1113
1114         object = view_highlight->private->object;;
1115         gl_label_object_get_position (object, &x, &y);
1116         gl_label_object_get_size (object, &w, &h);
1117
1118         switch (event->type) {
1119
1120         case GDK_BUTTON_PRESS:
1121                 switch (event->button.button) {
1122                 case 1:
1123                         dragging = TRUE;
1124                         gnome_canvas_item_grab (handle_item,
1125                                                 GDK_POINTER_MOTION_MASK |
1126                                                 GDK_BUTTON_RELEASE_MASK |
1127                                                 GDK_BUTTON_PRESS_MASK,
1128                                                 NULL, event->button.time);
1129                         /* Anchor to top-left corner */
1130                         x1 = x;
1131                         y1 = y;
1132                         return TRUE;
1133
1134                 default:
1135                         return FALSE;
1136                 }
1137
1138         case GDK_BUTTON_RELEASE:
1139                 switch (event->button.button) {
1140                 case 1:
1141                         dragging = FALSE;
1142                         gnome_canvas_item_ungrab (handle_item,
1143                                                   event->button.time);
1144                         x = x1;
1145                         y = y1;
1146                         w = MAX (event->button.x - x1, MIN_ITEM_SIZE);
1147                         h = MAX (event->button.y - y1, MIN_ITEM_SIZE);
1148                         gl_label_object_set_position (object, x, y);
1149                         gl_label_object_set_size (object, w, h);
1150                         return TRUE;
1151
1152                 default:
1153                         return FALSE;
1154                 }
1155
1156         case GDK_MOTION_NOTIFY:
1157                 if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
1158                         x = x1;
1159                         y = y1;
1160                         w = MAX (event->motion.x - x1, MIN_ITEM_SIZE);
1161                         h = MAX (event->motion.y - y1, MIN_ITEM_SIZE);
1162                         gl_label_object_set_position (object, x, y);
1163                         gl_label_object_set_size (object, w, h);
1164                         return TRUE;
1165                 } else {
1166                         return FALSE;
1167                 }
1168
1169         case GDK_ENTER_NOTIFY:
1170                 cursor = gdk_cursor_new (GDK_CROSSHAIR);
1171                 gdk_window_set_cursor (view_highlight->private->view->canvas->window,
1172                                        cursor);
1173                 gdk_cursor_unref (cursor);
1174                 return TRUE;
1175
1176         case GDK_LEAVE_NOTIFY:
1177                 cursor = gdk_cursor_new (GDK_LEFT_PTR);
1178                 gdk_window_set_cursor (view_highlight->private->view->canvas->window,
1179                                        cursor);
1180                 gdk_cursor_unref (cursor);
1181                 return TRUE;
1182
1183         default:
1184                 return FALSE;
1185         }
1186
1187 }
1188
1189 /*---------------------------------------------------------------------------*/
1190 /* PRIVATE.  "Left-side" Resize event handler.                               */
1191 /*---------------------------------------------------------------------------*/
1192 static int
1193 sl_resize_event_handler (GnomeCanvasItem *handle_item,
1194                          GdkEvent        *event,
1195                          glViewHighlight *view_highlight)
1196 {
1197         gdouble x, y, w, h;
1198         static gdouble x2;
1199         static gboolean dragging = FALSE;
1200         glLabelObject *object;
1201         GdkCursor *cursor;
1202
1203         if ( view_highlight->private->view->state != GL_VIEW_STATE_ARROW ) {
1204                 /* don't interfere with object creation modes */
1205                 return FALSE;
1206         }
1207
1208         object = view_highlight->private->object;;
1209         gl_label_object_get_position (object, &x, &y);
1210         gl_label_object_get_size (object, &w, &h);
1211
1212         switch (event->type) {
1213
1214         case GDK_BUTTON_PRESS:
1215                 switch (event->button.button) {
1216                 case 1:
1217                         dragging = TRUE;
1218                         gnome_canvas_item_grab (handle_item,
1219                                                 GDK_POINTER_MOTION_MASK |
1220                                                 GDK_BUTTON_RELEASE_MASK |
1221                                                 GDK_BUTTON_PRESS_MASK,
1222                                                 NULL, event->button.time);
1223                         /* Anchor to right side */
1224                         x2 = x + w;
1225                         return TRUE;
1226
1227                 default:
1228                         return FALSE;
1229                 }
1230
1231         case GDK_BUTTON_RELEASE:
1232                 switch (event->button.button) {
1233                 case 1:
1234                         dragging = FALSE;
1235                         gnome_canvas_item_ungrab (handle_item,
1236                                                   event->button.time);
1237                         x = MIN (event->button.x, x2 - MIN_ITEM_SIZE);
1238                         w = MAX (x2 - event->button.x, MIN_ITEM_SIZE);
1239                         gl_label_object_set_position (object, x, y);
1240                         gl_label_object_set_size (object, w, h);
1241                         return TRUE;
1242
1243                 default:
1244                         return FALSE;
1245                 }
1246
1247         case GDK_MOTION_NOTIFY:
1248                 if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
1249                         x = MIN (event->motion.x, x2 - MIN_ITEM_SIZE);
1250                         w = MAX (x2 - event->motion.x, MIN_ITEM_SIZE);
1251                         gl_label_object_set_position (object, x, y);
1252                         gl_label_object_set_size (object, w, h);
1253                         return TRUE;
1254                 } else {
1255                         return FALSE;
1256                 }
1257
1258         case GDK_ENTER_NOTIFY:
1259                 cursor = gdk_cursor_new (GDK_CROSSHAIR);
1260                 gdk_window_set_cursor (view_highlight->private->view->canvas->window,
1261                                        cursor);
1262                 gdk_cursor_unref (cursor);
1263                 return TRUE;
1264
1265         case GDK_LEAVE_NOTIFY:
1266                 cursor = gdk_cursor_new (GDK_LEFT_PTR);
1267                 gdk_window_set_cursor (view_highlight->private->view->canvas->window,
1268                                        cursor);
1269                 gdk_cursor_unref (cursor);
1270                 return TRUE;
1271
1272         default:
1273                 return FALSE;
1274         }
1275
1276 }
1277
1278 /*---------------------------------------------------------------------------*/
1279 /* PRIVATE.  "Right-side" Resize event handler.                              */
1280 /*---------------------------------------------------------------------------*/
1281 static int
1282 sr_resize_event_handler (GnomeCanvasItem *handle_item,
1283                          GdkEvent        *event,
1284                          glViewHighlight *view_highlight)
1285 {
1286         gdouble x, y, w, h;
1287         static gdouble x1;
1288         static gboolean dragging = FALSE;
1289         glLabelObject *object;
1290         GdkCursor *cursor;
1291
1292         if ( view_highlight->private->view->state != GL_VIEW_STATE_ARROW ) {
1293                 /* don't interfere with object creation modes */
1294                 return FALSE;
1295         }
1296
1297         object = view_highlight->private->object;;
1298         gl_label_object_get_position (object, &x, &y);
1299         gl_label_object_get_size (object, &w, &h);
1300
1301         switch (event->type) {
1302
1303         case GDK_BUTTON_PRESS:
1304                 switch (event->button.button) {
1305                 case 1:
1306                         dragging = TRUE;
1307                         gnome_canvas_item_grab (handle_item,
1308                                                 GDK_POINTER_MOTION_MASK |
1309                                                 GDK_BUTTON_RELEASE_MASK |
1310                                                 GDK_BUTTON_PRESS_MASK,
1311                                                 NULL, event->button.time);
1312                         /* Anchor to left side */
1313                         x1 = x;
1314                         return TRUE;
1315
1316                 default:
1317                         return FALSE;
1318                 }
1319
1320         case GDK_BUTTON_RELEASE:
1321                 switch (event->button.button) {
1322                 case 1:
1323                         dragging = FALSE;
1324                         gnome_canvas_item_ungrab (handle_item,
1325                                                   event->button.time);
1326                         x = x1;
1327                         w = MAX (event->button.x - x1, MIN_ITEM_SIZE);
1328                         gl_label_object_set_position (object, x, y);
1329                         gl_label_object_set_size (object, w, h);
1330                         return TRUE;
1331
1332                 default:
1333                         return FALSE;
1334                 }
1335
1336         case GDK_MOTION_NOTIFY:
1337                 if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
1338                         x = x1;
1339                         w = MAX (event->motion.x - x1, MIN_ITEM_SIZE);
1340                         gl_label_object_set_position (object, x, y);
1341                         gl_label_object_set_size (object, w, h);
1342                         return TRUE;
1343                 } else {
1344                         return FALSE;
1345                 }
1346
1347         case GDK_ENTER_NOTIFY:
1348                 cursor = gdk_cursor_new (GDK_CROSSHAIR);
1349                 gdk_window_set_cursor (view_highlight->private->view->canvas->window,
1350                                        cursor);
1351                 gdk_cursor_unref (cursor);
1352                 return TRUE;
1353
1354         case GDK_LEAVE_NOTIFY:
1355                 cursor = gdk_cursor_new (GDK_LEFT_PTR);
1356                 gdk_window_set_cursor (view_highlight->private->view->canvas->window,
1357                                        cursor);
1358                 gdk_cursor_unref (cursor);
1359                 return TRUE;
1360
1361         default:
1362                 return FALSE;
1363         }
1364
1365 }
1366
1367 /*---------------------------------------------------------------------------*/
1368 /* PRIVATE.  "Top-side" Resize event handler.                                */
1369 /*---------------------------------------------------------------------------*/
1370 static int
1371 st_resize_event_handler (GnomeCanvasItem *handle_item,
1372                          GdkEvent        *event,
1373                          glViewHighlight *view_highlight)
1374 {
1375         gdouble x, y, w, h;
1376         static gdouble y2;
1377         static gboolean dragging = FALSE;
1378         glLabelObject *object;
1379         GdkCursor *cursor;
1380
1381         if ( view_highlight->private->view->state != GL_VIEW_STATE_ARROW ) {
1382                 /* don't interfere with object creation modes */
1383                 return FALSE;
1384         }
1385
1386         object = view_highlight->private->object;;
1387         gl_label_object_get_position (object, &x, &y);
1388         gl_label_object_get_size (object, &w, &h);
1389
1390         switch (event->type) {
1391
1392         case GDK_BUTTON_PRESS:
1393                 switch (event->button.button) {
1394                 case 1:
1395                         dragging = TRUE;
1396                         gnome_canvas_item_grab (handle_item,
1397                                                 GDK_POINTER_MOTION_MASK |
1398                                                 GDK_BUTTON_RELEASE_MASK |
1399                                                 GDK_BUTTON_PRESS_MASK,
1400                                                 NULL, event->button.time);
1401                         /* Anchor to bottom-right corner */
1402                         y2 = y + h;
1403                         return TRUE;
1404
1405                 default:
1406                         return FALSE;
1407                 }
1408
1409         case GDK_BUTTON_RELEASE:
1410                 switch (event->button.button) {
1411                 case 1:
1412                         dragging = FALSE;
1413                         gnome_canvas_item_ungrab (handle_item,
1414                                                   event->button.time);
1415                         y = MIN (event->button.y, y2 - MIN_ITEM_SIZE);
1416                         h = MAX (y2 - event->button.y, MIN_ITEM_SIZE);
1417                         gl_label_object_set_position (object, x, y);
1418                         gl_label_object_set_size (object, w, h);
1419                         return TRUE;
1420
1421                 default:
1422                         return FALSE;
1423                 }
1424
1425         case GDK_MOTION_NOTIFY:
1426                 if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
1427                         y = MIN (event->motion.y, y2 - MIN_ITEM_SIZE);
1428                         h = MAX (y2 - event->motion.y, MIN_ITEM_SIZE);
1429                         gl_label_object_set_position (object, x, y);
1430                         gl_label_object_set_size (object, w, h);
1431                         return TRUE;
1432                 } else {
1433                         return FALSE;
1434                 }
1435
1436         case GDK_ENTER_NOTIFY:
1437                 cursor = gdk_cursor_new (GDK_CROSSHAIR);
1438                 gdk_window_set_cursor (view_highlight->private->view->canvas->window,
1439                                        cursor);
1440                 gdk_cursor_unref (cursor);
1441                 return TRUE;
1442
1443         case GDK_LEAVE_NOTIFY:
1444                 cursor = gdk_cursor_new (GDK_LEFT_PTR);
1445                 gdk_window_set_cursor (view_highlight->private->view->canvas->window,
1446                                        cursor);
1447                 gdk_cursor_unref (cursor);
1448                 return TRUE;
1449
1450         default:
1451                 return FALSE;
1452         }
1453
1454 }
1455
1456 /*---------------------------------------------------------------------------*/
1457 /* PRIVATE.  "Bottom-side" Resize event handler.                             */
1458 /*---------------------------------------------------------------------------*/
1459 static int
1460 sb_resize_event_handler (GnomeCanvasItem *handle_item,
1461                          GdkEvent        *event,
1462                          glViewHighlight *view_highlight)
1463 {
1464         gdouble x, y, w, h;
1465         static gdouble y1;
1466         static gboolean dragging = FALSE;
1467         glLabelObject *object;
1468         GdkCursor *cursor;
1469
1470         if ( view_highlight->private->view->state != GL_VIEW_STATE_ARROW ) {
1471                 /* don't interfere with object creation modes */
1472                 return FALSE;
1473         }
1474
1475         object = view_highlight->private->object;;
1476         gl_label_object_get_position (object, &x, &y);
1477         gl_label_object_get_size (object, &w, &h);
1478
1479         switch (event->type) {
1480
1481         case GDK_BUTTON_PRESS:
1482                 switch (event->button.button) {
1483                 case 1:
1484                         dragging = TRUE;
1485                         gnome_canvas_item_grab (handle_item,
1486                                                 GDK_POINTER_MOTION_MASK |
1487                                                 GDK_BUTTON_RELEASE_MASK |
1488                                                 GDK_BUTTON_PRESS_MASK,
1489                                                 NULL, event->button.time);
1490                         /* Anchor to top side */
1491                         y1 = y;
1492                         return TRUE;
1493
1494                 default:
1495                         return FALSE;
1496                 }
1497
1498         case GDK_BUTTON_RELEASE:
1499                 switch (event->button.button) {
1500                 case 1:
1501                         dragging = FALSE;
1502                         gnome_canvas_item_ungrab (handle_item,
1503                                                   event->button.time);
1504                         y = y1;
1505                         h = MAX (event->button.y - y1, MIN_ITEM_SIZE);
1506                         gl_label_object_set_position (object, x, y);
1507                         gl_label_object_set_size (object, w, h);
1508                         return TRUE;
1509
1510                 default:
1511                         return FALSE;
1512                 }
1513
1514         case GDK_MOTION_NOTIFY:
1515                 if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
1516                         y = y1;
1517                         h = MAX (event->motion.y - y1, MIN_ITEM_SIZE);
1518                         gl_label_object_set_position (object, x, y);
1519                         gl_label_object_set_size (object, w, h);
1520                         return TRUE;
1521                 } else {
1522                         return FALSE;
1523                 }
1524
1525         case GDK_ENTER_NOTIFY:
1526                 cursor = gdk_cursor_new (GDK_CROSSHAIR);
1527                 gdk_window_set_cursor (view_highlight->private->view->canvas->window,
1528                                        cursor);
1529                 gdk_cursor_unref (cursor);
1530                 return TRUE;
1531
1532         case GDK_LEAVE_NOTIFY:
1533                 cursor = gdk_cursor_new (GDK_LEFT_PTR);
1534                 gdk_window_set_cursor (view_highlight->private->view->canvas->window,
1535                                        cursor);
1536                 gdk_cursor_unref (cursor);
1537                 return TRUE;
1538
1539         default:
1540                 return FALSE;
1541         }
1542
1543 }
1544
1545 /*---------------------------------------------------------------------------*/
1546 /* PRIVATE.  Resize "P1" event handler.                                      */
1547 /*---------------------------------------------------------------------------*/
1548 static int
1549 p1_resize_event_handler (GnomeCanvasItem *handle_item,
1550                          GdkEvent        *event,
1551                          glViewHighlight *view_highlight)
1552 {
1553         gdouble x, y, dx, dy;
1554         static gdouble x0, y0;
1555         static gboolean dragging = FALSE;
1556         glLabelObject *object;
1557         GdkCursor *cursor;
1558
1559         if ( view_highlight->private->view->state != GL_VIEW_STATE_ARROW ) {
1560                 /* don't interfere with object creation modes */
1561                 return FALSE;
1562         }
1563
1564         object = view_highlight->private->object;;
1565         gl_label_object_get_position (object, &x, &y);
1566         gl_label_object_get_size (object, &dx, &dy);
1567
1568         switch (event->type) {
1569
1570         case GDK_BUTTON_PRESS:
1571                 switch (event->button.button) {
1572                 case 1:
1573                         dragging = TRUE;
1574                         gnome_canvas_item_grab (handle_item,
1575                                                 GDK_POINTER_MOTION_MASK |
1576                                                 GDK_BUTTON_RELEASE_MASK |
1577                                                 GDK_BUTTON_PRESS_MASK,
1578                                                 NULL, event->button.time);
1579                         /* Anchor to P2 */
1580                         x0 = x + dx;
1581                         y0 = y + dy;
1582                         return TRUE;
1583
1584                 default:
1585                         return FALSE;
1586                 }
1587
1588         case GDK_BUTTON_RELEASE:
1589                 switch (event->button.button) {
1590                 case 1:
1591                         dragging = FALSE;
1592                         gnome_canvas_item_ungrab (handle_item,
1593                                                   event->button.time);
1594                         x = x0;
1595                         y = y0;
1596                         dx = (event->button.x - x0);
1597                         dy = (event->button.y - y0);
1598                         gl_label_object_set_position (object, x, y);
1599                         gl_label_object_set_size (object, dx, dy);
1600                         return TRUE;
1601
1602                 default:
1603                         return FALSE;
1604                 }
1605
1606         case GDK_MOTION_NOTIFY:
1607                 if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
1608                         x = x0;
1609                         y = y0;
1610                         dx = (event->motion.x - x0);
1611                         dy = (event->motion.y - y0);
1612                         gl_label_object_set_position (object, x, y);
1613                         gl_label_object_set_size (object, dx, dy);
1614                         return TRUE;
1615                 } else {
1616                         return FALSE;
1617                 }
1618
1619         case GDK_ENTER_NOTIFY:
1620                 cursor = gdk_cursor_new (GDK_CROSSHAIR);
1621                 gdk_window_set_cursor (view_highlight->private->view->canvas->window,
1622                                        cursor);
1623                 gdk_cursor_unref (cursor);
1624                 return TRUE;
1625
1626         case GDK_LEAVE_NOTIFY:
1627                 cursor = gdk_cursor_new (GDK_LEFT_PTR);
1628                 gdk_window_set_cursor (view_highlight->private->view->canvas->window,
1629                                        cursor);
1630                 gdk_cursor_unref (cursor);
1631                 return TRUE;
1632
1633         default:
1634                 return FALSE;
1635         }
1636
1637 }
1638
1639 /*---------------------------------------------------------------------------*/
1640 /* PRIVATE.  Resize "P2" event handler.                                      */
1641 /*---------------------------------------------------------------------------*/
1642 static int
1643 p2_resize_event_handler (GnomeCanvasItem *handle_item,
1644                          GdkEvent        *event,
1645                          glViewHighlight *view_highlight)
1646 {
1647         gdouble x, y, dx, dy;
1648         static gdouble x0, y0;
1649         static gboolean dragging = FALSE;
1650         glLabelObject *object;
1651         GdkCursor *cursor;
1652
1653         if ( view_highlight->private->view->state != GL_VIEW_STATE_ARROW ) {
1654                 /* don't interfere with object creation modes */
1655                 return FALSE;
1656         }
1657
1658         object = view_highlight->private->object;;
1659         gl_label_object_get_position (object, &x, &y);
1660         gl_label_object_get_size (object, &dx, &dy);
1661
1662         switch (event->type) {
1663
1664         case GDK_BUTTON_PRESS:
1665                 switch (event->button.button) {
1666                 case 1:
1667                         dragging = TRUE;
1668                         gnome_canvas_item_grab (handle_item,
1669                                                 GDK_POINTER_MOTION_MASK |
1670                                                 GDK_BUTTON_RELEASE_MASK |
1671                                                 GDK_BUTTON_PRESS_MASK,
1672                                                 NULL, event->button.time);
1673                         /* Anchor to P1 */
1674                         x0 = x;
1675                         y0 = y;
1676                         return TRUE;
1677
1678                 default:
1679                         return FALSE;
1680                 }
1681
1682         case GDK_BUTTON_RELEASE:
1683                 switch (event->button.button) {
1684                 case 1:
1685                         dragging = FALSE;
1686                         gnome_canvas_item_ungrab (handle_item,
1687                                                   event->button.time);
1688                         x = x0;
1689                         y = y0;
1690                         dx = (event->button.x - x0);
1691                         dy = (event->button.y - y0);
1692                         gl_label_object_set_position (object, x, y);
1693                         gl_label_object_set_size (object, dx, dy);
1694                         return TRUE;
1695
1696                 default:
1697                         return FALSE;
1698                 }
1699
1700         case GDK_MOTION_NOTIFY:
1701                 if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
1702                         x = x0;
1703                         y = y0;
1704                         dx = (event->motion.x - x0);
1705                         dy = (event->motion.y - y0);
1706                         gl_label_object_set_position (object, x, y);
1707                         gl_label_object_set_size (object, dx, dy);
1708                         return TRUE;
1709                 } else {
1710                         return FALSE;
1711                 }
1712
1713         case GDK_ENTER_NOTIFY:
1714                 cursor = gdk_cursor_new (GDK_CROSSHAIR);
1715                 gdk_window_set_cursor (view_highlight->private->view->canvas->window,
1716                                        cursor);
1717                 gdk_cursor_unref (cursor);
1718                 return TRUE;
1719
1720         case GDK_LEAVE_NOTIFY:
1721                 cursor = gdk_cursor_new (GDK_LEFT_PTR);
1722                 gdk_window_set_cursor (view_highlight->private->view->canvas->window,
1723                                        cursor);
1724                 gdk_cursor_unref (cursor);
1725                 return TRUE;
1726
1727         default:
1728                 return FALSE;
1729         }
1730
1731 }
1732
1733 /*---------------------------------------------------------------------------*/
1734 /* PRIVATE.  Passthrough event handler.                                      */
1735 /*---------------------------------------------------------------------------*/
1736 static int
1737 passthrough_event_handler (GnomeCanvasItem *handle_item,
1738                            GdkEvent        *event,
1739                            glViewObject    *view_object)
1740 {
1741         GnomeCanvasItem *group;
1742
1743         group = gl_view_object_get_group (view_object);
1744         return gl_view_item_event_handler (group, event, view_object);
1745 }