]> git.sur5r.net Git - glabels/blob - glabels2/src/label-text.c
Text box refinement.
[glabels] / glabels2 / src / label-text.c
1 /*
2  *  (GLABELS) Label and Business Card Creation program for GNOME
3  *
4  *  label_text.c:  GLabels label text object
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 #include <libgnomeprint/gnome-glyphlist.h>
25
26 #include "label-text.h"
27
28 #include "pixmaps/checkerboard.xpm"
29
30 #include "debug.h"
31
32 /*========================================================*/
33 /* Private macros and constants.                          */
34 /*========================================================*/
35
36 #define DEFAULT_FONT_FAMILY      "Helvetica"
37 #define DEFAULT_FONT_SIZE        14.0
38 #define DEFAULT_FONT_WEIGHT      GNOME_FONT_BOOK
39 #define DEFAULT_FONT_ITALIC_FLAG FALSE
40 #define DEFAULT_JUST             GTK_JUSTIFY_LEFT
41 #define DEFAULT_COLOR            GNOME_CANVAS_COLOR (0,0,0)
42
43 /*========================================================*/
44 /* Private types.                                         */
45 /*========================================================*/
46
47 struct _glLabelTextPrivate {
48         GtkTextTagTable *tag_table;
49         GtkTextBuffer   *buffer;
50
51         gchar           *font_family;
52         gdouble          font_size;
53         GnomeFontWeight  font_weight;
54         gboolean         font_italic_flag;
55         GtkJustification just;
56         guint            color;
57 };
58
59 /*========================================================*/
60 /* Private globals.                                       */
61 /*========================================================*/
62
63 static glLabelObjectClass *parent_class = NULL;
64
65 static guint instance = 0;
66
67 /*========================================================*/
68 /* Private function prototypes.                           */
69 /*========================================================*/
70
71 static void gl_label_text_class_init    (glLabelTextClass *klass);
72 static void gl_label_text_instance_init (glLabelText      *ltext);
73 static void gl_label_text_finalize      (GObject          *object);
74
75 static void copy                        (glLabelObject    *dst_object,
76                                          glLabelObject    *src_object);
77
78 static void buffer_changed_cb           (GtkTextBuffer    *textbuffer,
79                                          glLabelText      *ltext);
80
81 static void get_size                    (glLabelObject    *object,
82                                          gdouble          *w,
83                                          gdouble          *h);
84
85 \f
86 /*****************************************************************************/
87 /* Boilerplate object stuff.                                                 */
88 /*****************************************************************************/
89 GType
90 gl_label_text_get_type (void)
91 {
92         static GType type = 0;
93
94         if (!type) {
95                 GTypeInfo info = {
96                         sizeof (glLabelTextClass),
97                         NULL,
98                         NULL,
99                         (GClassInitFunc) gl_label_text_class_init,
100                         NULL,
101                         NULL,
102                         sizeof (glLabelText),
103                         0,
104                         (GInstanceInitFunc) gl_label_text_instance_init,
105                 };
106
107                 type = g_type_register_static (GL_TYPE_LABEL_OBJECT,
108                                                "glLabelText", &info, 0);
109         }
110
111         return type;
112 }
113
114 static void
115 gl_label_text_class_init (glLabelTextClass *klass)
116 {
117         GObjectClass       *object_class       = (GObjectClass *) klass;
118         glLabelObjectClass *label_object_class = (glLabelObjectClass *) klass;
119
120         parent_class = g_type_class_peek_parent (klass);
121
122         label_object_class->copy     = copy;
123         label_object_class->get_size = get_size;
124
125         object_class->finalize = gl_label_text_finalize;
126 }
127
128 static void
129 gl_label_text_instance_init (glLabelText *ltext)
130 {
131         ltext->private = g_new0 (glLabelTextPrivate, 1);
132
133         ltext->private->tag_table        = gtk_text_tag_table_new ();
134         ltext->private->buffer           = gtk_text_buffer_new (ltext->private->tag_table);
135
136         ltext->private->font_family      = g_strdup(DEFAULT_FONT_FAMILY);
137         ltext->private->font_size        = DEFAULT_FONT_SIZE;
138         ltext->private->font_weight      = DEFAULT_FONT_WEIGHT;
139         ltext->private->font_italic_flag = DEFAULT_FONT_ITALIC_FLAG;
140         ltext->private->just             = DEFAULT_JUST;
141         ltext->private->color            = DEFAULT_COLOR;
142
143         g_signal_connect (G_OBJECT(ltext->private->buffer), "changed",
144                           G_CALLBACK(buffer_changed_cb), ltext);
145 }
146
147 static void
148 gl_label_text_finalize (GObject *object)
149 {
150         glLabelText *ltext;
151
152         g_return_if_fail (object && GL_IS_LABEL_TEXT (object));
153
154         ltext = GL_LABEL_TEXT (object);
155
156         g_object_unref (ltext->private->tag_table);
157         g_object_unref (ltext->private->buffer);
158         g_free (ltext->private);
159
160         G_OBJECT_CLASS (parent_class)->finalize (object);
161 }
162
163 /*****************************************************************************/
164 /* NEW label "text" object.                                               */
165 /*****************************************************************************/
166 GObject *
167 gl_label_text_new (glLabel *label)
168 {
169         glLabelText *ltext;
170
171         ltext = g_object_new (gl_label_text_get_type(), NULL);
172
173         gl_label_object_set_parent (GL_LABEL_OBJECT(ltext), label);
174
175         return G_OBJECT (ltext);
176 }
177
178 /*****************************************************************************/
179 /* Copy object contents.                                                     */
180 /*****************************************************************************/
181 static void
182 copy (glLabelObject *dst_object,
183       glLabelObject *src_object)
184 {
185         glLabelText      *ltext     = (glLabelText *)src_object;
186         glLabelText      *new_ltext = (glLabelText *)dst_object;
187         GList            *lines;
188         gchar            *font_family;
189         gdouble           font_size;
190         GnomeFontWeight   font_weight;
191         gboolean          font_italic_flag;
192         guint             color;
193         GtkJustification  just;
194
195         gl_debug (DEBUG_LABEL, "START");
196
197         g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
198         g_return_if_fail (new_ltext && GL_IS_LABEL_TEXT (new_ltext));
199
200         lines = gl_label_text_get_lines (ltext);
201         gl_label_text_get_props (ltext,
202                                  &font_family, &font_size, &font_weight,
203                                  &font_italic_flag,
204                                  &color, &just);
205
206         gl_label_text_set_lines (new_ltext, lines);
207         gl_label_text_set_props (new_ltext,
208                                  font_family, font_size, font_weight,
209                                  font_italic_flag,
210                                  color, just);
211
212         gl_text_node_lines_free (&lines);
213         g_free (font_family);
214
215         gl_debug (DEBUG_LABEL, "END");
216 }
217
218
219 /*****************************************************************************/
220 /* Set object params.                                                        */
221 /*****************************************************************************/
222 void
223 gl_label_text_set_lines (glLabelText *ltext,
224                          GList       *lines)
225 {
226         gchar *text;
227
228         gl_debug (DEBUG_LABEL, "START");
229
230         g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
231
232         text = gl_text_node_lines_expand (lines, NULL);
233         gtk_text_buffer_set_text (ltext->private->buffer, text, -1);
234         g_free (text);
235
236         gl_debug (DEBUG_LABEL, "END");
237 }
238
239 void
240 gl_label_text_set_props (glLabelText     *ltext,
241                          gchar           *font_family,
242                          gdouble          font_size,
243                          GnomeFontWeight  font_weight,
244                          gboolean         font_italic_flag,
245                          guint            color,
246                          GtkJustification just)
247 {
248         GList     *family_names;
249         gchar     *good_font_family;
250
251         gl_debug (DEBUG_LABEL, "START");
252
253         g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
254
255         /* Make sure we have a valid font family.  if not privide a good default. */
256         family_names = gnome_font_family_list ();
257         if (g_list_find_custom (family_names, font_family, (GCompareFunc)g_utf8_collate)) {
258                 good_font_family = g_strdup (font_family);
259         } else {
260                 if (family_names != NULL) {
261                         good_font_family = g_strdup (family_names->data); /* 1st entry */
262                 } else {
263                         good_font_family = NULL;
264                 }
265         }
266         gnome_font_family_list_free (family_names);
267
268         g_free (ltext->private->font_family);
269
270         ltext->private->font_family      = good_font_family;
271         ltext->private->font_size        = font_size;
272         ltext->private->font_weight      = font_weight;
273         ltext->private->font_italic_flag = font_italic_flag;
274         ltext->private->color            = color;
275         ltext->private->just             = just;
276
277         gl_debug (DEBUG_LABEL, "just = %d", ltext->private->just);
278
279         gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
280
281         gl_debug (DEBUG_LABEL, "END");
282 }
283
284
285 /*****************************************************************************/
286 /* Get object params.                                                        */
287 /*****************************************************************************/
288 GtkTextBuffer *
289 gl_label_text_get_buffer (glLabelText *ltext)
290 {
291         g_return_val_if_fail (ltext && GL_IS_LABEL_TEXT (ltext), NULL);
292
293         return ltext->private->buffer;
294 }
295
296 GList *
297 gl_label_text_get_lines (glLabelText *ltext)
298 {
299         GtkTextIter  start, end;
300         gchar       *text;
301         GList       *lines;
302
303         g_return_val_if_fail (ltext && GL_IS_LABEL_TEXT (ltext), NULL);
304
305         gtk_text_buffer_get_bounds (ltext->private->buffer, &start, &end);
306         text = gtk_text_buffer_get_text (ltext->private->buffer,
307                                          &start, &end, FALSE);
308         lines = gl_text_node_lines_new_from_text (text);
309         g_free (text);
310
311         return lines;
312 }
313
314 void
315 gl_label_text_get_props (glLabelText      *ltext,
316                          gchar           **font_family,
317                          gdouble          *font_size,
318                          GnomeFontWeight  *font_weight,
319                          gboolean         *font_italic_flag,
320                          guint            *color,
321                          GtkJustification *just)
322 {
323         g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
324
325         *font_family      = g_strdup (ltext->private->font_family);
326         *font_size        = ltext->private->font_size;
327         *font_weight      = ltext->private->font_weight;
328         *font_italic_flag = ltext->private->font_italic_flag;
329         *color            = ltext->private->color;
330         *just             = ltext->private->just;
331
332         gl_debug (DEBUG_LABEL, "just = %d", *just);
333 }
334
335 void
336 gl_label_text_get_box (glLabelText *ltext,
337                        gdouble     *w,
338                        gdouble     *h)
339 {
340         g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
341
342         /* peek at the parent size. */
343         (* parent_class->get_size) (GL_LABEL_OBJECT(ltext), w, h);
344 }
345
346 /*---------------------------------------------------------------------------*/
347 /* PRIVATE.  text buffer "changed" callback.                                 */
348 /*---------------------------------------------------------------------------*/
349 void buffer_changed_cb (GtkTextBuffer *textbuffer,
350                         glLabelText   *ltext)
351 {
352         gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
353 }
354
355 /*---------------------------------------------------------------------------*/
356 /* PRIVATE.  get object size method.                                         */
357 /*---------------------------------------------------------------------------*/
358 static void
359 get_size (glLabelObject *object,
360           gdouble       *w,
361           gdouble       *h)
362 {
363         glLabelText    *ltext = (glLabelText *)object;
364         GnomeFont      *font;
365         GtkTextIter     start, end;
366         gchar          *text;
367         gchar         **line;
368         gint            i;
369         GnomeGlyphList *glyphlist;
370         ArtDRect        bbox;
371         gdouble         affine[6];
372         gdouble         w_parent, h_parent;
373
374         gl_debug (DEBUG_LABEL, "START");
375
376         g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
377
378         (* parent_class->get_size) (object, &w_parent, &h_parent);
379
380         if ( (w_parent != 0.0) || (h_parent != 0.0) ) {
381                 *w = w_parent;
382                 *h = h_parent;
383                 return;
384         }
385
386         font = gnome_font_find_closest_from_weight_slant (
387                 ltext->private->font_family,
388                 ltext->private->font_weight,
389                 ltext->private->font_italic_flag,
390                 ltext->private->font_size);
391
392         gtk_text_buffer_get_bounds (ltext->private->buffer, &start, &end);
393         text = gtk_text_buffer_get_text (ltext->private->buffer,
394                                          &start, &end, FALSE);
395         line = g_strsplit (text, "\n", -1);
396         g_free (text);
397
398         art_affine_identity (affine);
399
400         *w = 0.0;
401         *h = 0.0;
402         for (i = 0; line[i] != NULL; i++) {
403
404                 glyphlist = gnome_glyphlist_from_text_dumb (font, 0,
405                                                             0.0, 0.0,
406                                                             line[i]);
407
408                 gnome_glyphlist_bbox (glyphlist, affine, 0, &bbox);
409
410                 if ( bbox.x1 > *w ) *w = bbox.x1;
411
412                 *h += ltext->private->font_size;
413
414         }
415
416         if ( *h == 0.0 ) *h = ltext->private->font_size;
417
418         *w += 2*GL_LABEL_TEXT_MARGIN;
419         *h += 2*GL_LABEL_TEXT_MARGIN;
420
421
422         g_strfreev (line);
423
424         gl_debug (DEBUG_LABEL, "END");
425 }
426