2 * (GLABELS) Label and Business Card Creation program for GNOME
4 * wdgt_rotate_label.c: label rotate selection widget module
6 * Copyright (C) 2001-2002 Jim Evins <evins@snaught.com>.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include "wdgt-rotate-label.h"
35 /*========================================================*/
36 /* Private macros and constants. */
37 /*========================================================*/
38 #define MINI_PREVIEW_MAX_PIXELS 48
39 #define MINI_PREVIEW_CANVAS_PIXELS (MINI_PREVIEW_MAX_PIXELS + 8)
41 #define LINE_COLOR GL_COLOR(0,0,0)
42 #define FILL_COLOR GL_COLOR(255,255,255)
43 #define UNSENSITIVE_LINE_COLOR GL_COLOR(0x66,0x66,0x66)
44 #define UNSENSITIVE_FILL_COLOR GL_COLOR(0xCC,0xCC,0xCC)
46 #define RES 5 /* Resolution in degrees for Business Card CD outlines */
48 /*===========================================*/
50 /*===========================================*/
57 typedef void (*glWdgtRotateLabelSignal) (GObject * object, gpointer data);
59 /*===========================================*/
61 /*===========================================*/
63 static GObjectClass *parent_class;
65 static gint wdgt_rotate_label_signals[LAST_SIGNAL] = { 0 };
67 /*===========================================*/
68 /* Local function prototypes */
69 /*===========================================*/
71 static void gl_wdgt_rotate_label_class_init (glWdgtRotateLabelClass *class);
72 static void gl_wdgt_rotate_label_instance_init (glWdgtRotateLabel *rotate_select);
73 static void gl_wdgt_rotate_label_finalize (GObject *object);
75 static void gl_wdgt_rotate_label_construct (glWdgtRotateLabel *rotate_select);
77 static void entry_changed_cb (GtkToggleButton *toggle,
80 static GtkWidget *mini_preview_canvas_new (void);
82 static void mini_preview_canvas_update (GnomeCanvas *canvas,
84 gboolean rotate_flag);
86 static GnomeCanvasItem *cdbc_item (GnomeCanvasGroup *group,
94 /****************************************************************************/
95 /* Boilerplate Object stuff. */
96 /****************************************************************************/
98 gl_wdgt_rotate_label_get_type (void)
100 static guint wdgt_rotate_label_type = 0;
102 if (!wdgt_rotate_label_type) {
103 GTypeInfo wdgt_rotate_label_info = {
104 sizeof (glWdgtRotateLabelClass),
107 (GClassInitFunc) gl_wdgt_rotate_label_class_init,
110 sizeof (glWdgtRotateLabel),
112 (GInstanceInitFunc) gl_wdgt_rotate_label_instance_init,
116 wdgt_rotate_label_type =
117 g_type_register_static (gl_hig_hbox_get_type (),
119 &wdgt_rotate_label_info, 0);
122 return wdgt_rotate_label_type;
126 gl_wdgt_rotate_label_class_init (glWdgtRotateLabelClass *class)
128 GObjectClass *object_class;
130 object_class = (GObjectClass *) class;
132 parent_class = g_type_class_peek_parent (class);
134 object_class->finalize = gl_wdgt_rotate_label_finalize;
136 wdgt_rotate_label_signals[CHANGED] =
137 g_signal_new ("changed",
138 G_OBJECT_CLASS_TYPE(object_class),
140 G_STRUCT_OFFSET (glWdgtRotateLabelClass, changed),
142 gl_marshal_VOID__VOID,
148 gl_wdgt_rotate_label_instance_init (glWdgtRotateLabel *rotate_select)
150 rotate_select->rotate_check = NULL;
152 rotate_select->canvas = NULL;
154 rotate_select->template = NULL;
158 gl_wdgt_rotate_label_finalize (GObject *object)
160 glWdgtRotateLabel *rotate_select;
161 glWdgtRotateLabelClass *class;
163 g_return_if_fail (object != NULL);
164 g_return_if_fail (GL_IS_WDGT_ROTATE_LABEL (object));
166 rotate_select = GL_WDGT_ROTATE_LABEL (object);
168 G_OBJECT_CLASS (parent_class)->finalize (object);
172 gl_wdgt_rotate_label_new (void)
174 glWdgtRotateLabel *rotate_select;
176 rotate_select = g_object_new (gl_wdgt_rotate_label_get_type (), NULL);
178 gl_wdgt_rotate_label_construct (rotate_select);
180 return GTK_WIDGET (rotate_select);
183 /*--------------------------------------------------------------------------*/
184 /* Construct composite widget. */
185 /*--------------------------------------------------------------------------*/
187 gl_wdgt_rotate_label_construct (glWdgtRotateLabel *rotate_select)
191 whbox = GTK_WIDGET (rotate_select);
193 /* Actual selection control */
194 rotate_select->rotate_check =
195 gtk_check_button_new_with_label (_("Rotate"));
196 gl_hig_hbox_add_widget (GL_HIG_HBOX(whbox),
197 rotate_select->rotate_check);
199 /* mini_preview canvas */
200 rotate_select->canvas = mini_preview_canvas_new ();
201 gl_hig_hbox_add_widget (GL_HIG_HBOX(whbox), rotate_select->canvas);
203 /* Connect signals to controls */
204 g_signal_connect (G_OBJECT (rotate_select->rotate_check), "toggled",
205 G_CALLBACK (entry_changed_cb), rotate_select);
208 /*--------------------------------------------------------------------------*/
209 /* PRIVATE. modify widget due to change of check button */
210 /*--------------------------------------------------------------------------*/
212 entry_changed_cb (GtkToggleButton *toggle,
215 glWdgtRotateLabel *rotate_select = GL_WDGT_ROTATE_LABEL (user_data);
217 if (rotate_select->template != NULL) {
218 /* Update mini_preview canvas & details with template */
219 mini_preview_canvas_update (GNOME_CANVAS
220 (rotate_select->canvas),
221 rotate_select->template,
222 gtk_toggle_button_get_active
226 /* Emit our "changed" signal */
227 g_signal_emit (G_OBJECT (user_data),
228 wdgt_rotate_label_signals[CHANGED], 0);
232 /*--------------------------------------------------------------------------*/
233 /* PRIVATE. Draw a mini-preview canvas. */
234 /*--------------------------------------------------------------------------*/
236 mini_preview_canvas_new (void)
238 GtkWidget *wcanvas = NULL;
240 /* Create a canvas */
241 gtk_widget_push_colormap (gdk_rgb_get_colormap ());
242 wcanvas = gnome_canvas_new_aa ();
243 gtk_widget_pop_colormap ();
245 gtk_widget_set_size_request (GTK_WIDGET (wcanvas),
246 MINI_PREVIEW_CANVAS_PIXELS,
247 MINI_PREVIEW_CANVAS_PIXELS);
249 gtk_object_set_data (GTK_OBJECT (wcanvas), "label_item", NULL);
254 /*--------------------------------------------------------------------------*/
255 /* PRIVATE. Update mini-preview canvas from new template. */
256 /*--------------------------------------------------------------------------*/
258 mini_preview_canvas_update (GnomeCanvas *canvas,
259 glTemplate *template,
260 gboolean rotate_flag)
262 gdouble canvas_scale;
263 GnomeCanvasGroup *group = NULL;
264 GnomeCanvasItem *label_item = NULL;
265 gdouble m, m_canvas, w, h;
266 guint line_color, fill_color;
268 /* Fetch our data from canvas */
269 label_item = g_object_get_data (G_OBJECT (canvas), "label_item");
271 gl_template_get_label_size (template, &w, &h);
273 canvas_scale = MINI_PREVIEW_MAX_PIXELS / m;
274 m_canvas = MINI_PREVIEW_CANVAS_PIXELS / canvas_scale;
276 /* scale and size canvas */
277 gnome_canvas_set_pixels_per_unit (GNOME_CANVAS (canvas), canvas_scale);
278 group = gnome_canvas_root (GNOME_CANVAS (canvas));
279 gnome_canvas_set_scroll_region (GNOME_CANVAS (canvas),
280 -m_canvas / 2.0, -m_canvas / 2.0,
281 +m_canvas / 2.0, +m_canvas / 2.0);
283 /* remove old label outline */
284 if (label_item != NULL) {
285 gtk_object_destroy (GTK_OBJECT (label_item));
288 /* Adjust sensitivity (should the canvas be grayed?) */
290 line_color = LINE_COLOR;
291 fill_color = FILL_COLOR;
293 line_color = UNSENSITIVE_LINE_COLOR;
294 fill_color = UNSENSITIVE_FILL_COLOR;
297 /* draw mini label outline */
298 switch (template->label.style) {
299 case GL_TEMPLATE_STYLE_RECT:
300 label_item = gnome_canvas_item_new (group,
301 gnome_canvas_rect_get_type(),
307 "outline_color_rgba", line_color,
308 "fill_color_rgba", fill_color,
311 case GL_TEMPLATE_STYLE_ROUND:
312 label_item = gnome_canvas_item_new (group,
313 gnome_canvas_ellipse_get_type(),
319 "outline_color_rgba", line_color,
320 "fill_color_rgba", fill_color,
323 case GL_TEMPLATE_STYLE_CD:
325 label_item = gnome_canvas_item_new (group,
326 gnome_canvas_ellipse_get_type(),
332 "outline_color_rgba", line_color,
333 "fill_color_rgba", fill_color,
336 label_item = cdbc_item (group,
337 w, h, template->label.cd.r1,
338 1, line_color, fill_color);
342 g_warning ("Unknown label style");
349 art_affine_rotate (affine, 90);
350 gnome_canvas_item_affine_absolute (label_item, affine);
353 gtk_object_set_data (GTK_OBJECT (canvas), "label_item", label_item);
357 /****************************************************************************/
358 /* query state of widget. */
359 /****************************************************************************/
361 gl_wdgt_rotate_label_get_state (glWdgtRotateLabel *rotate_select)
364 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
365 (rotate_select->rotate_check));
368 /****************************************************************************/
369 /* set state of widget. */
370 /****************************************************************************/
372 gl_wdgt_rotate_label_set_state (glWdgtRotateLabel *rotate_select,
375 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
376 (rotate_select->rotate_check), state);
379 /****************************************************************************/
380 /* set template for widget. */
381 /****************************************************************************/
383 gl_wdgt_rotate_label_set_template_name (glWdgtRotateLabel *rotate_select,
386 glTemplate *template;
387 gdouble raw_w, raw_h;
389 template = gl_template_from_name (name);
390 rotate_select->template = template;
391 gl_template_get_label_size (template, &raw_w, &raw_h);
393 gtk_widget_set_sensitive (rotate_select->rotate_check,
396 mini_preview_canvas_update (GNOME_CANVAS (rotate_select->canvas),
398 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
399 (rotate_select->rotate_check), FALSE);
402 /*--------------------------------------------------------------------------*/
403 /* PRIVATE. Draw CD business card item (cut-off in w and/or h). */
404 /*--------------------------------------------------------------------------*/
405 static GnomeCanvasItem *
406 cdbc_item (GnomeCanvasGroup *group,
414 GnomeCanvasPoints *points;
415 gint i_coords, i_theta;
416 gdouble theta1, theta2;
417 GnomeCanvasItem *item;
419 theta1 = (180.0/G_PI) * acos (w / (2.0*r));
420 theta2 = (180.0/G_PI) * asin (h / (2.0*r));
422 points = gnome_canvas_points_new (360/RES + 1);
425 points->coords[i_coords++] = r * cos (theta1 * G_PI / 180.0);
426 points->coords[i_coords++] = r * sin (theta1 * G_PI / 180.0);
428 for ( i_theta = theta1 + RES; i_theta < theta2; i_theta +=RES ) {
429 points->coords[i_coords++] = r * cos (i_theta * G_PI / 180.0);
430 points->coords[i_coords++] = r * sin (i_theta * G_PI / 180.0);
433 points->coords[i_coords++] = r * cos (theta2 * G_PI / 180.0);
434 points->coords[i_coords++] = r * sin (theta2 * G_PI / 180.0);
437 if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
438 points->coords[i_coords++] = r * cos ((180-theta2) * G_PI / 180.0);
439 points->coords[i_coords++] = r * sin ((180-theta2) * G_PI / 180.0);
442 for ( i_theta = 180-theta2+RES; i_theta < (180-theta1); i_theta +=RES ) {
443 points->coords[i_coords++] = r * cos (i_theta * G_PI / 180.0);
444 points->coords[i_coords++] = r * sin (i_theta * G_PI / 180.0);
447 points->coords[i_coords++] = r * cos ((180-theta1) * G_PI / 180.0);
448 points->coords[i_coords++] = r * sin ((180-theta1) * G_PI / 180.0);
450 if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
451 points->coords[i_coords++] = r * cos ((180+theta1) * G_PI / 180.0);
452 points->coords[i_coords++] = r * sin ((180+theta1) * G_PI / 180.0);
455 for ( i_theta = 180+theta1+RES; i_theta < (180+theta2); i_theta +=RES ) {
456 points->coords[i_coords++] = r * cos (i_theta * G_PI / 180.0);
457 points->coords[i_coords++] = r * sin (i_theta * G_PI / 180.0);
460 points->coords[i_coords++] = r * cos ((180+theta2) * G_PI / 180.0);
461 points->coords[i_coords++] = r * sin ((180+theta2) * G_PI / 180.0);
463 if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
464 points->coords[i_coords++] = r * cos ((360-theta2) * G_PI / 180.0);
465 points->coords[i_coords++] = r * sin ((360-theta2) * G_PI / 180.0);
468 for ( i_theta = 360-theta2+RES; i_theta < (360-theta1); i_theta +=RES ) {
469 points->coords[i_coords++] = r * cos (i_theta * G_PI / 180.0);
470 points->coords[i_coords++] = r * sin (i_theta * G_PI / 180.0);
473 if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
474 points->coords[i_coords++] = r * cos ((360-theta1) * G_PI / 180.0);
475 points->coords[i_coords++] = r * sin ((360-theta1) * G_PI / 180.0);
478 points->num_points = i_coords / 2;
481 item = gnome_canvas_item_new (group,
482 gnome_canvas_polygon_get_type (),
484 "width_pixels", line_width,
485 "outline_color_rgba", line_color,
486 "fill_color_rgba", fill_color,
489 gnome_canvas_points_free (points);