]> git.sur5r.net Git - glabels/blob - glabels2/src/view-text.c
110fa87e75da170d8ff35487818f0e125504e3b9
[glabels] / glabels2 / src / view-text.c
1 /*
2  *  (GLABELS) Label and Business Card Creation program for GNOME
3  *
4  *  view_text.c:  GLabels label text 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 <libgnomeprint/gnome-glyphlist.h>
26
27 #include "view-text.h"
28 #include "canvas-hacktext.h"
29 #include "view-highlight.h"
30 #include "wdgt-text-entry.h"
31 #include "wdgt-text-props.h"
32 #include "wdgt-position.h"
33 #include "color.h"
34 #include "prefs.h"
35 #include "hig.h"
36
37 #include "pixmaps/cursor_text.xbm"
38 #include "pixmaps/cursor_text_mask.xbm"
39
40 #include "debug.h"
41
42 /*========================================================*/
43 /* Private macros and constants.                          */
44 /*========================================================*/
45
46 /*========================================================*/
47 /* Private types.                                         */
48 /*========================================================*/
49
50 struct _glViewTextPrivate {
51
52         GList     *item_list;
53
54         /* Page 0 widgets */
55         GtkWidget *text_entry;
56
57         /* Page 1 widgets */
58         GtkWidget *text_props;
59
60         /* Page 2 widgets */
61         GtkWidget *position;
62 };
63
64 /*========================================================*/
65 /* Private globals.                                       */
66 /*========================================================*/
67
68 static glViewObjectClass *parent_class = NULL;
69
70
71 /*========================================================*/
72 /* Private function prototypes.                           */
73 /*========================================================*/
74
75 static void      gl_view_text_class_init       (glViewTextClass *klass);
76 static void      gl_view_text_instance_init    (glViewText      *view_text);
77 static void      gl_view_text_finalize         (GObject         *object);
78
79 static void      update_view_text_cb           (glLabelObject   *object,
80                                                 glViewText      *view_text);
81
82 static GtkWidget *construct_properties_dialog  (glViewText      *view_text);
83
84 static void      response_cb                   (GtkDialog       *dialog,
85                                                 gint             response,
86                                                 glViewText      *view_text);
87
88 static void      text_entry_changed_cb         (glWdgtTextEntry *text_entry,
89                                                 glViewText      *view_text);
90
91 static void      text_props_changed_cb         (glWdgtTextProps *text_props,
92                                                 glViewText      *view_text);
93
94 static void      position_changed_cb           (glWdgtPosition  *position,
95                                                 glViewText      *view_text);
96
97 static void      update_dialog_cb              (glLabelObject   *object,
98                                                 glViewText      *view_text);
99
100 static void      update_dialog_from_move_cb    (glLabelObject   *object,
101                                                 gdouble          dx,
102                                                 gdouble          dy,
103                                                 glViewText      *view_text);
104
105 static void      draw_hacktext                 (glViewText      *view_text);
106
107 \f
108 /*****************************************************************************/
109 /* Boilerplate object stuff.                                                 */
110 /*****************************************************************************/
111 GType
112 gl_view_text_get_type (void)
113 {
114         static GType type = 0;
115
116         if (!type) {
117                 GTypeInfo info = {
118                         sizeof (glViewTextClass),
119                         NULL,
120                         NULL,
121                         (GClassInitFunc) gl_view_text_class_init,
122                         NULL,
123                         NULL,
124                         sizeof (glViewText),
125                         0,
126                         (GInstanceInitFunc) gl_view_text_instance_init,
127                 };
128
129                 type = g_type_register_static (GL_TYPE_VIEW_OBJECT,
130                                                "glViewText", &info, 0);
131         }
132
133         return type;
134 }
135
136 static void
137 gl_view_text_class_init (glViewTextClass *klass)
138 {
139         GObjectClass *object_class = (GObjectClass *) klass;
140
141         gl_debug (DEBUG_VIEW, "START");
142
143         parent_class = g_type_class_peek_parent (klass);
144
145         object_class->finalize = gl_view_text_finalize;
146
147         gl_debug (DEBUG_VIEW, "END");
148 }
149
150 static void
151 gl_view_text_instance_init (glViewText *view_text)
152 {
153         gl_debug (DEBUG_VIEW, "START");
154
155         view_text->private = g_new0 (glViewTextPrivate, 1);
156
157         gl_debug (DEBUG_VIEW, "END");
158 }
159
160 static void
161 gl_view_text_finalize (GObject *object)
162 {
163         glLabel       *parent;
164
165         gl_debug (DEBUG_VIEW, "START");
166
167         g_return_if_fail (object && GL_IS_VIEW_TEXT (object));
168
169         G_OBJECT_CLASS (parent_class)->finalize (object);
170
171         gl_debug (DEBUG_VIEW, "END");
172 }
173
174 /*****************************************************************************/
175 /* NEW text object view.                                                  */
176 /*****************************************************************************/
177 glViewObject *
178 gl_view_text_new (glLabelText *object,
179                   glView     *view)
180 {
181         glViewText         *view_text;
182         GtkMenu            *menu;
183
184         gl_debug (DEBUG_VIEW, "START");
185         g_return_if_fail (object && GL_IS_LABEL_TEXT (object));
186         g_return_if_fail (view && GL_IS_VIEW (view));
187         
188         view_text = g_object_new (gl_view_text_get_type(), NULL);
189
190         gl_view_object_set_view (GL_VIEW_OBJECT(view_text), view);
191         gl_view_object_set_object (GL_VIEW_OBJECT(view_text),
192                                    GL_LABEL_OBJECT(object),
193                                    GL_VIEW_HIGHLIGHT_SIMPLE);
194
195         /* Create analogous canvas item. */
196         draw_hacktext (view_text);
197
198         g_signal_connect (G_OBJECT (object), "changed",
199                           G_CALLBACK (update_view_text_cb), view_text);
200
201         /* Create a dialog for controlling/viewing object properties. */
202         gl_view_object_set_dlg_constructor (GL_VIEW_OBJECT(view_text),
203                                             GL_VIEW_OBJECT_DLG_CONSTRUCTOR(construct_properties_dialog));
204
205         gl_debug (DEBUG_VIEW, "END");
206
207         return GL_VIEW_OBJECT (view_text);
208 }
209
210 /*---------------------------------------------------------------------------*/
211 /* PRIVATE. label object "changed" callback.                                 */
212 /*---------------------------------------------------------------------------*/
213 static void
214 update_view_text_cb (glLabelObject *object,
215                      glViewText    *view_text)
216 {
217         gl_debug (DEBUG_VIEW, "START");
218
219         /* Adjust appearance of analogous canvas item. */
220         draw_hacktext (view_text);
221
222         gl_debug (DEBUG_VIEW, "END");
223 }
224
225 /*****************************************************************************/
226 /* Create a properties dialog for a text object.                          */
227 /*****************************************************************************/
228 static GtkWidget *
229 construct_properties_dialog (glViewText *view_text)
230 {
231         GtkWidget          *dialog, *wsection, *wbutton;
232         glLabelObject      *object;
233         gdouble            x, y, w, h, label_width, label_height;
234         GList              *lines;
235         gchar              *font_family;
236         gdouble            font_size;
237         GnomeFontWeight    font_weight;
238         gboolean           font_italic_flag;
239         guint              color;
240         GtkJustification   just;
241         glMerge            *merge;
242         GtkSizeGroup       *label_size_group;
243         GtkWidget          *window;
244
245         gl_debug (DEBUG_VIEW, "START");
246
247         /* retrieve object and query parameters */
248         object = gl_view_object_get_object (GL_VIEW_OBJECT(view_text));
249         gl_label_object_get_position (GL_LABEL_OBJECT(object), &x, &y);
250         lines = gl_label_text_get_lines(GL_LABEL_TEXT(object));
251         gl_label_text_get_props (GL_LABEL_TEXT(object),
252                                  &font_family, &font_size,
253                                  &font_weight, &font_italic_flag,
254                                  &color, &just);
255         gl_label_get_size (GL_LABEL(object->parent),
256                            &label_width, &label_height);
257         merge = gl_label_get_merge (GL_LABEL(object->parent));
258
259         /*-----------------------------------------------------------------*/
260         /* Build dialog.                                                   */
261         /*-----------------------------------------------------------------*/
262         window = gtk_widget_get_toplevel (
263                 GTK_WIDGET(gl_view_object_get_view(GL_VIEW_OBJECT(view_text))));
264         dialog = gl_hig_dialog_new_with_buttons ( _("Edit text object properties"),
265                                                   GTK_WINDOW (window),
266                                                   GTK_DIALOG_DESTROY_WITH_PARENT,
267                                                   GTK_STOCK_CLOSE,
268                                                            GTK_RESPONSE_CLOSE,
269                                                   NULL );
270         gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
271         g_signal_connect (G_OBJECT (dialog), "response",
272                           G_CALLBACK (response_cb), view_text);
273
274         label_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
275
276         /*---------------------------*/
277         /* Text Section              */
278         /*---------------------------*/
279         wsection = gl_hig_category_new (_("Text"));
280         gl_hig_dialog_add_widget (GL_HIG_DIALOG(dialog), wsection);
281         view_text->private->text_entry =
282                 gl_wdgt_text_entry_new (merge->field_defs);
283         gl_wdgt_text_entry_set_label_size_group (GL_WDGT_TEXT_ENTRY(view_text->private->text_entry),
284                                                  label_size_group);
285         gl_wdgt_text_entry_set_text (GL_WDGT_TEXT_ENTRY(view_text->private->text_entry),
286                                      (merge->type != GL_MERGE_NONE),
287                                      lines);
288         gl_hig_category_add_widget (GL_HIG_CATEGORY(wsection),
289                                     view_text->private->text_entry);
290         g_signal_connect ( G_OBJECT(view_text->private->text_entry),
291                            "changed", G_CALLBACK (text_entry_changed_cb),
292                            view_text);
293
294
295         /*---------------------------*/
296         /* Text Properties section   */
297         /*---------------------------*/
298         wsection = gl_hig_category_new (_("Properties"));
299         gl_hig_dialog_add_widget (GL_HIG_DIALOG(dialog), wsection);
300         view_text->private->text_props = gl_wdgt_text_props_new ();
301         gl_wdgt_text_props_set_label_size_group (GL_WDGT_TEXT_PROPS(view_text->private->text_props),
302                                                  label_size_group);
303         gl_wdgt_text_props_set_params (GL_WDGT_TEXT_PROPS(view_text->private->text_props),
304                                        font_family, font_size, font_weight,
305                                        font_italic_flag, color, just);
306         gl_hig_category_add_widget (GL_HIG_CATEGORY(wsection),
307                                     view_text->private->text_props);
308         g_signal_connect ( G_OBJECT(view_text->private->text_props),
309                            "changed", G_CALLBACK (text_props_changed_cb),
310                            view_text);
311
312
313         /*----------------------------*/
314         /* Position section           */
315         /*----------------------------*/
316         wsection = gl_hig_category_new (_("Position"));
317         gl_hig_dialog_add_widget (GL_HIG_DIALOG(dialog), wsection);
318         view_text->private->position = gl_wdgt_position_new ();
319         gl_wdgt_position_set_label_size_group (GL_WDGT_POSITION(view_text->private->position),
320                                                label_size_group);
321         gl_wdgt_position_set_params (GL_WDGT_POSITION (view_text->private->position),
322                                      x, y,
323                                      label_width, label_height);
324         gl_hig_category_add_widget (GL_HIG_CATEGORY(wsection),
325                                     view_text->private->position);
326         g_signal_connect (G_OBJECT (view_text->private->position),
327                           "changed",
328                           G_CALLBACK(position_changed_cb), view_text);
329
330
331         /*----------------------------*/
332         /* Track object changes.      */
333         /*----------------------------*/
334         g_signal_connect (G_OBJECT (object), "changed",
335                           G_CALLBACK (update_dialog_cb), view_text);
336         g_signal_connect (G_OBJECT (object), "moved",
337                           G_CALLBACK (update_dialog_from_move_cb), view_text);
338
339         gl_debug (DEBUG_VIEW, "END");
340
341         return dialog;
342 }
343
344 /*---------------------------------------------------------------------------*/
345 /* PRIVATE.  "Response" callback.                                            */
346 /*---------------------------------------------------------------------------*/
347 static void
348 response_cb (GtkDialog     *dialog,
349              gint           response,
350              glViewText    *view_text)
351 {
352         gl_debug (DEBUG_VIEW, "START");
353
354         g_return_if_fail(dialog != NULL);
355         g_return_if_fail(GTK_IS_DIALOG(dialog));
356
357         switch(response) {
358         case GTK_RESPONSE_CLOSE:
359                 gtk_widget_hide (GTK_WIDGET(dialog));
360                 break;
361         case GTK_RESPONSE_DELETE_EVENT:
362                 break;
363         default:
364                 g_print ("response = %d", response);
365                 g_assert_not_reached();
366         }
367
368         gl_debug (DEBUG_VIEW, "END");
369 }
370
371 /*---------------------------------------------------------------------------*/
372 /* PRIVATE.  text_entry "changed" callback.                                  */
373 /*---------------------------------------------------------------------------*/
374 static void
375 text_entry_changed_cb (glWdgtTextEntry  *text_entry,
376                        glViewText       *view_text)
377 {
378         glLabelObject    *object;
379         GList            *lines;
380
381         gl_debug (DEBUG_VIEW, "START");
382
383         object = gl_view_object_get_object (GL_VIEW_OBJECT(view_text));
384
385         lines = gl_wdgt_text_entry_get_text (text_entry);
386
387         g_signal_handlers_block_by_func (G_OBJECT(object),
388                                          update_dialog_cb, view_text);
389         gl_label_text_set_lines (GL_LABEL_TEXT(object), lines);
390         g_signal_handlers_unblock_by_func (G_OBJECT(object),
391                                            update_dialog_cb, view_text);
392
393         gl_text_node_lines_free (&lines);
394
395         gl_debug (DEBUG_VIEW, "END");
396 }
397
398 /*---------------------------------------------------------------------------*/
399 /* PRIVATE.  text_props "changed" callback.                                  */
400 /*---------------------------------------------------------------------------*/
401 static void
402 text_props_changed_cb (glWdgtTextProps  *text_props,
403                        glViewText       *view_text)
404 {
405         glLabelObject      *object;
406         gchar              *font_family;
407         gdouble            font_size;
408         GnomeFontWeight    font_weight;
409         gboolean           font_italic_flag;
410         guint              color;
411         GtkJustification   just;
412
413
414         gl_debug (DEBUG_VIEW, "START");
415
416         object = gl_view_object_get_object (GL_VIEW_OBJECT(view_text));
417
418         gl_wdgt_text_props_get_params (text_props,
419                                        &font_family, &font_size, &font_weight,
420                                        &font_italic_flag,
421                                        &color, &just);
422
423         g_signal_handlers_block_by_func (G_OBJECT(object),
424                                          update_dialog_cb, view_text);
425         gl_label_text_set_props (GL_LABEL_TEXT(object),
426                                  font_family, font_size, font_weight,
427                                  font_italic_flag,
428                                  color, just);
429         g_signal_handlers_unblock_by_func (G_OBJECT(object),
430                                            update_dialog_cb, view_text);
431
432         g_free (font_family);
433
434         gl_debug (DEBUG_VIEW, "END");
435 }
436
437 /*---------------------------------------------------------------------------*/
438 /* PRIVATE.  position "changed" callback.                                    */
439 /*---------------------------------------------------------------------------*/
440 static void
441 position_changed_cb (glWdgtPosition     *position,
442                      glViewText         *view_text)
443 {
444         glLabelObject      *object;
445         gdouble            x, y;
446
447         gl_debug (DEBUG_VIEW, "START");
448
449         gl_wdgt_position_get_position (GL_WDGT_POSITION (position), &x, &y);
450
451         object = gl_view_object_get_object (GL_VIEW_OBJECT(view_text));
452
453         g_signal_handlers_block_by_func (G_OBJECT(object),
454                                          update_dialog_cb, view_text);
455         gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
456         g_signal_handlers_unblock_by_func (G_OBJECT(object),
457                                            update_dialog_cb, view_text);
458
459         gl_debug (DEBUG_VIEW, "END");
460 }
461
462 /*---------------------------------------------------------------------------*/
463 /* PRIVATE. label object "changed" callback.                                 */
464 /*---------------------------------------------------------------------------*/
465 static void
466 update_dialog_cb (glLabelObject  *object,
467                   glViewText     *view_text)
468 {
469         gdouble            x, y;
470         GList              *lines;
471         glMerge            *merge;
472         gchar              *font_family;
473         gdouble            font_size;
474         GnomeFontWeight    font_weight;
475         gboolean           font_italic_flag;
476         guint              color;
477         GtkJustification   just;
478
479         gl_debug (DEBUG_VIEW, "START");
480
481         /* Query properties of object. */
482         lines = gl_label_text_get_lines(GL_LABEL_TEXT(object));
483         gl_label_text_get_props (GL_LABEL_TEXT(object),
484                                  &font_family, &font_size,
485                                  &font_weight, &font_italic_flag,
486                                  &color, &just);
487         gl_label_object_get_position (GL_LABEL_OBJECT(object), &x, &y);
488         merge = gl_label_get_merge (GL_LABEL(object->parent));
489
490         /* Block widget handlers to prevent recursion */
491         g_signal_handlers_block_by_func (G_OBJECT(view_text->private->text_entry),
492                                          text_entry_changed_cb, view_text);
493         g_signal_handlers_block_by_func (G_OBJECT(view_text->private->text_props),
494                                          text_props_changed_cb, view_text);
495         g_signal_handlers_block_by_func (G_OBJECT(view_text->private->position),
496                                          position_changed_cb, view_text);
497
498         /* Update widgets in property dialog */
499
500         gl_wdgt_text_entry_set_text (GL_WDGT_TEXT_ENTRY(view_text->private->text_entry),
501                                      (merge->type != GL_MERGE_NONE),
502                                      lines);
503         gl_wdgt_text_entry_set_field_defs (GL_WDGT_TEXT_ENTRY(view_text->private->text_entry),
504                                            merge->field_defs);
505         gl_wdgt_text_props_set_params (GL_WDGT_TEXT_PROPS(view_text->private->text_props),
506                                        font_family, font_size, font_weight,
507                                        font_italic_flag, color, just);
508         gl_wdgt_position_set_position (GL_WDGT_POSITION(view_text->private->position),
509                                        x, y);
510
511         /* Unblock widget handlers */
512         g_signal_handlers_unblock_by_func (G_OBJECT(view_text->private->text_entry),
513                                            text_entry_changed_cb, view_text);
514         g_signal_handlers_unblock_by_func (G_OBJECT(view_text->private->text_props),
515                                            text_props_changed_cb, view_text);
516         g_signal_handlers_unblock_by_func (G_OBJECT(view_text->private->position),
517                                            position_changed_cb, view_text);
518
519         gl_text_node_lines_free (&lines);
520
521         gl_debug (DEBUG_VIEW, "END");
522 }
523
524 /*---------------------------------------------------------------------------*/
525 /* PRIVATE. label object "moved" callback.                                   */
526 /*---------------------------------------------------------------------------*/
527 static void
528 update_dialog_from_move_cb (glLabelObject *object,
529                             gdouble        dx,
530                             gdouble        dy,
531                             glViewText    *view_text)
532 {
533         gdouble            x, y;
534
535         gl_debug (DEBUG_VIEW, "START");
536
537         /* Query properties of object. */
538         gl_label_object_get_position (GL_LABEL_OBJECT(object), &x, &y);
539
540         /* Block widget handlers to prevent recursion */
541         g_signal_handlers_block_by_func (G_OBJECT(view_text->private->position),
542                                          position_changed_cb, view_text);
543
544         /* Update widgets in property dialog */
545         gl_wdgt_position_set_position (GL_WDGT_POSITION(view_text->private->position),
546                                        x, y);
547
548         /* Unblock widget handlers */
549         g_signal_handlers_unblock_by_func (G_OBJECT(view_text->private->position),
550                                            position_changed_cb, view_text);
551
552         gl_debug (DEBUG_VIEW, "END");
553 }
554
555 /*****************************************************************************/
556 /* Return apropos cursor for create object mode.                             */
557 /*****************************************************************************/
558 GdkCursor *
559 gl_view_text_get_create_cursor (void)
560 {
561         static GdkCursor *cursor = NULL;
562         GdkPixmap        *pixmap_data, *pixmap_mask;
563         GdkColor         fg = { 0, 0, 0, 0 };
564         GdkColor         bg = { 0, 65535, 65535, 65535 };
565
566         gl_debug (DEBUG_VIEW, "START");
567
568         if (!cursor) {
569                 pixmap_data = gdk_bitmap_create_from_data (NULL,
570                                                            cursor_text_bits,
571                                                            cursor_text_width,
572                                                            cursor_text_height);
573                 pixmap_mask = gdk_bitmap_create_from_data (NULL,
574                                                            cursor_text_mask_bits,
575                                                            cursor_text_mask_width,
576                                                            cursor_text_mask_height);
577                 cursor =
578                     gdk_cursor_new_from_pixmap (pixmap_data, pixmap_mask, &fg,
579                                                 &bg, cursor_text_x_hot,
580                                                 cursor_text_y_hot);
581         }
582
583         gl_debug (DEBUG_VIEW, "END");
584
585         return cursor;
586 }
587
588 /*****************************************************************************/
589 /* Canvas event handler for creating text objects.                           */
590 /*****************************************************************************/
591 int
592 gl_view_text_create_event_handler (GnomeCanvas *canvas,
593                                       GdkEvent    *event,
594                                       glView      *view)
595 {
596         static gdouble      x0, y0;
597         static gboolean     dragging = FALSE;
598         static glViewObject *view_text;
599         static GObject      *object;
600         gdouble             x, y;
601         GList               *lines;
602
603         gl_debug (DEBUG_VIEW, "");
604
605         switch (event->type) {
606
607         case GDK_BUTTON_PRESS:
608                 gl_debug (DEBUG_VIEW, "BUTTON_PRESS");
609                 switch (event->button.button) {
610                 case 1:
611                         dragging = TRUE;
612                         gnome_canvas_item_grab (canvas->root,
613                                                 GDK_POINTER_MOTION_MASK |
614                                                 GDK_BUTTON_RELEASE_MASK |
615                                                 GDK_BUTTON_PRESS_MASK,
616                                                 NULL, event->button.time);
617                         gnome_canvas_window_to_world (canvas,
618                                                       event->button.x,
619                                                       event->button.y, &x, &y);
620                         object = gl_label_text_new (view->label);
621                         gl_label_object_set_position (GL_LABEL_OBJECT(object),
622                                                      x, y);
623                         gl_label_text_set_props (GL_LABEL_TEXT(object),
624                                                  gl_prefs->default_font_family,
625                                                  gl_prefs->default_font_size,
626                                                  gl_prefs->default_font_weight,
627                                                  gl_prefs->default_font_italic_flag,
628                                                  gl_color_set_opacity (gl_prefs->default_text_color, 0.5),
629                                                  gl_prefs->default_text_alignment);
630                         lines = gl_text_node_lines_new_from_text (_("Text"));
631                         gl_label_text_set_lines (GL_LABEL_TEXT(object), lines);
632                         view_text = gl_view_text_new (GL_LABEL_TEXT(object),
633                                                       view);
634                         x0 = x;
635                         y0 = y;
636                         return TRUE;
637
638                 default:
639                         return FALSE;
640                 }
641
642         case GDK_BUTTON_RELEASE:
643                 gl_debug (DEBUG_VIEW, "BUTTON_RELEASE");
644                 switch (event->button.button) {
645                 case 1:
646                         dragging = FALSE;
647                         gnome_canvas_item_ungrab (canvas->root, event->button.time);
648                         gnome_canvas_window_to_world (canvas,
649                                                       event->button.x,
650                                                       event->button.y, &x, &y);
651                         gl_label_object_set_position (GL_LABEL_OBJECT(object),
652                                                       x, y);
653                         gl_label_text_set_props (GL_LABEL_TEXT(object),
654                                                  gl_prefs->default_font_family,
655                                                  gl_prefs->default_font_size,
656                                                  gl_prefs->default_font_weight,
657                                                  gl_prefs->default_font_italic_flag,
658                                                  gl_prefs->default_text_color,
659                                                  gl_prefs->default_text_alignment);
660                         gl_view_unselect_all (view);
661                         gl_view_object_select (GL_VIEW_OBJECT(view_text));
662                         gl_view_arrow_mode (view);
663                         return TRUE;
664
665                 default:
666                         return FALSE;
667                 }
668
669         case GDK_MOTION_NOTIFY:
670                 gl_debug (DEBUG_VIEW, "MOTION_NOTIFY");
671                 if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
672                         gnome_canvas_window_to_world (canvas,
673                                                       event->motion.x,
674                                                       event->motion.y, &x, &y);
675                         gl_label_object_set_position (GL_LABEL_OBJECT(object),
676                                                       x, y);
677                         return TRUE;
678                 } else {
679                         return FALSE;
680                 }
681
682         default:
683                 return FALSE;
684         }
685
686 }
687
688 /*--------------------------------------------------------------------------*/
689 /* PRIVATE.  Draw hacktext to item (group).                                 */
690 /*--------------------------------------------------------------------------*/
691 static void
692 draw_hacktext (glViewText *view_text)
693 {
694         glLabelObject    *object;
695         GnomeCanvasItem  *item;
696         GList            *lines;
697         gchar            *text;
698         gchar            *font_family;
699         GnomeFontWeight  font_weight;
700         gboolean         font_italic_flag;
701         gdouble          font_size;
702         guint            color;
703         GtkJustification just;
704         GnomeFont        *font;
705         GnomeGlyphList   *glyphlist;
706         ArtDRect         bbox;
707         gdouble          affine[6];
708         gdouble          x_offset, y_offset, w, object_w, object_h;
709         gint             i;
710         gchar            **line;
711         GList            *li;
712
713         gl_debug (DEBUG_VIEW, "START");
714
715         /* Query label object and properties */
716         object = gl_view_object_get_object (GL_VIEW_OBJECT(view_text));
717         gl_label_object_get_size (object, &object_w, &object_h);
718         gl_label_text_get_props (GL_LABEL_TEXT(object),
719                                  &font_family, &font_size,
720                                  &font_weight, &font_italic_flag,
721                                  &color, &just);
722         lines = gl_label_text_get_lines(GL_LABEL_TEXT(object));
723         text = gl_text_node_lines_expand (lines, NULL);
724         line = g_strsplit (text, "\n", -1);
725
726         /* remove previous items from group. */
727         for (li = view_text->private->item_list; li != NULL; li = li->next) {
728                 gl_debug (DEBUG_VIEW, "in loop");
729                 gtk_object_destroy (GTK_OBJECT (li->data));
730         }
731         gl_debug (DEBUG_VIEW, "1");
732         g_list_free (view_text->private->item_list);
733         view_text->private->item_list = NULL;
734         gl_debug (DEBUG_VIEW, "2");
735
736         /* get Gnome Font */
737         font = gnome_font_find_closest_from_weight_slant (font_family,
738                                                           font_weight,
739                                                           font_italic_flag,
740                                                           font_size);
741         art_affine_identity (affine);
742
743         /* render to group, one item per line. */
744         for (i = 0; line[i] != NULL; i++) {
745
746                 glyphlist = gnome_glyphlist_from_text_dumb (font, color,
747                                                             0.0, 0.0,
748                                                             line[i]);
749
750                 gnome_glyphlist_bbox (glyphlist, affine, 0, &bbox);
751                 w = bbox.x1;
752
753                 switch (just) {
754                 case GTK_JUSTIFY_LEFT:
755                         x_offset = 0.0;
756                         break;
757                 case GTK_JUSTIFY_CENTER:
758                         x_offset = (object_w - w) / 2.0;
759                         break;
760                 case GTK_JUSTIFY_RIGHT:
761                         x_offset = object_w - w;
762                         break;
763                 default:
764                         x_offset = 0.0;
765                         break;  /* shouldn't happen */
766                 }
767
768                 y_offset =
769                         (i + 1) * font_size + gnome_font_get_descender (font);
770
771                 item = gl_view_object_item_new (GL_VIEW_OBJECT(view_text),
772                                                 gl_canvas_hacktext_get_type (),
773                                                 "x", x_offset,
774                                                 "y", y_offset,
775                                                 "glyphlist", glyphlist, NULL);
776                 view_text->private->item_list =
777                         g_list_prepend (view_text->private->item_list, item);
778
779         }
780
781         /* clean up */
782         g_strfreev (line);
783         gl_text_node_lines_free (&lines);
784         g_free (text);
785
786         gl_debug (DEBUG_VIEW, "END");
787 }
788