]> git.sur5r.net Git - glabels/blob - glabels2/src/view-image.c
Made set_size and get_size into child methods for label-object, and construct_dialog...
[glabels] / glabels2 / src / view-image.c
1 /*
2  *  (GLABELS) Label and Business Card Creation program for GNOME
3  *
4  *  view_image.c:  GLabels label image object widget
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 <glib.h>
24
25 #include "view-image.h"
26
27 #include "view-highlight.h"
28
29 #include "wdgt-line.h"
30 #include "wdgt-fill.h"
31 #include "wdgt-size.h"
32 #include "wdgt-position.h"
33
34 #include "pixmaps/cursor_image.xbm"
35 #include "pixmaps/cursor_image_mask.xbm"
36
37 #include "debug.h"
38
39 /*========================================================*/
40 /* Private macros and constants.                          */
41 /*========================================================*/
42
43 #define DELTA 0.01
44
45 /*========================================================*/
46 /* Private types.                                         */
47 /*========================================================*/
48
49 struct _glViewImagePrivate {
50         GnomeCanvasItem *item;
51
52         /* Page 0 widgets */
53         GtkWidget       *pixmap_entry;
54
55         /* Page 1 widgets */
56         GtkWidget       *position;
57         GtkWidget       *size;
58 };
59
60 /*========================================================*/
61 /* Private globals.                                       */
62 /*========================================================*/
63
64 static glViewObjectClass *parent_class = NULL;
65
66 /* Save state of image file entry */
67 static gchar *image_path = NULL;
68
69
70 /*========================================================*/
71 /* Private function prototypes.                           */
72 /*========================================================*/
73
74 static void      gl_view_image_class_init      (glViewImageClass *klass);
75 static void      gl_view_image_instance_init   (glViewImage    *view_image);
76 static void      gl_view_image_finalize        (GObject        *object);
77
78 static void      update_view_image_cb          (glLabelObject  *object,
79                                                 glViewImage    *view_image);
80
81 static GtkWidget *construct_properties_dialog  (glViewObject   *view_object);
82
83 static void      response_cb                   (GtkDialog      *dialog,
84                                                 gint            response,
85                                                 glViewImage    *view_image);
86
87 static void      file_changed_cb               (GtkEntry       *pixmap_entry,
88                                                 glViewImage    *view_image);
89
90 static void      position_changed_cb           (glWdgtPosition *position,
91                                                 glViewImage    *view_image);
92
93 static void      size_changed_cb               (glWdgtSize     *size,
94                                                 glViewImage    *view_image);
95
96 static void      size_reset_cb                 (GtkButton      *button,
97                                                 glViewImage    *view_image);
98
99 static void      update_dialog_cb              (glLabelObject  *object,
100                                                 glViewImage    *view_image);
101
102 static void      update_dialog_from_move_cb    (glLabelObject  *object,
103                                                 gdouble         dx,
104                                                 gdouble         dy,
105                                                 glViewImage    *view_image);
106
107 \f
108 /*****************************************************************************/
109 /* Boilerplate object stuff.                                                 */
110 /*****************************************************************************/
111 GType
112 gl_view_image_get_type (void)
113 {
114         static GType type = 0;
115
116         if (!type) {
117                 GTypeInfo info = {
118                         sizeof (glViewImageClass),
119                         NULL,
120                         NULL,
121                         (GClassInitFunc) gl_view_image_class_init,
122                         NULL,
123                         NULL,
124                         sizeof (glViewImage),
125                         0,
126                         (GInstanceInitFunc) gl_view_image_instance_init,
127                 };
128
129                 type = g_type_register_static (GL_TYPE_VIEW_OBJECT,
130                                                "glViewImage", &info, 0);
131         }
132
133         return type;
134 }
135
136 static void
137 gl_view_image_class_init (glViewImageClass *klass)
138 {
139         GObjectClass      *object_class      = (GObjectClass *) klass;
140         glViewObjectClass *view_object_class = (glViewObjectClass *) klass;
141
142         gl_debug (DEBUG_VIEW, "START");
143
144         parent_class = g_type_class_peek_parent (klass);
145
146         object_class->finalize = gl_view_image_finalize;
147
148         view_object_class->construct_dialog = construct_properties_dialog;
149
150         gl_debug (DEBUG_VIEW, "END");
151 }
152
153 static void
154 gl_view_image_instance_init (glViewImage *view_image)
155 {
156         gl_debug (DEBUG_VIEW, "START");
157
158         view_image->private = g_new0 (glViewImagePrivate, 1);
159
160         gl_debug (DEBUG_VIEW, "END");
161 }
162
163 static void
164 gl_view_image_finalize (GObject *object)
165 {
166         glLabel       *parent;
167
168         gl_debug (DEBUG_VIEW, "START");
169
170         g_return_if_fail (object && GL_IS_VIEW_IMAGE (object));
171
172         G_OBJECT_CLASS (parent_class)->finalize (object);
173
174         gl_debug (DEBUG_VIEW, "END");
175 }
176
177 /*****************************************************************************/
178 /* NEW image object view.                                                  */
179 /*****************************************************************************/
180 glViewObject *
181 gl_view_image_new (glLabelImage *object,
182                    glView       *view)
183 {
184         glViewImage        *view_image;
185         const GdkPixbuf    *pixbuf;
186         gdouble            w, h;
187         GtkMenu            *menu;
188
189         gl_debug (DEBUG_VIEW, "START");
190         g_return_if_fail (object && GL_IS_LABEL_IMAGE (object));
191         g_return_if_fail (view && GL_IS_VIEW (view));
192         
193         view_image = g_object_new (gl_view_image_get_type(), NULL);
194
195         gl_view_object_set_view (GL_VIEW_OBJECT(view_image), view);
196         gl_view_object_set_object (GL_VIEW_OBJECT(view_image),
197                                    GL_LABEL_OBJECT(object),
198                                    GL_VIEW_HIGHLIGHT_BOX_RESIZABLE);
199
200         /* Query properties of object. */
201         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
202         pixbuf = gl_label_image_get_pixbuf(object);
203
204         /* Create analogous canvas item. */
205         view_image->private->item =
206                 gl_view_object_item_new (GL_VIEW_OBJECT(view_image),
207                                          gnome_canvas_pixbuf_get_type (),
208                                          "x", 0.0,
209                                          "y", 0.0,
210                                          "width_set", TRUE,
211                                          "height_set", TRUE,
212                                          "width", w,
213                                          "height", h,
214                                          "pixbuf", pixbuf,
215                                          NULL);
216
217         g_signal_connect (G_OBJECT (object), "changed",
218                           G_CALLBACK (update_view_image_cb), view_image);
219
220         gl_debug (DEBUG_VIEW, "END");
221
222         return GL_VIEW_OBJECT (view_image);
223 }
224
225 /*---------------------------------------------------------------------------*/
226 /* PRIVATE. label object "changed" callback.                                 */
227 /*---------------------------------------------------------------------------*/
228 static void
229 update_view_image_cb (glLabelObject *object,
230                       glViewImage   *view_image)
231 {
232         const GdkPixbuf    *pixbuf;
233         gdouble            w, h;
234
235         gl_debug (DEBUG_VIEW, "START");
236
237         /* Query properties of object. */
238         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
239         pixbuf = gl_label_image_get_pixbuf (GL_LABEL_IMAGE(object));
240
241         /* Adjust appearance of analogous canvas item. */
242         gnome_canvas_item_set (view_image->private->item,
243                                "width_set", TRUE,
244                                "height_set", TRUE,
245                                "width", w,
246                                "height", h,
247                                "pixbuf", pixbuf,
248                                NULL);
249
250         gl_debug (DEBUG_VIEW, "END");
251 }
252
253 /*****************************************************************************/
254 /* Create a properties dialog for a image object.                          */
255 /*****************************************************************************/
256 static GtkWidget *
257 construct_properties_dialog (glViewObject *view_object)
258 {
259         glViewImage        *view_image = (glViewImage *)view_object;
260         GtkWidget          *dialog, *wsection, *wbutton;
261         glLabelObject      *object;
262         gdouble            x, y, w, h, label_width, label_height;
263         gchar              *filename;
264         GtkSizeGroup       *label_size_group;
265         GtkWidget          *window;
266
267         gl_debug (DEBUG_VIEW, "START");
268
269         /* retrieve object and query parameters */
270         object = gl_view_object_get_object (GL_VIEW_OBJECT(view_image));
271         gl_label_object_get_position (GL_LABEL_OBJECT(object), &x, &y);
272         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
273         filename = gl_label_image_get_filename (GL_LABEL_IMAGE(object));
274         gl_label_get_size (GL_LABEL(object->parent),
275                            &label_width, &label_height);
276
277         /*-----------------------------------------------------------------*/
278         /* Build dialog.                                                   */
279         /*-----------------------------------------------------------------*/
280         window = gtk_widget_get_toplevel (
281                 GTK_WIDGET(gl_view_object_get_view(GL_VIEW_OBJECT(view_image))));
282         dialog = gl_hig_dialog_new_with_buttons ( _("Edit image object properties"),
283                                                   GTK_WINDOW (window),
284                                                   GTK_DIALOG_DESTROY_WITH_PARENT,
285                                                   GTK_STOCK_CLOSE,
286                                                            GTK_RESPONSE_CLOSE,
287                                                   NULL );
288         gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
289         g_signal_connect (G_OBJECT (dialog), "response",
290                           G_CALLBACK (response_cb), view_image);
291
292         label_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
293
294         /*---------------------------*/
295         /* Image section             */
296         /*---------------------------*/
297         wsection = gl_hig_category_new (_("Image"));
298         gl_hig_dialog_add_widget (GL_HIG_DIALOG(dialog), wsection);
299         view_image->private->pixmap_entry =
300                 gnome_pixmap_entry_new ("image", "Load image", TRUE);
301         gnome_pixmap_entry_set_preview_size (GNOME_PIXMAP_ENTRY
302                                              (view_image->private->pixmap_entry),
303                                              128, 128);
304
305         /* Set default path for image entry */
306         if (filename != NULL) {
307                 /* Set default path to the directory containing image. */
308                 if (image_path != NULL)
309                         g_free (image_path);
310                 image_path = g_path_get_dirname (filename);
311                 if (image_path != NULL) {
312                         image_path = g_strconcat (image_path, "/", NULL);
313                 }
314         } else if (image_path == NULL) {
315                 /* First time, set it to our CWD. */
316                 image_path = g_get_current_dir ();
317         }
318
319         gl_hig_category_add_widget (GL_HIG_CATEGORY(wsection),
320                                     view_image->private->pixmap_entry);
321         g_signal_connect ( G_OBJECT(gnome_file_entry_gtk_entry
322                                     (GNOME_FILE_ENTRY (view_image->private->pixmap_entry))),
323                            "changed", G_CALLBACK (file_changed_cb),
324                            view_image);
325
326
327         /*----------------------------*/
328         /* Position section           */
329         /*----------------------------*/
330         wsection = gl_hig_category_new (_("Position"));
331         gl_hig_dialog_add_widget (GL_HIG_DIALOG(dialog), wsection);
332         view_image->private->position = gl_wdgt_position_new ();
333         gl_wdgt_position_set_label_size_group (GL_WDGT_POSITION(view_image->private->position),
334                                                label_size_group);
335         gl_wdgt_position_set_params (GL_WDGT_POSITION (view_image->private->position),
336                                      x, y, label_width, label_height);
337         gl_hig_category_add_widget (GL_HIG_CATEGORY(wsection),
338                                     view_image->private->position);
339         g_signal_connect (G_OBJECT (view_image->private->position),
340                           "changed",
341                           G_CALLBACK(position_changed_cb), view_image);
342
343
344         /*----------------------------*/
345         /* Size section               */
346         /*----------------------------*/
347         wsection = gl_hig_category_new (_("Size"));
348         gl_hig_dialog_add_widget (GL_HIG_DIALOG(dialog), wsection);
349         view_image->private->size = gl_wdgt_size_new ();
350         gl_wdgt_size_set_label_size_group (GL_WDGT_SIZE(view_image->private->size),
351                                                label_size_group);
352         gl_wdgt_size_set_params (GL_WDGT_SIZE (view_image->private->size),
353                                  w, h, TRUE, label_width, label_height);
354         gl_hig_category_add_widget (GL_HIG_CATEGORY(wsection),
355                                     view_image->private->size);
356         g_signal_connect (G_OBJECT (view_image->private->size), "changed",
357                           G_CALLBACK(size_changed_cb), view_image);
358
359         /* ------ Size Reset Button ------ */
360         wbutton = gtk_button_new_with_label (_("Reset image size"));
361         gl_hig_category_add_widget (GL_HIG_CATEGORY(wsection), wbutton);
362         g_signal_connect (G_OBJECT (wbutton), "clicked",
363                           G_CALLBACK (size_reset_cb), view_image);
364
365
366         /*----------------------------*/
367         /* Track object changes.      */
368         /*----------------------------*/
369         g_signal_connect (G_OBJECT (object), "changed",
370                           G_CALLBACK (update_dialog_cb), view_image);
371         g_signal_connect (G_OBJECT (object), "moved",
372                           G_CALLBACK (update_dialog_from_move_cb), view_image);
373
374         gl_debug (DEBUG_VIEW, "END");
375
376         return dialog;
377 }
378
379 /*---------------------------------------------------------------------------*/
380 /* PRIVATE.  "Response" callback.                                            */
381 /*---------------------------------------------------------------------------*/
382 static void
383 response_cb (GtkDialog     *dialog,
384              gint           response,
385              glViewImage   *view_image)
386 {
387         gl_debug (DEBUG_VIEW, "START");
388
389         g_return_if_fail(dialog != NULL);
390         g_return_if_fail(GTK_IS_DIALOG(dialog));
391
392         switch(response) {
393         case GTK_RESPONSE_CLOSE:
394                 gtk_widget_hide (GTK_WIDGET(dialog));
395                 break;
396         case GTK_RESPONSE_DELETE_EVENT:
397                 break;
398         default:
399                 g_print ("response = %d", response);
400                 g_assert_not_reached();
401         }
402
403         gl_debug (DEBUG_VIEW, "END");
404 }
405
406 /*---------------------------------------------------------------------------*/
407 /* PRIVATE.  file "changed" callback.                                        */
408 /*---------------------------------------------------------------------------*/
409 static void
410 file_changed_cb (GtkEntry          *pixmap_entry,
411                  glViewImage       *view_image)
412 {
413         glLabelObject    *object;
414         gchar            *filename;
415
416         gl_debug (DEBUG_VIEW, "START");
417
418         object = gl_view_object_get_object (GL_VIEW_OBJECT(view_image));
419
420         filename = gnome_pixmap_entry_get_filename (GNOME_PIXMAP_ENTRY(view_image->private->pixmap_entry));
421         gl_debug (DEBUG_VIEW, "filename = %s", filename);
422
423         g_signal_handlers_block_by_func (G_OBJECT(object),
424                                          update_dialog_cb, view_image);
425         gl_label_image_set_filename(GL_LABEL_IMAGE(object), filename);
426         g_signal_handlers_unblock_by_func (G_OBJECT(object),
427                                            update_dialog_cb, view_image);
428
429         g_free (filename);
430
431         gl_debug (DEBUG_VIEW, "END");
432 }
433
434 /*---------------------------------------------------------------------------*/
435 /* PRIVATE.  position "changed" callback.                                    */
436 /*---------------------------------------------------------------------------*/
437 static void
438 position_changed_cb (glWdgtPosition   *position,
439                      glViewImage      *view_image)
440 {
441         glLabelObject      *object;
442         gdouble            x, y;
443
444         gl_debug (DEBUG_VIEW, "START");
445
446         gl_wdgt_position_get_position (GL_WDGT_POSITION (position), &x, &y);
447
448         object = gl_view_object_get_object (GL_VIEW_OBJECT(view_image));
449
450         g_signal_handlers_block_by_func (G_OBJECT(object),
451                                          update_dialog_cb, view_image);
452         gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
453         g_signal_handlers_unblock_by_func (G_OBJECT(object),
454                                            update_dialog_cb, view_image);
455
456         gl_debug (DEBUG_VIEW, "END");
457 }
458
459 /*---------------------------------------------------------------------------*/
460 /* PRIVATE.  size "changed" callback.                                        */
461 /*---------------------------------------------------------------------------*/
462 static void
463 size_changed_cb (glWdgtSize   *size,
464                  glViewImage  *view_image)
465 {
466         glLabelObject *object;
467         gdouble       w, h;
468         gboolean      keep_aspect_ratio_flag;
469
470         gl_debug (DEBUG_VIEW, "START");
471
472         gl_wdgt_size_get_size (GL_WDGT_SIZE (size),
473                                &w, &h, &keep_aspect_ratio_flag);
474
475         object = gl_view_object_get_object (GL_VIEW_OBJECT(view_image));
476
477         g_signal_handlers_block_by_func (G_OBJECT(object),
478                                          update_dialog_cb, view_image);
479         gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
480         g_signal_handlers_unblock_by_func (G_OBJECT(object),
481                                            update_dialog_cb, view_image);
482
483         gl_debug (DEBUG_VIEW, "END");
484 }
485
486 /*---------------------------------------------------------------------------*/
487 /* PRIVATE.  size "changed" callback.                                        */
488 /*---------------------------------------------------------------------------*/
489 static void
490 size_reset_cb (GtkButton    *button,
491                glViewImage  *view_image)
492 {
493         glLabelObject   *object;
494         gdouble         image_w, image_h;
495         const GdkPixbuf *pixbuf;
496
497         gl_debug (DEBUG_VIEW, "START");
498
499         object = gl_view_object_get_object (GL_VIEW_OBJECT(view_image));
500         pixbuf = gl_label_image_get_pixbuf (GL_LABEL_IMAGE(object));
501
502         image_w = gdk_pixbuf_get_width (pixbuf);
503         image_h = gdk_pixbuf_get_height (pixbuf);
504
505         gl_label_object_set_size (GL_LABEL_OBJECT(object), image_w, image_h);
506
507         gl_debug (DEBUG_VIEW, "END");
508 }
509
510 /*---------------------------------------------------------------------------*/
511 /* PRIVATE. label object "changed" callback.                                 */
512 /*---------------------------------------------------------------------------*/
513 static void
514 update_dialog_cb (glLabelObject   *object,
515                   glViewImage     *view_image)
516 {
517         gchar              *filename;
518         gdouble            x, y, w, h;
519
520         gl_debug (DEBUG_VIEW, "START");
521
522         /* Query properties of object. */
523         gl_label_object_get_position (GL_LABEL_OBJECT(object), &x, &y);
524         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
525         filename = gl_label_image_get_filename (GL_LABEL_IMAGE(object));
526
527         /* Block widget handlers to prevent recursion */
528         g_signal_handlers_block_by_func (G_OBJECT(view_image->private->pixmap_entry),
529                                          file_changed_cb, view_image);
530         g_signal_handlers_block_by_func (G_OBJECT(view_image->private->position),
531                                          position_changed_cb, view_image);
532         g_signal_handlers_block_by_func (G_OBJECT(view_image->private->size),
533                                          size_changed_cb, view_image);
534
535         /* Update widgets in property dialog */
536
537         if ( filename != NULL ) {
538                 gnome_file_entry_set_filename (GNOME_FILE_ENTRY (view_image->private->pixmap_entry),
539                                                filename);
540         }
541         gl_wdgt_position_set_position (GL_WDGT_POSITION(view_image->private->position),
542                                        x, y);
543         gl_wdgt_size_set_size (GL_WDGT_SIZE(view_image->private->size), w, h);
544
545         /* Unblock widget handlers */
546         g_signal_handlers_unblock_by_func (G_OBJECT(view_image->private->pixmap_entry),
547                                            file_changed_cb, view_image);
548         g_signal_handlers_unblock_by_func (G_OBJECT(view_image->private->position),
549                                            position_changed_cb, view_image);
550         g_signal_handlers_unblock_by_func (G_OBJECT(view_image->private->size),
551                                            size_changed_cb, view_image);
552
553         g_free (filename);
554
555         gl_debug (DEBUG_VIEW, "END");
556 }
557
558 /*---------------------------------------------------------------------------*/
559 /* PRIVATE. label object "moved" callback.                                   */
560 /*---------------------------------------------------------------------------*/
561 static void
562 update_dialog_from_move_cb (glLabelObject *object,
563                             gdouble        dx,
564                             gdouble        dy,
565                             glViewImage   *view_image)
566 {
567         gdouble            x, y;
568
569         gl_debug (DEBUG_VIEW, "START");
570
571         /* Query properties of object. */
572         gl_label_object_get_position (GL_LABEL_OBJECT(object), &x, &y);
573
574         /* Block widget handlers to prevent recursion */
575         g_signal_handlers_block_by_func (G_OBJECT(view_image->private->position),
576                                          position_changed_cb, view_image);
577
578         /* Update widgets in property dialog */
579         gl_wdgt_position_set_position (GL_WDGT_POSITION(view_image->private->position),
580                                        x, y);
581
582         /* Unblock widget handlers */
583         g_signal_handlers_unblock_by_func (G_OBJECT(view_image->private->position),
584                                            position_changed_cb, view_image);
585
586         gl_debug (DEBUG_VIEW, "END");
587 }
588
589 /*****************************************************************************/
590 /* Return apropos cursor for create object mode.                             */
591 /*****************************************************************************/
592 GdkCursor *
593 gl_view_image_get_create_cursor (void)
594 {
595         static GdkCursor *cursor = NULL;
596         GdkPixmap        *pixmap_data, *pixmap_mask;
597         GdkColor         fg = { 0, 0, 0, 0 };
598         GdkColor         bg = { 0, 65535, 65535, 65535 };
599
600         gl_debug (DEBUG_VIEW, "START");
601
602         if (!cursor) {
603                 pixmap_data = gdk_bitmap_create_from_data (NULL,
604                                                            cursor_image_bits,
605                                                            cursor_image_width,
606                                                            cursor_image_height);
607                 pixmap_mask = gdk_bitmap_create_from_data (NULL,
608                                                            cursor_image_mask_bits,
609                                                            cursor_image_mask_width,
610                                                            cursor_image_mask_height);
611                 cursor =
612                     gdk_cursor_new_from_pixmap (pixmap_data, pixmap_mask, &fg,
613                                                 &bg, cursor_image_x_hot,
614                                                 cursor_image_y_hot);
615         }
616
617         gl_debug (DEBUG_VIEW, "END");
618
619         return cursor;
620 }
621
622 /*****************************************************************************/
623 /* Canvas event handler for creating image objects.                          */
624 /*****************************************************************************/
625 int
626 gl_view_image_create_event_handler (GnomeCanvas *canvas,
627                                       GdkEvent    *event,
628                                       glView      *view)
629 {
630         static gdouble      x0, y0;
631         static gboolean     dragging = FALSE;
632         static glViewObject *view_image;
633         static GObject      *object;
634         gdouble             line_width;
635         guint               line_color, fill_color;
636         gdouble             x, y, w, h;
637
638         gl_debug (DEBUG_VIEW, "");
639
640         switch (event->type) {
641
642         case GDK_BUTTON_PRESS:
643                 switch (event->button.button) {
644                 case 1:
645                         dragging = TRUE;
646                         gnome_canvas_item_grab (canvas->root,
647                                                 GDK_POINTER_MOTION_MASK |
648                                                 GDK_BUTTON_RELEASE_MASK |
649                                                 GDK_BUTTON_PRESS_MASK,
650                                                 NULL, event->button.time);
651                         gnome_canvas_window_to_world (canvas,
652                                                       event->button.x,
653                                                       event->button.y, &x, &y);
654                         object = gl_label_image_new (view->label);
655                         gl_label_object_set_position (GL_LABEL_OBJECT(object),
656                                                      x, y);
657                         gl_label_object_set_size (GL_LABEL_OBJECT(object),
658                                                   0.0, 0.0);
659                         view_image = gl_view_image_new (GL_LABEL_IMAGE(object),
660                                                         view);
661                         x0 = x;
662                         y0 = y;
663                         return TRUE;
664
665                 default:
666                         return FALSE;
667                 }
668
669         case GDK_BUTTON_RELEASE:
670                 switch (event->button.button) {
671                 case 1:
672                         dragging = FALSE;
673                         gnome_canvas_item_ungrab (canvas->root, event->button.time);
674                         gnome_canvas_window_to_world (canvas,
675                                                       event->button.x,
676                                                       event->button.y, &x, &y);
677                         if ((x0 == x) && (y0 == y)) {
678                                 x = x0 + 36.0;
679                                 y = y0 + 36.0;
680                         }
681                         gl_label_object_set_position (GL_LABEL_OBJECT(object),
682                                                      MIN (x, x0), MIN (y, y0));
683                         w = MAX (x, x0) - MIN (x, x0);
684                         h = MAX (y, y0) - MIN (y, y0);
685                         gl_label_object_set_size (GL_LABEL_OBJECT(object),
686                                                   w, h);
687                         gl_view_unselect_all (view);
688                         gl_view_object_select (GL_VIEW_OBJECT(view_image));
689                         gl_view_arrow_mode (view);
690                         return TRUE;
691
692                 default:
693                         return FALSE;
694                 }
695
696         case GDK_MOTION_NOTIFY:
697                 if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
698                         gnome_canvas_window_to_world (canvas,
699                                                       event->motion.x,
700                                                       event->motion.y, &x, &y);
701                         gl_label_object_set_position (GL_LABEL_OBJECT(object),
702                                                      MIN (x, x0), MIN (y, y0));
703                         w = MAX (x, x0) - MIN (x, x0);
704                         h = MAX (y, y0) - MIN (y, y0);
705                         gl_label_object_set_size (GL_LABEL_OBJECT(object),
706                                                   w, h);
707                         return TRUE;
708                 } else {
709                         return FALSE;
710                 }
711
712         default:
713                 return FALSE;
714         }
715
716 }