1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
4 * (GLABELS) Label and Business Card Creation program for GNOME
6 * wdgt_rotate_label.c: label rotate selection widget module
8 * Copyright (C) 2001-2006 Jim Evins <evins@snaught.com>.
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.
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.
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
27 #include "wdgt-rotate-label.h"
29 #include <glib/gi18n.h>
30 #include <gtk/gtkradiobutton.h>
31 #include <gtk/gtkdrawingarea.h>
37 #include <libglabels/db.h>
38 #include "cairo-label-path.h"
42 /*========================================================*/
43 /* Private macros and constants. */
44 /*========================================================*/
45 #define MINI_PREVIEW_MAX_PIXELS 48
46 #define MINI_PREVIEW_CANVAS_PIXELS (MINI_PREVIEW_MAX_PIXELS + 8)
48 #define LINE_COLOR GL_COLOR(0,0,0)
49 #define FILL_COLOR GL_COLOR(255,255,255)
50 #define SHADOW_COLOR GL_COLOR_A(192,192,192,128)
52 #define LINE_WIDTH_PIXELS 1.0
54 #define SHADOW_X_OFFSET 3
55 #define SHADOW_Y_OFFSET 3
58 /*===========================================*/
60 /*===========================================*/
62 struct _glWdgtRotateLabelPrivate {
64 GtkWidget *no_rotate_radio;
65 GtkWidget *rotate_radio;
66 GtkWidget *no_rotate_image;
67 GtkWidget *rotate_image;
69 lglTemplate *template;
77 /*===========================================*/
79 /*===========================================*/
81 static gint wdgt_rotate_label_signals[LAST_SIGNAL] = { 0 };
83 /*===========================================*/
84 /* Local function prototypes */
85 /*===========================================*/
87 static void gl_wdgt_rotate_label_finalize (GObject *object);
89 static void toggled_cb (GtkToggleButton *toggle,
92 static GdkPixbuf *create_pixbuf (lglTemplate *template,
93 gboolean rotate_flag);
96 /****************************************************************************/
97 /* Boilerplate Object stuff. */
98 /****************************************************************************/
99 G_DEFINE_TYPE (glWdgtRotateLabel, gl_wdgt_rotate_label, GTK_TYPE_HBOX);
103 gl_wdgt_rotate_label_class_init (glWdgtRotateLabelClass *class)
105 GObjectClass *object_class = G_OBJECT_CLASS (class);
107 gl_wdgt_rotate_label_parent_class = g_type_class_peek_parent (class);
109 object_class->finalize = gl_wdgt_rotate_label_finalize;
111 wdgt_rotate_label_signals[CHANGED] =
112 g_signal_new ("changed",
113 G_OBJECT_CLASS_TYPE(object_class),
115 G_STRUCT_OFFSET (glWdgtRotateLabelClass, changed),
117 gl_marshal_VOID__VOID,
123 gl_wdgt_rotate_label_init (glWdgtRotateLabel *rotate_label)
125 rotate_label->priv = g_new0 (glWdgtRotateLabelPrivate, 1);
127 gtk_container_set_border_width (GTK_CONTAINER (rotate_label), GL_HIG_PAD2);
129 rotate_label->priv->no_rotate_radio = gtk_radio_button_new_with_label (NULL, _("Normal"));
130 rotate_label->priv->rotate_radio = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (rotate_label->priv->no_rotate_radio), _("Rotated"));
132 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rotate_label->priv->no_rotate_radio),
134 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rotate_label->priv->rotate_radio),
137 gtk_button_set_image_position (GTK_BUTTON (rotate_label->priv->no_rotate_radio),
139 gtk_button_set_image_position (GTK_BUTTON (rotate_label->priv->rotate_radio),
142 rotate_label->priv->no_rotate_image = gtk_image_new ();
143 rotate_label->priv->rotate_image = gtk_image_new ();
145 gtk_button_set_image (GTK_BUTTON (rotate_label->priv->no_rotate_radio),
146 rotate_label->priv->no_rotate_image);
147 gtk_button_set_image (GTK_BUTTON (rotate_label->priv->rotate_radio),
148 rotate_label->priv->rotate_image);
150 gtk_box_pack_start (GTK_BOX (rotate_label),
151 rotate_label->priv->no_rotate_radio,
152 FALSE, FALSE, GL_HIG_PAD1);
153 gtk_box_pack_start (GTK_BOX (rotate_label),
154 rotate_label->priv->rotate_radio,
155 FALSE, FALSE, GL_HIG_PAD1);
157 /* Connect signals to controls */
158 g_signal_connect (G_OBJECT (rotate_label->priv->no_rotate_radio),
160 G_CALLBACK (toggled_cb), rotate_label);
161 g_signal_connect (G_OBJECT (rotate_label->priv->rotate_radio),
163 G_CALLBACK (toggled_cb), rotate_label);
167 gl_wdgt_rotate_label_finalize (GObject *object)
169 glWdgtRotateLabel *rotate_label = GL_WDGT_ROTATE_LABEL (object);
171 g_return_if_fail (object != NULL);
172 g_return_if_fail (GL_IS_WDGT_ROTATE_LABEL (object));
174 if (rotate_label->priv->template) {
175 lgl_template_free (rotate_label->priv->template);
176 rotate_label->priv->template = NULL;
178 g_free (rotate_label->priv);
180 G_OBJECT_CLASS (gl_wdgt_rotate_label_parent_class)->finalize (object);
184 gl_wdgt_rotate_label_new (void)
186 glWdgtRotateLabel *rotate_label;
188 rotate_label = g_object_new (gl_wdgt_rotate_label_get_type (), NULL);
190 return GTK_WIDGET (rotate_label);
193 /*--------------------------------------------------------------------------*/
194 /* PRIVATE. modify widget due to change of check button */
195 /*--------------------------------------------------------------------------*/
197 toggled_cb (GtkToggleButton *toggle,
201 /* Emit our "changed" signal */
202 g_signal_emit (G_OBJECT (user_data),
203 wdgt_rotate_label_signals[CHANGED], 0);
207 /*--------------------------------------------------------------------------*/
208 /* PRIVATE. Update mini-preview from template . */
209 /*--------------------------------------------------------------------------*/
211 create_pixbuf (lglTemplate *template,
212 gboolean rotate_flag)
215 cairo_surface_t *surface;
216 const lglTemplateFrame *frame;
217 gdouble m, m_canvas, w, h, scale;
221 /* Create pixbuf and cairo context. */
222 pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, MINI_PREVIEW_CANVAS_PIXELS, MINI_PREVIEW_CANVAS_PIXELS);
223 surface = cairo_image_surface_create_for_data (gdk_pixbuf_get_pixels (pixbuf),
225 gdk_pixbuf_get_width (pixbuf),
226 gdk_pixbuf_get_height (pixbuf),
227 gdk_pixbuf_get_rowstride (pixbuf));
230 if (template == NULL)
235 frame = (lglTemplateFrame *)template->frames->data;
239 lgl_template_frame_get_size (frame, &h, &w);
243 lgl_template_frame_get_size (frame, &w, &h);
246 scale = MINI_PREVIEW_MAX_PIXELS / m;
247 m_canvas = MINI_PREVIEW_CANVAS_PIXELS / scale;
249 cr = cairo_create (surface);
250 cairo_surface_destroy (surface);
254 cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
258 cairo_set_antialias (cr, CAIRO_ANTIALIAS_GRAY);
260 cairo_identity_matrix (cr);
261 cairo_translate (cr, MINI_PREVIEW_CANVAS_PIXELS/2, MINI_PREVIEW_CANVAS_PIXELS/2);
262 cairo_scale (cr, scale, scale);
263 cairo_translate (cr, -w/2.0, -h/2.0);
269 cairo_translate (cr, SHADOW_X_OFFSET/scale, SHADOW_Y_OFFSET/scale);
270 gl_cairo_label_path (cr, template, rotate_flag, FALSE);
272 cairo_set_source_rgb (cr, GL_COLOR_RGB_ARGS (SHADOW_COLOR));
273 cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
280 gl_cairo_label_path (cr, template, rotate_flag, FALSE);
282 cairo_set_source_rgb (cr, GL_COLOR_RGB_ARGS (FILL_COLOR));
283 cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
284 cairo_fill_preserve (cr);
286 cairo_set_line_width (cr, LINE_WIDTH_PIXELS/scale);
287 cairo_set_source_rgb (cr, GL_COLOR_RGB_ARGS (LINE_COLOR));
296 /****************************************************************************/
297 /* query state of widget. */
298 /****************************************************************************/
300 gl_wdgt_rotate_label_get_state (glWdgtRotateLabel *rotate_label)
303 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
304 (rotate_label->priv->rotate_radio));
307 /****************************************************************************/
308 /* set state of widget. */
309 /****************************************************************************/
311 gl_wdgt_rotate_label_set_state (glWdgtRotateLabel *rotate_label,
314 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
315 (rotate_label->priv->rotate_radio), state);
318 /****************************************************************************/
319 /* set template for widget. */
320 /****************************************************************************/
322 gl_wdgt_rotate_label_set_template_name (glWdgtRotateLabel *rotate_label,
325 lglTemplate *template;
326 const lglTemplateFrame *frame;
327 gdouble raw_w, raw_h;
331 rotate_label->priv->template = NULL;
333 gtk_widget_set_sensitive (rotate_label->priv->no_rotate_radio, FALSE);
334 gtk_widget_set_sensitive (rotate_label->priv->rotate_radio, FALSE);
338 template = lgl_db_lookup_template_from_name (name);
339 frame = (lglTemplateFrame *)template->frames->data;
341 rotate_label->priv->template = template;
342 lgl_template_frame_get_size (frame, &raw_w, &raw_h);
344 gtk_image_set_from_pixbuf (GTK_IMAGE (rotate_label->priv->no_rotate_image),
345 create_pixbuf (rotate_label->priv->template, FALSE));
346 gtk_image_set_from_pixbuf (GTK_IMAGE (rotate_label->priv->rotate_image),
347 create_pixbuf (rotate_label->priv->template, TRUE));
349 gtk_widget_set_sensitive (rotate_label->priv->no_rotate_radio,
351 gtk_widget_set_sensitive (rotate_label->priv->rotate_radio,
354 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
355 (rotate_label->priv->no_rotate_radio), TRUE);
356 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
357 (rotate_label->priv->rotate_radio), FALSE);