]> git.sur5r.net Git - glabels/blob - glabels2/src/mini-label-preview.c
e58986fd97aca0466f13a9fad51549a21aae9f59
[glabels] / glabels2 / src / mini-label-preview.c
1 /*
2  *  mini-label-preview.c
3  *  Copyright (C) 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 <config.h>
22
23 #include "mini-label-preview.h"
24
25 #include <libglabels/libglabels.h>
26 #include "cairo-label-path.h"
27 #include "color.h"
28 #include "marshal.h"
29
30
31 /*===========================================*/
32 /* Private macros and constants.             */
33 /*===========================================*/
34
35 #define MARGIN 2
36 #define SHADOW_OFFSET 3
37
38
39 /*===========================================*/
40 /* Private types                             */
41 /*===========================================*/
42
43 struct _glMiniLabelPreviewPrivate {
44
45         lglTemplate *template;
46         gboolean     rotate_flag;
47 };
48
49
50 /*===========================================*/
51 /* Private globals                           */
52 /*===========================================*/
53
54
55 /*===========================================*/
56 /* Local function prototypes                 */
57 /*===========================================*/
58
59 static void       gl_mini_label_preview_finalize (GObject              *object);
60
61 static void       style_set_cb                   (GtkWidget            *widget,
62                                                   GtkStyle             *previous_style);
63
64 static void       redraw                         (glMiniLabelPreview   *this);
65
66 static gboolean   expose_event_cb                (GtkWidget            *widget,
67                                                   GdkEventExpose       *event);
68
69 static void       draw_preview                   (glMiniLabelPreview   *this,
70                                                   cairo_t              *cr);
71
72
73 /****************************************************************************/
74 /* Boilerplate Object stuff.                                                */
75 /****************************************************************************/
76 G_DEFINE_TYPE (glMiniLabelPreview, gl_mini_label_preview, GTK_TYPE_DRAWING_AREA);
77
78
79 /*****************************************************************************/
80 /* Class Init Function.                                                      */
81 /*****************************************************************************/
82 static void
83 gl_mini_label_preview_class_init (glMiniLabelPreviewClass *class)
84 {
85         GObjectClass   *gobject_class = G_OBJECT_CLASS (class);
86         GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
87
88         gl_mini_label_preview_parent_class = g_type_class_peek_parent (class);
89
90         gobject_class->finalize    = gl_mini_label_preview_finalize;
91
92         widget_class->expose_event = expose_event_cb;
93         widget_class->style_set    = style_set_cb;
94 }
95
96
97 /*****************************************************************************/
98 /* Object Instance Init Function.                                            */
99 /*****************************************************************************/
100 static void
101 gl_mini_label_preview_init (glMiniLabelPreview *this)
102 {
103         GTK_WIDGET_SET_FLAGS (GTK_WIDGET (this), GTK_NO_WINDOW);
104
105         this->priv = g_new0 (glMiniLabelPreviewPrivate, 1);
106 }
107
108
109 /*****************************************************************************/
110 /* Finalize Method.                                                          */
111 /*****************************************************************************/
112 static void
113 gl_mini_label_preview_finalize (GObject *object)
114 {
115         glMiniLabelPreview *this = GL_MINI_LABEL_PREVIEW (object);
116
117         g_return_if_fail (object != NULL);
118         g_return_if_fail (GL_IS_MINI_LABEL_PREVIEW (object));
119
120         lgl_template_free (this->priv->template);
121         g_free (this->priv);
122
123         G_OBJECT_CLASS (gl_mini_label_preview_parent_class)->finalize (object);
124 }
125
126
127 /*****************************************************************************/
128 /** New Object Generator.                                                    */
129 /*****************************************************************************/
130 GtkWidget *
131 gl_mini_label_preview_new (gint         w,
132                            gint         h)
133 {
134         glMiniLabelPreview *this;
135
136         this = g_object_new (GL_TYPE_MINI_LABEL_PREVIEW, NULL);
137
138         gtk_widget_set_size_request (GTK_WIDGET (this), w, h);
139
140         return GTK_WIDGET (this);
141 }
142
143
144 /*****************************************************************************/
145 /* Set label by name.                                                        */
146 /*****************************************************************************/
147 void
148 gl_mini_label_preview_set_by_name (glMiniLabelPreview *this,
149                                    gchar              *name,
150                                    gboolean            rotate_flag)
151 {
152         if (!name)
153         {
154                 lgl_template_free (this->priv->template);
155                 this->priv->template = NULL;
156         }
157         else
158         {
159                 this->priv->template = lgl_db_lookup_template_from_name (name);
160                 this->priv->rotate_flag = rotate_flag;
161         }
162
163         redraw (this);
164 }
165
166
167 /*--------------------------------------------------------------------------*/
168 /* Style set handler (updates colors when style/theme changes).             */
169 /*--------------------------------------------------------------------------*/
170 static void
171 style_set_cb (GtkWidget        *widget,
172               GtkStyle         *previous_style)
173 {
174         redraw (GL_MINI_LABEL_PREVIEW (widget));
175 }
176
177
178 /*****************************************************************************/
179 /* Request redraw.                                                           */
180 /*****************************************************************************/
181 static void
182 redraw (glMiniLabelPreview  *this)
183 {
184         GdkRegion *region;
185
186         if (GTK_WIDGET_REALIZED (GTK_WIDGET (this)))
187         {
188                 /* redraw the cairo canvas forcing an expose event */
189                 region = gdk_drawable_get_clip_region (GTK_WIDGET (this)->window);
190                 gdk_window_invalidate_region (GTK_WIDGET (this)->window, region, TRUE);
191                 gdk_region_destroy (region);
192         }
193 }
194
195
196 /*****************************************************************************/
197 /* "Expose event" callback.                                                  */
198 /*****************************************************************************/
199 static gboolean
200 expose_event_cb (GtkWidget      *widget,
201                  GdkEventExpose *event)
202 {
203         cairo_t *cr;
204
205         cr = gdk_cairo_create (widget->window);
206
207         cairo_rectangle (cr,
208                         event->area.x, event->area.y,
209                         event->area.width, event->area.height);
210         cairo_clip (cr);
211
212         cairo_translate (cr, widget->allocation.x, widget->allocation.y);
213
214         draw_preview (GL_MINI_LABEL_PREVIEW (widget), cr);
215
216         cairo_destroy (cr);
217
218         return FALSE;
219 }
220
221
222 /*****************************************************************************/
223 /* Draw sample.                                                              */
224 /*****************************************************************************/
225 static void
226 draw_preview (glMiniLabelPreview *this,
227               cairo_t            *cr)
228 {
229         GtkStyle               *style;
230         gdouble                 w, h;
231         guint                   fill_color, line_color, shadow_color;
232         const lglTemplateFrame *frame;
233         gdouble                 w_label, h_label;
234         gdouble                 scale;
235
236
237         w = GTK_WIDGET (this)->allocation.width;
238         h = GTK_WIDGET (this)->allocation.height;
239
240
241         style = gtk_widget_get_style (GTK_WIDGET (this));
242         if ( GTK_WIDGET_IS_SENSITIVE (GTK_WIDGET (this)) )
243         {
244                 fill_color   = gl_color_from_gdk_color (&style->light[GTK_STATE_NORMAL]);
245                 line_color   = gl_color_from_gdk_color (&style->fg[GTK_STATE_NORMAL]);
246                 shadow_color = gl_color_from_gdk_color (&style->dark[GTK_STATE_NORMAL]);
247         }
248         else
249         {
250                 fill_color   = GL_COLOR_NONE;
251                 line_color   = gl_color_from_gdk_color (&style->fg[GTK_STATE_INSENSITIVE]);
252                 shadow_color = GL_COLOR_NONE;
253         }
254
255
256         if (this->priv->template == NULL)
257         {
258                 return;
259         }
260
261         frame = (lglTemplateFrame *)this->priv->template->frames->data;
262
263         if (this->priv->rotate_flag)
264         {
265                 lgl_template_frame_get_size (frame, &h_label, &w_label);
266         }
267         else
268         {
269                 lgl_template_frame_get_size (frame, &w_label, &h_label);
270         }
271
272         scale = MIN( (w - 2*MARGIN - 2*SHADOW_OFFSET)/w_label,
273                      (h - 2*MARGIN - 2*SHADOW_OFFSET)/h_label );
274
275
276         cairo_translate (cr, w/2.0, h/2.0);
277         cairo_scale (cr, scale, scale);
278         cairo_translate (cr, -w_label/2.0, -h_label/2.0);
279
280
281         /*
282          * Shadow
283          */
284         cairo_save (cr);
285         cairo_translate (cr, SHADOW_OFFSET/scale, SHADOW_OFFSET/scale);
286         gl_cairo_label_path (cr, this->priv->template, this->priv->rotate_flag, FALSE);
287
288         cairo_set_source_rgba (cr, GL_COLOR_RGBA_ARGS (shadow_color));
289         cairo_fill (cr);
290         cairo_restore (cr);
291
292         /*
293          * Label + outline
294          */
295         gl_cairo_label_path (cr, this->priv->template, this->priv->rotate_flag, FALSE);
296
297         cairo_set_source_rgba (cr, GL_COLOR_RGBA_ARGS (fill_color));
298         cairo_fill_preserve (cr);
299
300         cairo_set_line_width (cr, 1.0/scale);
301         cairo_set_source_rgba (cr, GL_COLOR_RGBA_ARGS (line_color));
302         cairo_stroke (cr);
303
304 }
305
306
307
308 /*
309  * Local Variables:       -- emacs
310  * mode: C                -- emacs
311  * c-basic-offset: 8      -- emacs
312  * tab-width: 8           -- emacs
313  * indent-tabs-mode: nil  -- emacs
314  * End:                   -- emacs
315  */