]> git.sur5r.net Git - glabels/blob - glabels2/src/view-text.c
2007-09-14 Jim Evins <evins@snaught.com>
[glabels] / glabels2 / src / view-text.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
2
3 /*
4  *  (GLABELS) Label and Business Card Creation program for GNOME
5  *
6  *  view_text.c:  GLabels label text object view
7  *
8  *  Copyright (C) 2001-2007  Jim Evins <evins@snaught.com>.
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
23  */
24 #include <config.h>
25
26 #include "view-text.h"
27
28 #include <glib/gi18n.h>
29 #include <glib/gmem.h>
30
31 #include "color.h"
32 #include "object-editor.h"
33 #include "stock.h"
34
35 #include "pixmaps/cursor_text.xbm"
36 #include "pixmaps/cursor_text_mask.xbm"
37
38 #include "debug.h"
39
40 /*========================================================*/
41 /* Private macros and constants.                          */
42 /*========================================================*/
43
44 /*========================================================*/
45 /* Private types.                                         */
46 /*========================================================*/
47
48 struct _glViewTextPrivate {
49 };
50
51 /*========================================================*/
52 /* Private globals.                                       */
53 /*========================================================*/
54
55
56 /*========================================================*/
57 /* Private function prototypes.                           */
58 /*========================================================*/
59
60 static void       gl_view_text_finalize             (GObject          *object);
61
62 static GtkWidget *construct_properties_editor       (glViewObject     *view_object);
63
64 static void       update_object_from_editor_cb      (glObjectEditor   *editor,
65                                                      glLabelObject    *object);
66
67 static void       update_object_from_editor_size_cb (glObjectEditor   *editor,
68                                                      glLabelObject    *object);
69
70 static void       update_editor_from_object_cb      (glLabelObject    *object,
71                                                      glObjectEditor   *editor);
72
73 static void       update_editor_from_move_cb        (glLabelObject    *object,
74                                                      gdouble           dx,
75                                                      gdouble           dy,
76                                                      glObjectEditor   *editor);
77
78 static void       update_editor_from_label_cb       (glLabel          *label,
79                                                      glObjectEditor   *editor);
80
81 static gboolean   object_at                         (glViewObject     *view_object,
82                                                      cairo_t          *cr,
83                                                      gdouble           x,
84                                                      gdouble           y);
85
86
87
88 \f
89 /*****************************************************************************/
90 /* Boilerplate object stuff.                                                 */
91 /*****************************************************************************/
92 G_DEFINE_TYPE (glViewText, gl_view_text, GL_TYPE_VIEW_OBJECT);
93
94
95 static void
96 gl_view_text_class_init (glViewTextClass *class)
97 {
98         GObjectClass      *object_class      = G_OBJECT_CLASS (class);
99         glViewObjectClass *view_object_class = GL_VIEW_OBJECT_CLASS (class);
100
101         gl_debug (DEBUG_VIEW, "START");
102
103         gl_view_text_parent_class = g_type_class_peek_parent (class);
104
105         object_class->finalize = gl_view_text_finalize;
106
107         view_object_class->construct_editor = construct_properties_editor;
108         view_object_class->object_at        = object_at;
109
110         gl_debug (DEBUG_VIEW, "END");
111 }
112
113 static void
114 gl_view_text_init (glViewText *view_text)
115 {
116         gl_debug (DEBUG_VIEW, "START");
117
118         view_text->priv = g_new0 (glViewTextPrivate, 1);
119
120         gl_debug (DEBUG_VIEW, "END");
121 }
122
123 static void
124 gl_view_text_finalize (GObject *object)
125 {
126         glViewText *view_text = GL_VIEW_TEXT (object);
127
128         gl_debug (DEBUG_VIEW, "START");
129
130         g_return_if_fail (object && GL_IS_VIEW_TEXT (object));
131
132         g_free (view_text->priv);
133
134         G_OBJECT_CLASS (gl_view_text_parent_class)->finalize (object);
135
136         gl_debug (DEBUG_VIEW, "END");
137 }
138
139 /*****************************************************************************/
140 /* NEW text object view.                                                     */
141 /*****************************************************************************/
142 glViewObject *
143 gl_view_text_new (glLabelText *object,
144                   glView      *view)
145 {
146         glViewText         *view_text;
147
148         gl_debug (DEBUG_VIEW, "START");
149
150         g_return_val_if_fail (object && GL_IS_LABEL_TEXT (object), NULL);
151         g_return_val_if_fail (view && GL_IS_VIEW (view), NULL);
152         
153         view_text = g_object_new (gl_view_text_get_type(), NULL);
154
155         gl_view_object_set_object (GL_VIEW_OBJECT(view_text),
156                                    GL_LABEL_OBJECT(object),
157                                    GL_VIEW_OBJECT_HANDLES_BOX);
158         gl_view_object_set_view (GL_VIEW_OBJECT(view_text), view);
159
160         gl_debug (DEBUG_VIEW, "END");
161
162         return GL_VIEW_OBJECT (view_text);
163 }
164
165 /*****************************************************************************/
166 /* Create a properties dialog for a text object.                             */
167 /*****************************************************************************/
168 static GtkWidget *
169 construct_properties_editor (glViewObject *view_object)
170 {
171         GtkWidget          *editor;
172         glViewText          *view_text = (glViewText *)view_object;
173         glLabelObject      *object;
174         GtkTextBuffer      *buffer;
175
176         gl_debug (DEBUG_VIEW, "START");
177
178         object = gl_view_object_get_object (GL_VIEW_OBJECT(view_text));
179
180         /* Build editor. */
181         editor = gl_object_editor_new (GL_STOCK_TEXT, _("Text object properties"),
182                                        GL_OBJECT_EDITOR_SHADOW_PAGE,
183                                        GL_OBJECT_EDITOR_POSITION_PAGE,
184                                        GL_OBJECT_EDITOR_SIZE_PAGE,
185                                        GL_OBJECT_EDITOR_TEXT_PAGE,
186                                        GL_OBJECT_EDITOR_EDIT_PAGE,
187                                        0);
188
189         buffer = gl_label_text_get_buffer (GL_LABEL_TEXT(object));
190         gl_object_editor_set_text_buffer (GL_OBJECT_EDITOR(editor), buffer);
191         
192         /* Update */
193         update_editor_from_label_cb (object->parent, GL_OBJECT_EDITOR(editor));
194         update_editor_from_object_cb (object, GL_OBJECT_EDITOR(editor));
195         update_editor_from_move_cb (object, 0, 0, GL_OBJECT_EDITOR(editor));
196
197         /* Connect signals. */
198         g_signal_connect (G_OBJECT (editor), "changed",
199                           G_CALLBACK(update_object_from_editor_cb), object);
200         g_signal_connect (G_OBJECT (editor), "size_changed",
201                           G_CALLBACK(update_object_from_editor_size_cb), object);
202         g_signal_connect (G_OBJECT (object), "changed",
203                           G_CALLBACK (update_editor_from_object_cb), editor);
204         g_signal_connect (G_OBJECT (object), "moved",
205                           G_CALLBACK (update_editor_from_move_cb), editor);
206         g_signal_connect (G_OBJECT (object->parent), "size_changed",
207                           G_CALLBACK (update_editor_from_label_cb), editor);                      
208         g_signal_connect (G_OBJECT (object->parent), "merge_changed",
209                           G_CALLBACK (update_editor_from_label_cb), editor);
210
211         gl_debug (DEBUG_VIEW, "END");
212
213         return editor;
214 }
215
216 /*---------------------------------------------------------------------------*/
217 /* PRIVATE.  editor "changed" callback.                                      */
218 /*---------------------------------------------------------------------------*/
219 static void
220 update_object_from_editor_cb (glObjectEditor *editor,
221                               glLabelObject  *object)
222 {
223         gdouble            x, y;
224         gchar             *font_family;
225         gdouble            font_size;
226         PangoWeight        font_weight;
227         gboolean           font_italic_flag;
228         glColorNode       *color_node;
229         PangoAlignment     align;
230         gdouble            text_line_spacing;
231         gboolean           auto_shrink;
232         gboolean           shadow_state;
233         gdouble            shadow_x, shadow_y;
234         glColorNode       *shadow_color_node;
235         gdouble            shadow_opacity;
236
237         gl_debug (DEBUG_VIEW, "START");
238
239         g_signal_handlers_block_by_func (G_OBJECT(object),
240                                          update_editor_from_object_cb,
241                                          editor);
242         g_signal_handlers_block_by_func (G_OBJECT(object),
243                                          update_editor_from_move_cb,
244                                          editor);
245
246         gl_object_editor_get_position (editor, &x, &y);
247         font_family = gl_object_editor_get_font_family (editor);
248         font_size = gl_object_editor_get_font_size (editor);
249         font_weight = gl_object_editor_get_font_weight (editor);
250         font_italic_flag = gl_object_editor_get_font_italic_flag (editor);
251         color_node = gl_object_editor_get_text_color (editor);
252         align = gl_object_editor_get_text_alignment (editor);
253         text_line_spacing = gl_object_editor_get_text_line_spacing (editor);
254         auto_shrink = gl_object_editor_get_text_auto_shrink (editor);
255
256         gl_label_object_set_position (object, x, y);
257         gl_label_object_set_font_family (object, font_family);
258         gl_label_object_set_font_size (object, font_size);
259         gl_label_object_set_font_weight (object, font_weight);
260         gl_label_object_set_font_italic_flag (object, font_italic_flag);
261         gl_label_object_set_text_color (object, color_node);
262         gl_label_object_set_text_alignment (object, align);
263         gl_label_object_set_text_line_spacing (object, text_line_spacing);
264         gl_label_text_set_auto_shrink (GL_LABEL_TEXT (object), auto_shrink);
265
266         gl_color_node_free (&color_node);
267         g_free (font_family);
268
269         shadow_state = gl_object_editor_get_shadow_state (editor);
270         gl_label_object_set_shadow_state (object, shadow_state);
271
272         gl_object_editor_get_shadow_offset (editor, &shadow_x, &shadow_y);
273         gl_label_object_set_shadow_offset (object, shadow_x, shadow_y);
274
275         shadow_color_node = gl_object_editor_get_shadow_color (editor);
276         gl_label_object_set_shadow_color (object, shadow_color_node);
277         gl_color_node_free (&shadow_color_node);
278
279         shadow_opacity = gl_object_editor_get_shadow_opacity (editor);
280         gl_label_object_set_shadow_opacity (object, shadow_opacity);
281
282         g_signal_handlers_unblock_by_func (G_OBJECT(object),
283                                            update_editor_from_object_cb,
284                                            editor);
285         g_signal_handlers_unblock_by_func (G_OBJECT(object),
286                                            update_editor_from_move_cb,
287                                            editor);
288
289         gl_debug (DEBUG_VIEW, "END");
290 }
291
292 /*---------------------------------------------------------------------------*/
293 /* PRIVATE.  editor "changed" callback.                                      */
294 /*---------------------------------------------------------------------------*/
295 static void
296 update_object_from_editor_size_cb (glObjectEditor *editor,
297                                    glLabelObject  *object)
298 {
299         gdouble            w, h;
300
301         gl_debug (DEBUG_VIEW, "START");
302
303         g_signal_handlers_block_by_func (G_OBJECT(object),
304                                          update_editor_from_object_cb,
305                                          editor);
306         g_signal_handlers_block_by_func (G_OBJECT(object),
307                                          update_editor_from_move_cb,
308                                          editor);
309
310         gl_object_editor_get_size (editor, &w, &h);
311
312         gl_label_object_set_size (object, w, h);
313
314         g_signal_handlers_unblock_by_func (G_OBJECT(object),
315                                            update_editor_from_object_cb,
316                                            editor);
317         g_signal_handlers_unblock_by_func (G_OBJECT(object),
318                                            update_editor_from_move_cb,
319                                            editor);
320
321         gl_debug (DEBUG_VIEW, "END");
322 }
323
324 /*---------------------------------------------------------------------------*/
325 /* PRIVATE. label object "changed" callback.                                 */
326 /*---------------------------------------------------------------------------*/
327 static void
328 update_editor_from_object_cb (glLabelObject  *object,
329                               glObjectEditor *editor)
330 {
331         gdouble            w, h;
332         gchar             *font_family;
333         gdouble            font_size;
334         PangoWeight        font_weight;
335         gboolean           font_italic_flag;
336         glColorNode       *color_node;
337         PangoAlignment     align;
338         gdouble            text_line_spacing;
339         gboolean           auto_shrink;
340         gboolean           shadow_state;
341         gdouble            shadow_x, shadow_y;
342         glColorNode       *shadow_color_node;
343         gdouble            shadow_opacity;
344         glMerge           *merge;
345
346         gl_debug (DEBUG_VIEW, "START");
347
348         gl_label_object_get_size (object, &w, &h);
349         gl_object_editor_set_size (editor, w, h);
350         merge = gl_label_get_merge (GL_LABEL(object->parent));
351
352         font_family      = gl_label_object_get_font_family (object);
353         font_size        = gl_label_object_get_font_size (object);
354         font_weight      = gl_label_object_get_font_weight (object);
355         font_italic_flag = gl_label_object_get_font_italic_flag (object);
356         color_node       = gl_label_object_get_text_color (object);
357         align             = gl_label_object_get_text_alignment (object);
358         text_line_spacing = gl_label_object_get_text_line_spacing (object);
359         auto_shrink      = gl_label_text_get_auto_shrink (GL_LABEL_TEXT (object));
360
361         gl_object_editor_set_font_family (editor, font_family);
362         gl_object_editor_set_font_size (editor, font_size);
363         gl_object_editor_set_font_weight (editor, font_weight);
364         gl_object_editor_set_font_italic_flag (editor, font_italic_flag);
365         gl_object_editor_set_text_color (editor, (merge != NULL), color_node);
366         gl_object_editor_set_text_alignment (editor, align);
367         gl_object_editor_set_text_line_spacing (editor, text_line_spacing);
368         gl_object_editor_set_text_auto_shrink (editor, auto_shrink);
369
370         gl_color_node_free (&color_node);
371         g_free (font_family);
372
373         shadow_state = gl_label_object_get_shadow_state (object);
374         gl_object_editor_set_shadow_state (editor, shadow_state);
375
376         gl_label_object_get_shadow_offset (object, &shadow_x, &shadow_y);
377         gl_object_editor_set_shadow_offset (editor, shadow_x, shadow_y);
378
379         shadow_color_node = gl_label_object_get_shadow_color (object);
380         gl_object_editor_set_shadow_color (editor, (merge != NULL), shadow_color_node);
381         gl_color_node_free (&shadow_color_node);
382
383         shadow_opacity = gl_label_object_get_shadow_opacity (object);
384         gl_object_editor_set_shadow_opacity (editor, shadow_opacity);
385
386         gl_debug (DEBUG_VIEW, "END");
387 }
388
389 /*---------------------------------------------------------------------------*/
390 /* PRIVATE. label object "moved" callback.                                   */
391 /*---------------------------------------------------------------------------*/
392 static void
393 update_editor_from_move_cb (glLabelObject    *object,
394                             gdouble           dx,
395                             gdouble           dy,
396                             glObjectEditor   *editor)
397 {
398         gdouble            x, y;
399
400         gl_debug (DEBUG_VIEW, "START");
401
402         gl_label_object_get_position (object, &x, &y);
403         gl_object_editor_set_position (editor, x, y);
404
405         gl_debug (DEBUG_VIEW, "END");
406 }
407
408 /*---------------------------------------------------------------------------*/
409 /* PRIVATE. label "changed" callback.                                        */
410 /*---------------------------------------------------------------------------*/
411 static void
412 update_editor_from_label_cb (glLabel        *label,
413                              glObjectEditor *editor)
414 {
415         gdouble            label_width, label_height;
416         glMerge                    *merge;
417
418         gl_debug (DEBUG_VIEW, "START");
419
420         gl_label_get_size (label, &label_width, &label_height);
421         gl_object_editor_set_max_position (GL_OBJECT_EDITOR (editor),
422                                            label_width, label_height);
423         gl_object_editor_set_max_size (GL_OBJECT_EDITOR (editor),
424                                        label_width, label_height);
425         gl_object_editor_set_max_shadow_offset (GL_OBJECT_EDITOR (editor),
426                                                 label_width, label_height);
427         
428         merge = gl_label_get_merge (label);
429         gl_object_editor_set_key_names (editor, merge);
430
431         gl_debug (DEBUG_VIEW, "END");
432 }
433
434 /*****************************************************************************/
435 /* Is object at (x,y)?                                                       */
436 /*****************************************************************************/
437 static gboolean
438 object_at (glViewObject  *view_object,
439            cairo_t       *cr,
440            gdouble        x,
441            gdouble        y)
442 {
443         glLabelObject    *object;
444         gdouble           w, h;
445
446         object = gl_view_object_get_object (view_object);
447
448         gl_label_object_get_size (object, &w, &h);
449
450         cairo_rectangle (cr, 0.0, 0.0, w, h);
451
452         if (cairo_in_fill (cr, x, y))
453         {
454                 return TRUE;
455         }
456
457         return FALSE;
458 }
459
460
461 /*****************************************************************************/
462 /* Return apropos cursor for create object mode.                             */
463 /*****************************************************************************/
464 GdkCursor *
465 gl_view_text_get_create_cursor (void)
466 {
467         GdkCursor       *cursor = NULL;
468         GdkPixmap       *pixmap_data, *pixmap_mask;
469         GdkColor         fg = { 0, 0, 0, 0 };
470         GdkColor         bg = { 0, 65535, 65535, 65535 };
471
472         gl_debug (DEBUG_VIEW, "START");
473
474         pixmap_data = gdk_bitmap_create_from_data (NULL,
475                                                    (gchar *)cursor_text_bits,
476                                                    cursor_text_width,
477                                                    cursor_text_height);
478         pixmap_mask = gdk_bitmap_create_from_data (NULL,
479                                                    (gchar *)cursor_text_mask_bits,
480                                                    cursor_text_mask_width,
481                                                    cursor_text_mask_height);
482         cursor = gdk_cursor_new_from_pixmap (pixmap_data, pixmap_mask, &fg,
483                                              &bg, cursor_text_x_hot,
484                                              cursor_text_y_hot);
485
486         gl_debug (DEBUG_VIEW, "END");
487
488         return cursor;
489 }
490
491 /*****************************************************************************/
492 /* Object creation handler: button press event.                              */
493 /*****************************************************************************/
494 void
495 gl_view_text_create_button_press_event   (glView *view,
496                                           gdouble x,
497                                           gdouble y)
498 {
499         GObject             *object;
500         glViewObject        *view_text;
501         GList               *lines;
502         gchar               *family;
503         glColorNode         *color_node;
504
505         gl_view_unselect_all (view);
506
507         object = gl_label_text_new (view->label);
508         color_node = gl_color_node_new_default ();
509         gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
510         family = gl_view_get_default_font_family (view);
511         gl_label_object_set_font_family (GL_LABEL_OBJECT(object), family);
512         gl_label_object_set_font_size (GL_LABEL_OBJECT(object),
513                                        gl_view_get_default_font_size (view));
514         gl_label_object_set_font_weight (GL_LABEL_OBJECT(object),
515                                          gl_view_get_default_font_weight (view));
516         gl_label_object_set_font_italic_flag (GL_LABEL_OBJECT(object),
517                                               gl_view_get_default_font_italic_flag (view));
518                                                                   
519         color_node->color = gl_color_set_opacity (gl_view_get_default_text_color (view), 0.5);
520         gl_label_object_set_text_color (GL_LABEL_OBJECT(object),
521                                                         color_node);
522         gl_label_object_set_text_alignment (GL_LABEL_OBJECT(object),
523                                             gl_view_get_default_text_alignment (view));
524         gl_label_object_set_text_line_spacing (GL_LABEL_OBJECT(object), gl_view_get_default_text_line_spacing (view));
525                                                        
526         g_free (family);
527         lines = gl_text_node_lines_new_from_text (_("Text"));
528         gl_label_text_set_lines (GL_LABEL_TEXT(object), lines);
529         view_text = gl_view_text_new (GL_LABEL_TEXT(object), view);
530         gl_color_node_free (&color_node);
531
532         view->create_object = GL_LABEL_OBJECT (object);
533         view->create_x0 = x;
534         view->create_y0 = y;
535 }
536
537 /*****************************************************************************/
538 /* Object creation handler: motion event.                                    */
539 /*****************************************************************************/
540 void
541 gl_view_text_create_motion_event     (glView *view,
542                                       gdouble x,
543                                       gdouble y)
544 {
545         gl_label_object_set_position (GL_LABEL_OBJECT(view->create_object), x, y);
546 }
547
548 /*****************************************************************************/
549 /* Object creation handler: button relesase event.                           */
550 /*****************************************************************************/
551 void
552 gl_view_text_create_button_release_event (glView *view,
553                                           gdouble x,
554                                           gdouble y)
555 {
556         glColorNode         *color_node;
557
558         color_node = gl_color_node_new_default ();
559         gl_label_object_set_position (GL_LABEL_OBJECT(view->create_object), x, y);
560         color_node->color = gl_view_get_default_text_color(view);
561         gl_label_object_set_text_color (GL_LABEL_OBJECT(view->create_object), color_node);
562         gl_color_node_free (&color_node);
563 }
564