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