]> git.sur5r.net Git - glabels/blob - src/wdgt-rotate-label.c
Imported Upstream version 2.2.8
[glabels] / src / wdgt-rotate-label.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  *  wdgt_rotate_label.c:  label rotate selection widget module
7  *
8  *  Copyright (C) 2001-2006  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
25 #include <config.h>
26
27 #include "wdgt-rotate-label.h"
28
29 #include <glib/gi18n.h>
30 #include <glade/glade-xml.h>
31 #include <gtk/gtktogglebutton.h>
32 #include <gtk/gtkcheckbutton.h>
33 #include <gtk/gtkdrawingarea.h>
34 #include <math.h>
35
36 #include "marshal.h"
37 #include "color.h"
38 #include <libglabels/db.h>
39 #include "cairo-label-path.h"
40
41 #include "debug.h"
42
43 /*========================================================*/
44 /* Private macros and constants.                          */
45 /*========================================================*/
46 #define MINI_PREVIEW_MAX_PIXELS 48
47 #define MINI_PREVIEW_CANVAS_PIXELS (MINI_PREVIEW_MAX_PIXELS + 8)
48
49 #define LINE_COLOR             GL_COLOR(0,0,0)
50 #define FILL_COLOR             GL_COLOR(255,255,255)
51
52 #define LINE_WIDTH_PIXELS    1.0
53
54 #define SHADOW_X_OFFSET 3
55 #define SHADOW_Y_OFFSET 3
56
57
58 /*===========================================*/
59 /* Private types                             */
60 /*===========================================*/
61
62 struct _glWdgtRotateLabelPrivate {
63
64         GtkWidget    *rotate_check;
65         GtkWidget    *rotate_drawingarea;
66
67         lglTemplate  *template;
68 };
69
70 enum {
71         CHANGED,
72         LAST_SIGNAL
73 };
74
75 /*===========================================*/
76 /* Private globals                           */
77 /*===========================================*/
78
79 static gint wdgt_rotate_label_signals[LAST_SIGNAL] = { 0 };
80
81 /*===========================================*/
82 /* Local function prototypes                 */
83 /*===========================================*/
84
85 static void gl_wdgt_rotate_label_finalize      (GObject                *object);
86
87 static void gl_wdgt_rotate_label_construct     (glWdgtRotateLabel      *rotate_label);
88
89 static void entry_changed_cb                   (GtkToggleButton        *toggle,
90                                                 gpointer                user_data);
91
92 static void drawingarea_update                 (GtkDrawingArea         *drawing_area,
93                                                 lglTemplate            *template,
94                                                 gboolean                rotate_flag);
95
96 static gboolean expose_cb                      (GtkWidget              *drawingarea,
97                                                 GdkEventExpose         *event,
98                                                 gpointer                user_data);
99
100
101 /****************************************************************************/
102 /* Boilerplate Object stuff.                                                */
103 /****************************************************************************/
104 G_DEFINE_TYPE (glWdgtRotateLabel, gl_wdgt_rotate_label, GTK_TYPE_VBOX);
105
106
107 static void
108 gl_wdgt_rotate_label_class_init (glWdgtRotateLabelClass *class)
109 {
110         GObjectClass *object_class = G_OBJECT_CLASS (class);
111
112         gl_wdgt_rotate_label_parent_class = g_type_class_peek_parent (class);
113
114         object_class->finalize = gl_wdgt_rotate_label_finalize;
115
116         wdgt_rotate_label_signals[CHANGED] =
117             g_signal_new ("changed",
118                           G_OBJECT_CLASS_TYPE(object_class),
119                           G_SIGNAL_RUN_LAST,
120                           G_STRUCT_OFFSET (glWdgtRotateLabelClass, changed),
121                           NULL, NULL,
122                           gl_marshal_VOID__VOID,
123                           G_TYPE_NONE, 0);
124
125 }
126
127 static void
128 gl_wdgt_rotate_label_init (glWdgtRotateLabel *rotate_label)
129 {
130         rotate_label->priv = g_new0 (glWdgtRotateLabelPrivate, 1);
131 }
132
133 static void
134 gl_wdgt_rotate_label_finalize (GObject *object)
135 {
136         glWdgtRotateLabel      *rotate_label = GL_WDGT_ROTATE_LABEL (object);
137
138         g_return_if_fail (object != NULL);
139         g_return_if_fail (GL_IS_WDGT_ROTATE_LABEL (object));
140
141         if (rotate_label->priv->template) {
142                 lgl_template_free (rotate_label->priv->template);
143                 rotate_label->priv->template = NULL;
144         }
145         g_free (rotate_label->priv);
146
147         G_OBJECT_CLASS (gl_wdgt_rotate_label_parent_class)->finalize (object);
148 }
149
150 GtkWidget *
151 gl_wdgt_rotate_label_new (void)
152 {
153         glWdgtRotateLabel *rotate_label;
154
155         rotate_label = g_object_new (gl_wdgt_rotate_label_get_type (), NULL);
156
157         gl_wdgt_rotate_label_construct (rotate_label);
158
159         return GTK_WIDGET (rotate_label);
160 }
161
162 /*--------------------------------------------------------------------------*/
163 /* Construct composite widget.                                              */
164 /*--------------------------------------------------------------------------*/
165 static void
166 gl_wdgt_rotate_label_construct (glWdgtRotateLabel *rotate_label)
167 {
168         GladeXML  *gui;
169         GtkWidget *hbox;
170
171         g_return_if_fail (GL_IS_WDGT_ROTATE_LABEL (rotate_label));
172         g_return_if_fail (rotate_label->priv != NULL);
173
174         gui = glade_xml_new (GLABELS_GLADE_DIR "wdgt-rotate-label.glade",
175                              "rotate_hbox", NULL);
176
177         if (!gui) {
178                 g_critical ("Could not open wdgt-media-select.glade. gLabels may not be installed correctly!");
179                 return;
180         }
181
182         hbox = glade_xml_get_widget (gui, "rotate_hbox");
183         gtk_container_add (GTK_CONTAINER (rotate_label), hbox);
184
185         rotate_label->priv->rotate_check       = glade_xml_get_widget (gui, "rotate_check");
186         rotate_label->priv->rotate_drawingarea = glade_xml_get_widget (gui, "rotate_drawingarea");
187
188         g_object_unref (gui);
189
190
191         gtk_widget_set_size_request (rotate_label->priv->rotate_drawingarea,
192                                      MINI_PREVIEW_CANVAS_PIXELS,
193                                      MINI_PREVIEW_CANVAS_PIXELS);
194
195         /* Connect signals to controls */
196         g_signal_connect (G_OBJECT (rotate_label->priv->rotate_check),
197                           "toggled",
198                           G_CALLBACK (entry_changed_cb), rotate_label);
199         g_signal_connect (G_OBJECT (rotate_label->priv->rotate_drawingarea),
200                           "expose_event",
201                           G_CALLBACK (expose_cb), rotate_label);
202 }
203
204 /*--------------------------------------------------------------------------*/
205 /* PRIVATE.  modify widget due to change of check button                    */
206 /*--------------------------------------------------------------------------*/
207 static void
208 entry_changed_cb (GtkToggleButton *toggle,
209                   gpointer         user_data)
210 {
211         glWdgtRotateLabel *rotate_label = GL_WDGT_ROTATE_LABEL (user_data);
212
213         if (rotate_label->priv->template != NULL) {
214                 /* Update mini_preview canvas & details with template */
215                 drawingarea_update (GTK_DRAWING_AREA (rotate_label->priv->rotate_drawingarea),
216                                     rotate_label->priv->template,
217                                     gtk_toggle_button_get_active (toggle));
218         }
219
220         /* Emit our "changed" signal */
221         g_signal_emit (G_OBJECT (user_data),
222                        wdgt_rotate_label_signals[CHANGED], 0);
223
224 }
225
226 /*--------------------------------------------------------------------------*/
227 /* PRIVATE.  Update mini-preview from template           .                  */
228 /*--------------------------------------------------------------------------*/
229 static void
230 drawingarea_update (GtkDrawingArea *drawing_area,
231                     lglTemplate    *template,
232                     gboolean        rotate_flag)
233 {
234         const lglTemplateFrame    *frame;
235         gdouble                    m, m_canvas, w, h, scale;
236         GtkStyle                  *style;
237         guint                      line_color, fill_color, shadow_color;
238         cairo_t                   *cr;
239
240         if (!GTK_WIDGET_DRAWABLE (GTK_WIDGET (drawing_area)))
241         {
242                 return;
243         }
244
245         /* Clear surface */
246         gdk_window_clear (GTK_WIDGET (drawing_area)->window);
247
248         if (template == NULL)
249         {
250                 return;
251         }
252
253         frame = (lglTemplateFrame *)template->frames->data;
254
255         if (rotate_flag)
256         {
257                 lgl_template_frame_get_size (frame, &h, &w);
258         }
259         else
260         {
261                 lgl_template_frame_get_size (frame, &w, &h);
262         }
263         m = MAX (w, h);
264         scale = MINI_PREVIEW_MAX_PIXELS / m;
265         m_canvas = MINI_PREVIEW_CANVAS_PIXELS / scale;
266
267         style = gtk_widget_get_style (GTK_WIDGET (drawing_area));
268
269         /* Adjust sensitivity (should the canvas be grayed?) */
270         if (w != h) {
271                 line_color = LINE_COLOR;
272                 fill_color = FILL_COLOR;
273         } else {
274                 line_color = gl_color_from_gdk_color (&style->text[GTK_STATE_INSENSITIVE]);
275                 fill_color = gl_color_from_gdk_color (&style->base[GTK_STATE_INSENSITIVE]);
276         }
277
278         shadow_color = gl_color_from_gdk_color (&style->bg[GTK_STATE_ACTIVE]);
279
280
281         cr = gdk_cairo_create (GTK_WIDGET (drawing_area)->window);
282   
283         cairo_identity_matrix (cr);
284         cairo_translate (cr, MINI_PREVIEW_CANVAS_PIXELS/2, MINI_PREVIEW_CANVAS_PIXELS/2);
285         cairo_scale (cr, scale, scale);
286         cairo_translate (cr, -w/2.0, -h/2.0);
287
288         /*
289          * Shadow
290          */
291         cairo_save (cr);
292         cairo_translate (cr, SHADOW_X_OFFSET/scale, SHADOW_Y_OFFSET/scale);
293         gl_cairo_label_path (cr, template, rotate_flag, FALSE);
294
295         cairo_set_source_rgb (cr, GL_COLOR_RGB_ARGS (shadow_color));
296         cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
297         cairo_fill (cr);
298         cairo_restore (cr);
299
300         /*
301          * Label + outline
302          */
303         gl_cairo_label_path (cr, template, rotate_flag, FALSE);
304
305         cairo_set_source_rgb (cr, GL_COLOR_RGB_ARGS (fill_color));
306         cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
307         cairo_fill_preserve (cr);
308
309         cairo_set_line_width (cr, LINE_WIDTH_PIXELS/scale);
310         cairo_set_source_rgb (cr, GL_COLOR_RGB_ARGS (line_color));
311         cairo_stroke (cr);
312
313
314         cairo_destroy (cr);
315
316 }
317
318 /*--------------------------------------------------------------------------*/
319 /* PRIVATE.  Expose handler.                                                */
320 /*--------------------------------------------------------------------------*/
321 static gboolean
322 expose_cb (GtkWidget *drawingarea, GdkEventExpose *event, gpointer user_data)
323 {
324         glWdgtRotateLabel *rotate_label = GL_WDGT_ROTATE_LABEL (user_data);
325
326         drawingarea_update (GTK_DRAWING_AREA (drawingarea),
327                             rotate_label->priv->template,
328                             gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (rotate_label->priv->rotate_check)));
329
330         return FALSE;
331 }
332
333 /****************************************************************************/
334 /* query state of widget.                                                   */
335 /****************************************************************************/
336 gboolean
337 gl_wdgt_rotate_label_get_state (glWdgtRotateLabel *rotate_label)
338 {
339         return
340             gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
341                                           (rotate_label->priv->rotate_check));
342 }
343
344 /****************************************************************************/
345 /* set state of widget.                                                     */
346 /****************************************************************************/
347 void
348 gl_wdgt_rotate_label_set_state (glWdgtRotateLabel *rotate_label,
349                                 gboolean state)
350 {
351         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
352                                       (rotate_label->priv->rotate_check), state);
353 }
354
355 /****************************************************************************/
356 /* set template for widget.                                                 */
357 /****************************************************************************/
358 void
359 gl_wdgt_rotate_label_set_template_name (glWdgtRotateLabel *rotate_label,
360                                         gchar             *name)
361 {
362         lglTemplate               *template;
363         const lglTemplateFrame    *frame;
364         gdouble                    raw_w, raw_h;
365
366         if (name == NULL)
367         {
368                 rotate_label->priv->template = NULL;
369
370                 gtk_widget_set_sensitive (rotate_label->priv->rotate_check,
371                                           FALSE);
372
373                 drawingarea_update (GTK_DRAWING_AREA (rotate_label->priv->rotate_drawingarea),
374                                     NULL,
375                                     FALSE);
376         }
377         else
378         {
379                 template = lgl_db_lookup_template_from_name (name);
380                 frame = (lglTemplateFrame *)template->frames->data;
381
382                 rotate_label->priv->template = template;
383                 lgl_template_frame_get_size (frame, &raw_w, &raw_h);
384
385                 gtk_widget_set_sensitive (rotate_label->priv->rotate_check,
386                                           (raw_w != raw_h));
387
388                 drawingarea_update (GTK_DRAWING_AREA (rotate_label->priv->rotate_drawingarea),
389                                     rotate_label->priv->template,
390                                     FALSE);
391         }
392         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
393                                       (rotate_label->priv->rotate_check), FALSE);
394 }
395