]> git.sur5r.net Git - glabels/blob - src/label-box.c
Imported Upstream version 3.0.0
[glabels] / src / label-box.c
1 /*
2  *  label-box.c
3  *  Copyright (C) 2001-2009  Jim Evins <evins@snaught.com>.
4  *
5  *  This file is part of gLabels.
6  *
7  *  gLabels is free software: you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation, either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  gLabels is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with gLabels.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include "label-box.h"
22
23 #include <glib/gi18n.h>
24 #include <glib.h>
25
26 #include "debug.h"
27
28
29 /*========================================================*/
30 /* Private types.                                         */
31 /*========================================================*/
32
33 struct _glLabelBoxPrivate {
34         gdouble          line_width;
35         glColorNode      *line_color_node;
36         glColorNode      *fill_color_node;
37 };
38
39
40 /*========================================================*/
41 /* Private globals.                                       */
42 /*========================================================*/
43
44
45 /*========================================================*/
46 /* Private function prototypes.                           */
47 /*========================================================*/
48
49 static void    gl_label_box_finalize      (GObject         *object);
50
51 static void    copy                       (glLabelObject   *dst_object,
52                                            glLabelObject   *src_object);
53
54 static void    set_fill_color             (glLabelObject   *object,
55                                            glColorNode     *fill_color_node,
56                                            gboolean         checkpoint);
57
58 static void    set_line_color             (glLabelObject   *object,
59                                            glColorNode     *line_color_node,
60                                            gboolean         checkpoint);
61
62 static void    set_line_width             (glLabelObject   *object,
63                                            gdouble          line_width,
64                                            gboolean         checkpoint);
65
66 static glColorNode*   get_fill_color      (glLabelObject   *object);
67
68 static glColorNode*   get_line_color      (glLabelObject   *object);
69
70 static gdouble get_line_width             (glLabelObject   *object);
71
72 static void    draw_object                (glLabelObject     *object,
73                                            cairo_t           *cr,
74                                            gboolean           screen_flag,
75                                            glMergeRecord     *record);
76
77 static void    draw_shadow                (glLabelObject     *object,
78                                            cairo_t           *cr,
79                                            gboolean           screen_flag,
80                                            glMergeRecord     *record);
81
82 static gboolean object_at                 (glLabelObject     *object,
83                                            cairo_t           *cr,
84                                            gdouble            x_pixels,
85                                            gdouble            y_pixels);
86
87
88 /*****************************************************************************/
89 /* Boilerplate object stuff.                                                 */
90 /*****************************************************************************/
91 G_DEFINE_TYPE (glLabelBox, gl_label_box, GL_TYPE_LABEL_OBJECT)
92
93
94 static void
95 gl_label_box_class_init (glLabelBoxClass *class)
96 {
97         GObjectClass       *object_class       = G_OBJECT_CLASS (class);
98         glLabelObjectClass *label_object_class = GL_LABEL_OBJECT_CLASS (class);
99
100         gl_label_box_parent_class = g_type_class_peek_parent (class);
101
102         label_object_class->copy           = copy;
103         label_object_class->set_fill_color = set_fill_color;
104         label_object_class->set_line_color = set_line_color;
105         label_object_class->set_line_width = set_line_width;
106         label_object_class->get_fill_color = get_fill_color;
107         label_object_class->get_line_color = get_line_color;
108         label_object_class->get_line_width = get_line_width;
109         label_object_class->draw_object    = draw_object;
110         label_object_class->draw_shadow    = draw_shadow;
111         label_object_class->object_at      = object_at;
112
113         object_class->finalize = gl_label_box_finalize;
114 }
115
116
117 static void
118 gl_label_box_init (glLabelBox *lbox)
119 {
120         lbox->priv = g_new0 (glLabelBoxPrivate, 1);
121 }
122
123
124 static void
125 gl_label_box_finalize (GObject *object)
126 {
127         glLabelBox *lbox = GL_LABEL_BOX (object);
128
129         g_return_if_fail (object && GL_IS_LABEL_BOX (object));
130
131         gl_color_node_free (&(lbox->priv->fill_color_node));
132         gl_color_node_free (&(lbox->priv->line_color_node));
133         g_free (lbox->priv);
134
135         G_OBJECT_CLASS (gl_label_box_parent_class)->finalize (object);
136 }
137
138
139 /*****************************************************************************/
140 /* NEW label "box" object.                                                   */
141 /*****************************************************************************/
142 GObject *
143 gl_label_box_new (glLabel *label,
144                   gboolean checkpoint)
145 {
146         glLabelBox          *lbox;
147         glColorNode         *fill_color_node;
148         glColorNode         *line_color_node;
149
150         lbox = g_object_new (gl_label_box_get_type(), NULL);
151
152         if (label != NULL)
153         {
154                 if ( checkpoint )
155                 {
156                         gl_label_checkpoint (label, _("Create box object"));
157                 }
158
159                 fill_color_node = gl_color_node_new_default ();
160                 line_color_node = gl_color_node_new_default ();
161
162                 line_color_node->color = gl_label_get_default_line_color(label);
163                 fill_color_node->color = gl_label_get_default_fill_color(label);
164
165                 lbox->priv->line_width      = gl_label_get_default_line_width(label);
166                 lbox->priv->line_color_node = line_color_node;
167                 lbox->priv->fill_color_node = fill_color_node;
168
169                 gl_label_add_object (label, GL_LABEL_OBJECT (lbox));
170                 gl_label_object_set_parent (GL_LABEL_OBJECT (lbox), label);
171         }
172
173         return G_OBJECT (lbox);
174 }
175
176
177 /*****************************************************************************/
178 /* Copy object contents.                                                     */
179 /*****************************************************************************/
180 static void
181 copy (glLabelObject *dst_object,
182       glLabelObject *src_object)
183 {
184         glLabelBox  *lbox     = (glLabelBox *)src_object;
185         glLabelBox  *new_lbox = (glLabelBox *)dst_object;
186         gdouble      line_width;
187         glColorNode *line_color_node;
188         glColorNode *fill_color_node;
189
190         gl_debug (DEBUG_LABEL, "START");
191
192         g_return_if_fail (lbox && GL_IS_LABEL_BOX (lbox));
193         g_return_if_fail (new_lbox && GL_IS_LABEL_BOX (new_lbox));
194
195         line_width = get_line_width (src_object);
196         line_color_node = get_line_color (src_object);
197         fill_color_node = get_fill_color (src_object);
198
199         set_line_width (dst_object, line_width, FALSE);
200         set_line_color (dst_object, line_color_node, FALSE);
201         set_fill_color (dst_object, fill_color_node, FALSE);
202         
203         gl_color_node_free (&line_color_node);
204         gl_color_node_free (&fill_color_node);
205
206         gl_debug (DEBUG_LABEL, "END");
207 }
208
209
210 /*---------------------------------------------------------------------------*/
211 /* PRIVATE.  Set fill color method.                                          */
212 /*---------------------------------------------------------------------------*/
213 static void
214 set_fill_color (glLabelObject *object,
215                 glColorNode   *fill_color_node,
216                 gboolean       checkpoint)
217 {
218         glLabelBox *lbox = (glLabelBox *)object;
219         glLabel    *label;
220         
221         gl_debug (DEBUG_LABEL, "START");
222
223         g_return_if_fail (lbox && GL_IS_LABEL_BOX (lbox));
224
225         if (!gl_color_node_equal (lbox->priv->fill_color_node, fill_color_node))
226         {
227                 if ( checkpoint )
228                 {
229                         label = gl_label_object_get_parent (GL_LABEL_OBJECT (lbox));
230                         gl_label_checkpoint (label, _("Fill color"));
231                 }
232
233                 gl_color_node_free (&(lbox->priv->fill_color_node));
234                 lbox->priv->fill_color_node = gl_color_node_dup (fill_color_node);
235
236                 gl_label_object_emit_changed (GL_LABEL_OBJECT(lbox));
237         }
238
239         gl_debug (DEBUG_LABEL, "END");
240 }
241
242
243 /*---------------------------------------------------------------------------*/
244 /* PRIVATE.  Set line color method.                                          */
245 /*---------------------------------------------------------------------------*/
246 static void
247 set_line_color (glLabelObject *object,
248                 glColorNode   *line_color_node,
249                 gboolean       checkpoint)
250 {
251         glLabelBox *lbox = (glLabelBox *)object;
252         glLabel    *label;
253
254         g_return_if_fail (lbox && GL_IS_LABEL_BOX (lbox));
255
256         if ( !gl_color_node_equal (lbox->priv->line_color_node, line_color_node ))
257         {
258                 if ( checkpoint )
259                 {
260                         label = gl_label_object_get_parent (GL_LABEL_OBJECT (lbox));
261                         gl_label_checkpoint (label, _("Line color"));
262                 }
263
264                 gl_color_node_free (&(lbox->priv->line_color_node));
265                 lbox->priv->line_color_node = gl_color_node_dup (line_color_node);
266                 gl_label_object_emit_changed (GL_LABEL_OBJECT(lbox));
267         }
268 }
269
270
271 /*---------------------------------------------------------------------------*/
272 /* PRIVATE.  Set line width method.                                          */
273 /*---------------------------------------------------------------------------*/
274 static void
275 set_line_width (glLabelObject *object,
276                 gdouble        line_width,
277                 gboolean       checkpoint)
278 {
279         glLabelBox *lbox = (glLabelBox *)object;
280         glLabel    *label;
281
282         g_return_if_fail (lbox && GL_IS_LABEL_BOX (lbox));
283
284         if ( lbox->priv->line_width != line_width )
285         {
286                 if ( checkpoint )
287                 {
288                         label = gl_label_object_get_parent (GL_LABEL_OBJECT (lbox));
289                         gl_label_checkpoint (label, _("Line width"));
290                 }
291
292                 lbox->priv->line_width = line_width;
293                 gl_label_object_emit_changed (GL_LABEL_OBJECT(lbox));
294         }
295 }
296
297
298 /*---------------------------------------------------------------------------*/
299 /* PRIVATE.  Get fill color method.                                          */
300 /*---------------------------------------------------------------------------*/
301 static gdouble
302 get_line_width (glLabelObject *object)
303 {
304         glLabelBox *lbox = (glLabelBox *)object;
305
306         g_return_val_if_fail (lbox && GL_IS_LABEL_BOX (lbox), 0.0);
307
308         return lbox->priv->line_width;
309 }
310
311
312 /*---------------------------------------------------------------------------*/
313 /* PRIVATE.  Get line color method.                                          */
314 /*---------------------------------------------------------------------------*/
315 static glColorNode*
316 get_line_color (glLabelObject *object)
317 {
318         glLabelBox *lbox = (glLabelBox *)object;
319
320         g_return_val_if_fail (lbox && GL_IS_LABEL_BOX (lbox), 0);
321
322         return gl_color_node_dup (lbox->priv->line_color_node);
323 }
324
325
326 /*---------------------------------------------------------------------------*/
327 /* PRIVATE.  Get line width method.                                          */
328 /*---------------------------------------------------------------------------*/
329 static glColorNode*
330 get_fill_color (glLabelObject *object)
331 {
332         glLabelBox *lbox = (glLabelBox *)object;
333
334         g_return_val_if_fail (lbox && GL_IS_LABEL_BOX (lbox), 0);
335
336         return gl_color_node_dup (lbox->priv->fill_color_node);
337 }
338
339
340 /*****************************************************************************/
341 /* Draw object method.                                                       */
342 /*****************************************************************************/
343 static void
344 draw_object (glLabelObject *object,
345              cairo_t       *cr,
346              gboolean       screen_flag,
347              glMergeRecord *record)
348 {
349         gdouble        w, h;
350         gdouble        line_width;
351         glColorNode   *line_color_node;
352         glColorNode   *fill_color_node;
353         guint          line_color;
354         guint          fill_color;
355
356         gl_debug (DEBUG_LABEL, "START");
357
358         gl_label_object_get_size (object, &w, &h);
359
360         line_width = gl_label_object_get_line_width (object);
361         
362         line_color_node = gl_label_object_get_line_color (object);
363         fill_color_node = gl_label_object_get_fill_color (object);
364         line_color = gl_color_node_expand (line_color_node, record);
365         fill_color = gl_color_node_expand (fill_color_node, record);
366         if (line_color_node->field_flag && screen_flag)
367         {
368                 line_color = GL_COLOR_MERGE_DEFAULT;
369         }
370         if (fill_color_node->field_flag && screen_flag)
371         {
372                 fill_color = GL_COLOR_FILL_MERGE_DEFAULT;
373         }
374
375
376         cairo_rectangle (cr, 0.0, 0.0, w, h);
377
378         /* Paint fill color */
379         cairo_set_source_rgba (cr, GL_COLOR_RGBA_ARGS (fill_color));
380         cairo_fill_preserve (cr);
381
382         /* Draw outline */
383         cairo_set_source_rgba (cr, GL_COLOR_RGBA_ARGS (line_color));
384         cairo_set_line_width (cr, line_width);
385         cairo_stroke (cr);
386
387         gl_color_node_free (&line_color_node);
388         gl_color_node_free (&fill_color_node);
389
390         gl_debug (DEBUG_LABEL, "END");
391 }
392
393
394 /*****************************************************************************/
395 /* Draw shadow method.                                                       */
396 /*****************************************************************************/
397 static void
398 draw_shadow (glLabelObject *object,
399              cairo_t       *cr,
400              gboolean       screen_flag,
401              glMergeRecord *record)
402 {
403         gdouble        w, h;
404         gdouble        line_width;
405         glColorNode   *line_color_node;
406         glColorNode   *fill_color_node;
407         guint          line_color;
408         guint          fill_color;
409         glColorNode   *shadow_color_node;
410         guint          shadow_color;
411         gdouble        shadow_opacity;
412
413         gl_debug (DEBUG_LABEL, "START");
414
415         cairo_save (cr);
416
417         gl_label_object_get_size (object, &w, &h);
418
419         line_width = gl_label_object_get_line_width (object);
420         
421         line_color_node = gl_label_object_get_line_color (object);
422         fill_color_node = gl_label_object_get_fill_color (object);
423         line_color = gl_color_node_expand (line_color_node, record);
424         fill_color = gl_color_node_expand (fill_color_node, record);
425         if (line_color_node->field_flag && screen_flag)
426         {
427                 line_color = GL_COLOR_MERGE_DEFAULT;
428         }
429         if (fill_color_node->field_flag && screen_flag)
430         {
431                 fill_color = GL_COLOR_FILL_MERGE_DEFAULT;
432         }
433
434         shadow_color_node = gl_label_object_get_shadow_color (object);
435         shadow_color = gl_color_node_expand (shadow_color_node, record);
436         if (shadow_color_node->field_flag && screen_flag)
437         {
438                 shadow_color = GL_COLOR_SHADOW_MERGE_DEFAULT;
439         }
440         shadow_opacity = gl_label_object_get_shadow_opacity (object);
441         shadow_color = gl_color_set_opacity (shadow_color, shadow_opacity);
442         
443
444         cairo_set_source_rgba (cr, GL_COLOR_RGBA_ARGS (shadow_color));
445
446         if ( GL_COLOR_F_ALPHA (fill_color) )
447         {
448                 if ( GL_COLOR_F_ALPHA (line_color) )
449                 {
450                         /* Has FILL and OUTLINE: adjust size to account for line width. */
451                         cairo_rectangle (cr,
452                                          -line_width/2, -line_width/2,
453                                          w+line_width, h+line_width);
454
455                 }
456                 else
457                 {
458                         /* Has FILL but no OUTLINE. */
459                         cairo_rectangle (cr, 0.0, 0.0, w, h);
460                 }
461
462                 /* Draw shadow */
463                 cairo_fill (cr);
464         }
465         else
466         {
467                 if ( GL_COLOR_F_ALPHA (line_color) )
468                 {
469                         /* Has only OUTLINE. */
470                         cairo_rectangle (cr, 0.0, 0.0, w, h);
471
472                         /* Draw shadow of outline */
473                         cairo_set_line_width (cr, line_width);
474                         cairo_stroke (cr);
475                 }
476         }
477
478
479         gl_color_node_free (&line_color_node);
480         gl_color_node_free (&fill_color_node);
481         gl_color_node_free (&shadow_color_node);
482
483         cairo_restore (cr);
484
485         gl_debug (DEBUG_LABEL, "END");
486 }
487
488
489 /*****************************************************************************/
490 /* Is object at coordinates?                                                 */
491 /*****************************************************************************/
492 static gboolean
493 object_at (glLabelObject *object,
494            cairo_t       *cr,
495            gdouble        x,
496            gdouble        y)
497 {
498         gdouble           w, h;
499         gdouble           line_width;
500
501         gl_label_object_get_size (object, &w, &h);
502
503         cairo_new_path (cr);
504         cairo_rectangle (cr, 0.0, 0.0, w, h);
505
506         if (cairo_in_fill (cr, x, y))
507         {
508                 return TRUE;
509         }
510
511         line_width = gl_label_object_get_line_width (object);
512         cairo_set_line_width (cr, line_width);
513         if (cairo_in_stroke (cr, x, y))
514         {
515                 return TRUE;
516         }
517
518         return FALSE;
519 }
520
521
522
523
524 /*
525  * Local Variables:       -- emacs
526  * mode: C                -- emacs
527  * c-basic-offset: 8      -- emacs
528  * tab-width: 8           -- emacs
529  * indent-tabs-mode: nil  -- emacs
530  * End:                   -- emacs
531  */