]> git.sur5r.net Git - glabels/blob - src/view-object.c
Organized master branch to be top-level directory for glabels, instead of
[glabels] / src / view-object.c
1 /*
2  *  view-object.c
3  *  Copyright (C) 2001-2009  Jim Evins <evins@snaught.com>.
4  *
5  *  This file is part of gLabels.
6  *
7  *  gLabels is free software: you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation, either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  gLabels is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with gLabels.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include "view-object.h"
22
23 #include <glib.h>
24
25 #include "debug.h"
26
27
28 /*========================================================*/
29 /* Private constants and macros.                          */
30 /*========================================================*/
31
32 #define HANDLE_FILL_RGBA_ARGS      0.0,   0.75,  0.0,   0.4
33 #define HANDLE_OUTLINE_RGBA_ARGS   0.0,   0.0,   0.0,   0.8
34
35 #define HANDLE_OUTLINE_WIDTH_PIXELS   1.0
36 #define HANDLE_PIXELS 7
37
38
39 /*========================================================*/
40 /* Private types.                                         */
41 /*========================================================*/
42
43 struct _glViewObjectPrivate {
44
45         glLabelObject              *object;
46
47         glView                     *view;
48         glViewObjectHandlesStyle    handles_style;
49
50         GtkWidget                  *property_editor;
51 };
52
53
54 /*========================================================*/
55 /* Private globals.                                       */
56 /*========================================================*/
57
58
59 /*========================================================*/
60 /* Private function prototypes.                           */
61 /*========================================================*/
62
63 static void     gl_view_object_finalize      (GObject             *object);
64
65 static void     object_removed_cb            (glViewObject        *view_object,
66                                               glLabelObject       *object);
67
68 static void     object_top_cb                (glViewObject        *view_object,
69                                               glLabelObject       *object);
70
71 static void     object_bottom_cb             (glViewObject        *view_object,
72                                               glLabelObject       *object);
73
74
75 /*****************************************************************************/
76 /* Boilerplate object stuff.                                                 */
77 /*****************************************************************************/
78 G_DEFINE_TYPE (glViewObject, gl_view_object, G_TYPE_OBJECT);
79
80
81 static void
82 gl_view_object_class_init (glViewObjectClass *class)
83 {
84         GObjectClass *object_class = G_OBJECT_CLASS (class);
85
86         gl_debug (DEBUG_VIEW, "START");
87
88         gl_view_object_parent_class = g_type_class_peek_parent (class);
89
90         object_class->finalize = gl_view_object_finalize;
91
92         gl_debug (DEBUG_VIEW, "END");
93 }
94
95
96 static void
97 gl_view_object_init (glViewObject *view_object)
98 {
99         gl_debug (DEBUG_VIEW, "START");
100
101         view_object->priv = g_new0 (glViewObjectPrivate, 1);
102
103         gl_debug (DEBUG_VIEW, "END");
104 }
105
106
107 static void
108 gl_view_object_finalize (GObject *object)
109 {
110         glViewObject  *view_object = GL_VIEW_OBJECT (object);
111         glView        *view;
112
113         gl_debug (DEBUG_VIEW, "START");
114
115         g_return_if_fail (object && GL_IS_VIEW_OBJECT (object));
116
117         view = view_object->priv->view;
118         view->object_list = g_list_remove (view->object_list, object);
119         view->selected_object_list =
120                 g_list_remove (view->selected_object_list, object);
121
122         g_object_unref (view_object->priv->object);
123         if (view_object->priv->property_editor) {
124                 gl_debug (DEBUG_VIEW, "Destroy editor");
125                 g_object_unref (G_OBJECT(view_object->priv->property_editor));
126         }
127         g_free (view_object->priv);
128
129         G_OBJECT_CLASS (gl_view_object_parent_class)->finalize (object);
130
131         gl_debug (DEBUG_VIEW, "END");
132 }
133
134
135 /*****************************************************************************/
136 /* NEW object view.                                                          */
137 /*****************************************************************************/
138 GObject *
139 gl_view_object_new (void)
140 {
141         glViewObject *view_object;
142
143         gl_debug (DEBUG_VIEW, "START");
144
145         view_object = g_object_new (gl_view_object_get_type(), NULL);
146
147         gl_debug (DEBUG_VIEW, "END");
148
149         return G_OBJECT (view_object);
150 }
151
152
153 /*****************************************************************************/
154 /* Set parent view to which this object view belongs.                        */
155 /*****************************************************************************/
156 void
157 gl_view_object_set_view       (glViewObject *view_object,
158                                glView *view)
159 {
160         gl_debug (DEBUG_VIEW, "START");
161
162         g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
163         g_return_if_fail (view && GL_IS_VIEW (view));
164         
165         view_object->priv->view = view;
166
167         view->object_list = g_list_append (view->object_list, view_object);
168
169         g_signal_connect_swapped (G_OBJECT (view_object->priv->object), "changed",
170                                   G_CALLBACK (gl_view_update), view);
171         g_signal_connect_swapped (G_OBJECT (view_object->priv->object), "moved",
172                                   G_CALLBACK (gl_view_update), view);
173
174         gl_debug (DEBUG_VIEW, "END");
175 }
176
177
178 /*****************************************************************************/
179 /* Set Label object to follow.                                               */
180 /*****************************************************************************/
181 void
182 gl_view_object_set_object     (glViewObject            *view_object,
183                                glLabelObject           *object,
184                                glViewObjectHandlesStyle style)
185 {
186         gl_debug (DEBUG_VIEW, "START");
187
188         g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
189         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
190         
191         view_object->priv->object = g_object_ref (G_OBJECT (object));
192         view_object->priv->handles_style = style;
193
194         g_signal_connect_swapped (G_OBJECT (object), "removed",
195                                   G_CALLBACK (object_removed_cb), view_object);
196         g_signal_connect_swapped (G_OBJECT (object), "top",
197                                   G_CALLBACK (object_top_cb), view_object);
198         g_signal_connect_swapped (G_OBJECT (object), "bottom",
199                                   G_CALLBACK (object_bottom_cb), view_object);
200
201         gl_debug (DEBUG_VIEW, "END");
202 }
203
204
205 /*---------------------------------------------------------------------------*/
206 /* PRIVATE.  Handle object "removed" signal.                                 */
207 /*---------------------------------------------------------------------------*/
208 static void
209 object_removed_cb (glViewObject  *view_object,
210                    glLabelObject *object)
211 {
212         glView *view;
213         gl_debug (DEBUG_VIEW, "START");
214
215         g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
216         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
217
218         view = gl_view_object_get_view (view_object);
219         view->object_list = g_list_remove (view->object_list, view_object);
220         g_object_unref (G_OBJECT (view_object));
221
222         gl_debug (DEBUG_VIEW, "END");
223 }
224
225
226 /*---------------------------------------------------------------------------*/
227 /* PRIVATE. Handle object "top" signal.                                      */
228 /*---------------------------------------------------------------------------*/
229 static void
230 object_top_cb (glViewObject  *view_object,
231                glLabelObject *object)
232 {
233         glView *view;
234         gl_debug (DEBUG_VIEW, "START");
235
236         g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
237         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
238
239         view = gl_view_object_get_view (view_object);
240
241         /* Move to end of list, representing front most object */
242         view->object_list = g_list_remove (view->object_list, view_object);
243         view->object_list = g_list_append (view->object_list, view_object);
244
245         gl_debug (DEBUG_VIEW, "END");
246 }
247
248
249 /*---------------------------------------------------------------------------*/
250 /* PRIVATE. Handle object "removed" signal.                                  */
251 /*---------------------------------------------------------------------------*/
252 static void
253 object_bottom_cb (glViewObject  *view_object,
254                   glLabelObject *object)
255 {
256         glView *view;
257         gl_debug (DEBUG_VIEW, "START");
258
259         g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
260         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
261
262         view = gl_view_object_get_view (view_object);
263
264         /* Move to front of list, representing rear most object */
265         view->object_list = g_list_remove (view->object_list, view_object);
266         view->object_list = g_list_prepend (view->object_list, view_object);
267
268         gl_debug (DEBUG_VIEW, "END");
269 }
270
271
272 /*****************************************************************************/
273 /* Return parent view associated with this view.                             */
274 /*****************************************************************************/
275 glView *
276 gl_view_object_get_view   (glViewObject *view_object)
277 {
278         gl_debug (DEBUG_VIEW, "START");
279
280         g_return_val_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object), NULL);
281
282         gl_debug (DEBUG_VIEW, "END");
283
284         return view_object->priv->view;
285 }
286
287
288 /*****************************************************************************/
289 /* Return label object that we are following.                                */
290 /*****************************************************************************/
291 glLabelObject *
292 gl_view_object_get_object (glViewObject *view_object)
293 {
294         gl_debug (DEBUG_VIEW, "START");
295
296         g_return_val_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object), NULL);
297         
298         gl_debug (DEBUG_VIEW, "END");
299
300         return view_object->priv->object;
301 }
302
303
304 /*****************************************************************************/
305 /* Get property editor.                                                      */
306 /*****************************************************************************/
307 GtkWidget *
308 gl_view_object_get_editor (glViewObject *view_object)
309 {
310         gl_debug (DEBUG_VIEW, "START");
311
312         g_return_val_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object), NULL);
313
314         if ( GL_VIEW_OBJECT_GET_CLASS(view_object)->construct_editor != NULL ) {
315
316                 if (view_object->priv->property_editor == NULL) {
317                         view_object->priv->property_editor =
318                                 GL_VIEW_OBJECT_GET_CLASS(view_object)->construct_editor (view_object);
319                 }
320                 g_signal_connect (G_OBJECT (view_object->priv->property_editor),
321                                   "destroy",
322                                   G_CALLBACK (gtk_widget_destroyed),
323                                   &view_object->priv->property_editor);
324         
325                 gtk_widget_show (view_object->priv->property_editor);
326
327         }
328
329
330         gl_debug (DEBUG_VIEW, "END");
331
332         return view_object->priv->property_editor;
333 }
334
335
336 /*****************************************************************************/
337 /* Select object.                                                            */
338 /*****************************************************************************/
339 void
340 gl_view_object_select (glViewObject *view_object)
341 {
342         gl_debug (DEBUG_VIEW, "START");
343
344         gl_view_select_object(view_object->priv->view, view_object);
345
346         gl_debug (DEBUG_VIEW, "END");
347 }
348
349
350 /*****************************************************************************/
351 /* Is object at (x,y)?                                                       */
352 /*****************************************************************************/
353 gboolean
354 gl_view_object_at (glViewObject  *view_object,
355                    cairo_t       *cr,
356                    gdouble        x,
357                    gdouble        y)
358 {
359         glLabelObject *object = view_object->priv->object;
360         gdouble        x0, y0;
361         cairo_matrix_t matrix;
362         gboolean       return_val = FALSE;
363
364         gl_debug (DEBUG_VIEW, "START");
365
366         g_return_val_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object), FALSE);
367         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
368
369         gl_label_object_get_position (object, &x0, &y0);
370         gl_label_object_get_matrix (object, &matrix);
371
372         cairo_save (cr);
373         cairo_translate (cr, x0, y0);
374         cairo_transform (cr, &matrix);
375
376         cairo_device_to_user (cr, &x, &y);
377
378         if ( GL_VIEW_OBJECT_GET_CLASS(view_object)->object_at != NULL ) {
379
380                 return_val = GL_VIEW_OBJECT_GET_CLASS(view_object)->object_at (view_object, cr, x, y);
381
382         }
383
384         cairo_restore (cr);
385
386         return return_val;
387
388         gl_debug (DEBUG_VIEW, "END");
389 }
390
391
392 /*--------------------------------------------------------------------------*/
393 /* Create handle path                                                       */
394 /*--------------------------------------------------------------------------*/
395 static void
396 create_handle_path (cairo_t                *cr,
397                     glLabelObject          *object,
398                     gdouble                 scale,
399                     gdouble                 x_handle,
400                     gdouble                 y_handle)
401 {
402         gl_debug (DEBUG_VIEW, "START");
403
404         cairo_rectangle (cr,
405                          x_handle - HANDLE_PIXELS/scale/2, y_handle - HANDLE_PIXELS/scale/2,
406                          HANDLE_PIXELS/scale, HANDLE_PIXELS/scale);
407
408         gl_debug (DEBUG_VIEW, "END");
409 }
410
411
412 /*****************************************************************************/
413 /* Draw object handles                                                       */
414 /*****************************************************************************/
415 void
416 gl_view_object_draw_handles (glViewObject *view_object,
417                              cairo_t      *cr)
418 {
419         glLabelObject *object = view_object->priv->object;
420         gdouble        x0, y0;
421         cairo_matrix_t matrix;
422         gdouble        scale;
423         gdouble        w, h;
424
425         gl_debug (DEBUG_VIEW, "START");
426
427         g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
428         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
429
430         scale = view_object->priv->view->home_scale * view_object->priv->view->zoom;
431
432         gl_label_object_get_position (object, &x0, &y0);
433         gl_label_object_get_matrix (object, &matrix);
434
435         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
436
437         cairo_save (cr);
438
439         cairo_translate (cr, x0, y0);
440         cairo_transform (cr, &matrix);
441
442         switch (view_object->priv->handles_style)
443         {
444         case GL_VIEW_OBJECT_HANDLES_BOX:
445
446                 /* North */
447                 cairo_new_path (cr);
448                 create_handle_path (cr, object, scale, w/2, 0);
449
450                 /* North East */
451                 cairo_new_sub_path (cr);
452                 create_handle_path (cr, object, scale, w, 0);
453
454                 /* East */
455                 cairo_new_sub_path (cr);
456                 create_handle_path (cr, object, scale, w, h/2);
457
458                 /* South East */
459                 cairo_new_sub_path (cr);
460                 create_handle_path (cr, object, scale, w, h);
461
462                 /* South */
463                 cairo_new_sub_path (cr);
464                 create_handle_path (cr, object, scale, w/2, h);
465
466                 /* South West */
467                 cairo_new_sub_path (cr);
468                 create_handle_path (cr, object, scale, 0, h);
469
470                 /* West */
471                 cairo_new_sub_path (cr);
472                 create_handle_path (cr, object, scale, 0, h/2);
473
474                 /* North West */
475                 cairo_new_sub_path (cr);
476                 create_handle_path (cr, object, scale, 0, 0);
477
478                 break;
479
480         case GL_VIEW_OBJECT_HANDLES_LINE:
481                 /* P1 */
482                 cairo_new_path (cr);
483                 create_handle_path (cr, object, scale, 0, 0);
484
485                 /* P2 */
486                 cairo_new_sub_path (cr);
487                 create_handle_path (cr, object, scale, w, h);
488
489                 break;
490         }
491
492         cairo_set_source_rgba (cr, HANDLE_FILL_RGBA_ARGS);
493         cairo_fill_preserve (cr);
494                                
495         cairo_set_line_width (cr, HANDLE_OUTLINE_WIDTH_PIXELS/scale);
496         cairo_set_source_rgba (cr, HANDLE_OUTLINE_RGBA_ARGS);
497         cairo_stroke (cr);
498
499         cairo_restore (cr);
500
501         gl_debug (DEBUG_VIEW, "END");
502 }
503
504
505 /*****************************************************************************/
506 /* Is there an object handle at (x,y).                                       */
507 /*****************************************************************************/
508 glViewObjectHandle
509 gl_view_object_handle_at (glViewObject *view_object,
510                           cairo_t      *cr,
511                           gdouble       x,
512                           gdouble       y)
513 {
514         glLabelObject *object = view_object->priv->object;
515         gdouble        x0, y0;
516         cairo_matrix_t matrix;
517         gdouble        scale;
518         gdouble        w, h;
519         glViewObjectHandle handle = GL_VIEW_OBJECT_HANDLE_NONE;
520
521         gl_debug (DEBUG_VIEW, "START");
522
523         g_return_val_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object), handle);
524         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), handle);
525
526         scale = view_object->priv->view->home_scale * view_object->priv->view->zoom;
527
528         gl_label_object_get_position (object, &x0, &y0);
529         gl_label_object_get_matrix (object, &matrix);
530
531         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
532
533         cairo_save (cr);
534
535         cairo_translate (cr, x0, y0);
536         cairo_transform (cr, &matrix);
537
538         cairo_device_to_user (cr, &x, &y);
539
540         switch (view_object->priv->handles_style)
541         {
542         case GL_VIEW_OBJECT_HANDLES_BOX:
543
544                 /* South East */
545                 create_handle_path (cr, object, scale, w, h);
546                 if (cairo_in_fill (cr, x, y))   {handle = GL_VIEW_OBJECT_HANDLE_SE; break;}
547
548                 /* South West */
549                 create_handle_path (cr, object, scale, 0, h);
550                 if (cairo_in_fill (cr, x, y))   {handle = GL_VIEW_OBJECT_HANDLE_SW; break;}
551
552                 /* North East */
553                 create_handle_path (cr, object, scale, w, 0);
554                 if (cairo_in_fill (cr, x, y))   {handle = GL_VIEW_OBJECT_HANDLE_NE; break;}
555
556                 /* North West */
557                 create_handle_path (cr, object, scale, 0, 0);
558                 if (cairo_in_fill (cr, x, y))   {handle = GL_VIEW_OBJECT_HANDLE_NW; break;}
559
560                 /* East */
561                 create_handle_path (cr, object, scale, w, h/2);
562                 if (cairo_in_fill (cr, x, y))   {handle = GL_VIEW_OBJECT_HANDLE_E; break;}
563
564                 /* South */
565                 create_handle_path (cr, object, scale, w/2, h);
566                 if (cairo_in_fill (cr, x, y))   {handle = GL_VIEW_OBJECT_HANDLE_S; break;}
567
568                 /* West */
569                 create_handle_path (cr, object, scale, 0, h/2);
570                 if (cairo_in_fill (cr, x, y))   {handle = GL_VIEW_OBJECT_HANDLE_W; break;}
571
572                 /* North */
573                 create_handle_path (cr, object, scale, w/2, 0);
574                 if (cairo_in_fill (cr, x, y))   {handle = GL_VIEW_OBJECT_HANDLE_N; break;}
575
576                 break;
577
578         case GL_VIEW_OBJECT_HANDLES_LINE:
579                 /* P2 */
580                 create_handle_path (cr, object, scale, w, h);
581                 if (cairo_in_fill (cr, x, y))   {handle = GL_VIEW_OBJECT_HANDLE_P2; break;}
582
583                 /* P1 */
584                 create_handle_path (cr, object, scale, 0, 0);
585                 if (cairo_in_fill (cr, x, y))   {handle = GL_VIEW_OBJECT_HANDLE_P1; break;}
586
587                 break;
588
589         }
590
591         cairo_restore (cr);
592
593         return handle;
594 }
595
596
597 /*---------------------------------------------------------------------------*/
598 /* PRIVATE.  Resize object.                                                  */
599 /*---------------------------------------------------------------------------*/
600 void
601 gl_view_object_resize_event (glViewObject       *view_object,
602                              glViewObjectHandle  handle,
603                              gboolean            honor_aspect,
604                              cairo_t            *cr,
605                              gdouble             x,
606                              gdouble             y)
607 {
608         glLabelObject *object;
609         cairo_matrix_t matrix;
610         gdouble        x0, y0, x1, y1, x2, y2;
611         gdouble        w, h;
612         gdouble        dx=0, dy=0;
613
614         gl_debug (DEBUG_VIEW, "x,y world = %g, %g", x, y);
615
616         object = view_object->priv->object;
617
618         /*
619          * Change to item relative coordinates
620          */
621         cairo_save (cr);
622         gl_label_object_get_position (object, &x0, &y0);
623         cairo_translate (cr, x0, y0);
624         gl_label_object_get_matrix (object, &matrix);
625         cairo_transform (cr, &matrix);
626
627         /*
628          * Initialize origin and 2 corners in object relative coordinates.
629          */
630         x0 = 0.0;
631         y0 = 0.0;
632
633         x1 = 0.0;
634         y1 = 0.0;
635
636         gl_label_object_get_size (object, &x2, &y2);
637
638         gl_debug (DEBUG_VIEW, "x0,y0 object = %g, %g", x0, y0);
639         gl_debug (DEBUG_VIEW, "x1,y1 object = %g, %g", x1, y1);
640         gl_debug (DEBUG_VIEW, "x2,y2 object = %g, %g", x2, y2);
641
642         /*
643          * Translate x,y into object relative coordinates.
644          */
645         cairo_device_to_user (cr, &x, &y);
646
647         gl_debug (DEBUG_VIEW, "x,y object = %g, %g", x, y);
648         
649         /*
650          * Get new size
651          */
652         switch (handle)
653         {
654
655         case GL_VIEW_OBJECT_HANDLE_NW:
656                 w = MAX (x2 - x, 0);
657                 h = MAX (y2 - y, 0);
658                 break;
659
660         case GL_VIEW_OBJECT_HANDLE_N:
661                 w = x2 - x1;
662                 h = MAX (y2 - y, 0);
663                 break;
664
665         case GL_VIEW_OBJECT_HANDLE_NE:
666                 w = MAX (x - x1, 0);
667                 h = MAX (y2 - y, 0);
668                 break;
669
670         case GL_VIEW_OBJECT_HANDLE_E:
671                 w = MAX (x - x1, 0);
672                 h = y2 - y1;
673                 break;
674
675         case GL_VIEW_OBJECT_HANDLE_SE:
676                 w = MAX (x - x1, 0);
677                 h = MAX (y - y1, 0);
678                 break;
679
680         case GL_VIEW_OBJECT_HANDLE_S:
681                 w = x2 - x1;
682                 h = MAX (y - y1, 0);
683                 break;
684
685         case GL_VIEW_OBJECT_HANDLE_SW:
686                 w = MAX (x2 - x, 0);
687                 h = MAX (y - y1, 0);
688                 break;
689
690         case GL_VIEW_OBJECT_HANDLE_W:
691                 w = MAX (x2 - x, 0);
692                 h = y2 - y1;
693                 break;
694         case GL_VIEW_OBJECT_HANDLE_P1:
695                 x1 = x;
696                 y1 = y;
697                 dx = (x2 - x);
698                 dy = (y2 - y);
699                 x0 = x0 + x1;
700                 y0 = y0 + y1;
701                 break;
702
703         case GL_VIEW_OBJECT_HANDLE_P2:
704                 dx = x - x1;
705                 dy = y - y1;
706                 x0 = x0 + x1;
707                 y0 = y0 + y1;
708                 break;
709
710         default:
711                 g_print ("Invalid handle.\n");  /* Should not happen! */
712
713         }
714         if ( (handle != GL_VIEW_OBJECT_HANDLE_P1) && (handle != GL_VIEW_OBJECT_HANDLE_P2) )
715         {
716                 if ( honor_aspect )
717                 {
718                         gl_label_object_set_size_honor_aspect (object, w, h);
719                 }
720                 else
721                 {
722                         gl_label_object_set_size (object, w, h);
723                 }
724
725                 /*
726                  * Query the new size in case it was constrained.
727                  */
728                 gl_label_object_get_size (object, &w, &h);
729
730                 /*
731                  * Get new position
732                  */
733                 switch (handle)
734                 {
735
736                 case GL_VIEW_OBJECT_HANDLE_NW:
737                         x0 += x2 - w;
738                         y0 += y2 - h;
739                         break;
740
741                 case GL_VIEW_OBJECT_HANDLE_N:
742                 case GL_VIEW_OBJECT_HANDLE_NE:
743                         /* x unchanged */
744                         y0 += y2 - h;
745                         break;
746
747                 case GL_VIEW_OBJECT_HANDLE_E:
748                 case GL_VIEW_OBJECT_HANDLE_SE:
749                 case GL_VIEW_OBJECT_HANDLE_S:
750                         /* unchanged */
751                         break;
752
753                 case GL_VIEW_OBJECT_HANDLE_SW:
754                 case GL_VIEW_OBJECT_HANDLE_W:
755                         x0 += x2 - w;
756                         /* y unchanged */
757                         break;
758
759                 default:
760                         g_print ("Invalid handle.\n");  /* Should not happen! */
761                 }
762         }
763         else
764         {
765                 gl_label_object_set_size (object, dx, dy);
766         }
767
768         /*
769          * Put new origin back into world coordinates and set.
770          */
771         cairo_user_to_device (cr, &x0, &y0);
772         cairo_restore (cr);
773         cairo_device_to_user (cr, &x0, &y0);
774         gl_label_object_set_position (object, x0, y0);
775 }
776
777
778
779 /*
780  * Local Variables:       -- emacs
781  * mode: C                -- emacs
782  * c-basic-offset: 8      -- emacs
783  * tab-width: 8           -- emacs
784  * indent-tabs-mode: nil  -- emacs
785  * End:                   -- emacs
786  */