]> git.sur5r.net Git - glabels/blob - glabels2/src/wdgt-mini-preview.c
2003-12-30 Jim Evins <evins@snaught.com>
[glabels] / glabels2 / src / wdgt-mini-preview.c
1 /*
2  *  (GLABELS) Label and Business Card Creation program for GNOME
3  *
4  *  wdgt_mini_preview.c:  mini preview widget module
5  *
6  *  Copyright (C) 2001  Jim Evins <evins@snaught.com>.
7  *
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.
12  *
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.
17  *
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
21  */
22
23 #include <config.h>
24
25 #include <math.h>
26
27 #include "wdgt-mini-preview.h"
28 #include "marshal.h"
29 #include "color.h"
30
31 #include "debug.h"
32
33 #define WDGT_MINI_PREVIEW_MAX_PIXELS 175
34 #define SHADOW_X_OFFSET 5
35 #define SHADOW_Y_OFFSET 5
36
37 #define RES 5 /* Resolution in degrees for Business Card CD outlines */
38
39 /*===========================================*/
40 /* Private types                             */
41 /*===========================================*/
42
43 enum {
44         CLICKED,
45         PRESSED,
46         LAST_SIGNAL
47 };
48
49
50 /*===========================================*/
51 /* Private globals                           */
52 /*===========================================*/
53
54 static GtkContainerClass *parent_class;
55
56 static gint wdgt_mini_preview_signals[LAST_SIGNAL] = { 0 };
57
58 /*===========================================*/
59 /* Local function prototypes                 */
60 /*===========================================*/
61
62 static void gl_wdgt_mini_preview_class_init    (glWdgtMiniPreviewClass * class);
63 static void gl_wdgt_mini_preview_instance_init (glWdgtMiniPreview * preview);
64 static void gl_wdgt_mini_preview_finalize      (GObject * object);
65
66 static void gl_wdgt_mini_preview_construct     (glWdgtMiniPreview * preview,
67                                                 gint height, gint width);
68
69 static GList *mini_outline_list_new            (GnomeCanvas      *canvas,
70                                                 const glTemplate *template);
71 static void mini_outline_list_free             (GList ** list);
72
73 static gint canvas_event_cb                    (GnomeCanvas * canvas,
74                                                 GdkEvent * event,
75                                                 gpointer data);
76
77 static GnomeCanvasItem *cdbc_item              (GnomeCanvasGroup *group,
78                                                 gdouble           x1,
79                                                 gdouble           y1,
80                                                 const glTemplate *template);
81
82 static void style_set_cb                       (GtkWidget        *widget,
83                                                 GtkStyle         *previous_style,
84                                                 gpointer data);
85
86
87
88 \f
89 /****************************************************************************/
90 /* Boilerplate Object stuff.                                                */
91 /****************************************************************************/
92 guint
93 gl_wdgt_mini_preview_get_type (void)
94 {
95         static guint wdgt_mini_preview_type = 0;
96
97         if (!wdgt_mini_preview_type) {
98                 GTypeInfo wdgt_mini_preview_info = {
99                         sizeof (glWdgtMiniPreviewClass),
100                         NULL,
101                         NULL,
102                         (GClassInitFunc) gl_wdgt_mini_preview_class_init,
103                         NULL,
104                         NULL,
105                         sizeof (glWdgtMiniPreview),
106                         0,
107                         (GInstanceInitFunc) gl_wdgt_mini_preview_instance_init,
108                 };
109
110                 wdgt_mini_preview_type =
111                         g_type_register_static (gtk_hbox_get_type (),
112                                                 "glWdgtMiniPreview",
113                                                 &wdgt_mini_preview_info, 0);
114         }
115
116         return wdgt_mini_preview_type;
117 }
118
119 static void
120 gl_wdgt_mini_preview_class_init (glWdgtMiniPreviewClass * class)
121 {
122         GObjectClass *object_class;
123
124         gl_debug (DEBUG_MINI_PREVIEW, "START");
125
126         object_class = (GObjectClass *) class;
127
128         parent_class = gtk_type_class (gtk_hbox_get_type ());
129
130         object_class->finalize = gl_wdgt_mini_preview_finalize;
131
132         wdgt_mini_preview_signals[CLICKED] =
133             g_signal_new ("clicked",
134                           G_OBJECT_CLASS_TYPE(object_class),
135                           G_SIGNAL_RUN_LAST,
136                           G_STRUCT_OFFSET (glWdgtMiniPreviewClass, clicked),
137                           NULL, NULL,
138                           gl_marshal_VOID__INT,
139                           G_TYPE_NONE, 1, G_TYPE_INT);
140
141         wdgt_mini_preview_signals[PRESSED] =
142             g_signal_new ("pressed",
143                           G_OBJECT_CLASS_TYPE(object_class),
144                           G_SIGNAL_RUN_LAST,
145                           G_STRUCT_OFFSET (glWdgtMiniPreviewClass, pressed),
146                           NULL, NULL,
147                           gl_marshal_VOID__INT_INT,
148                           G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
149
150         gl_debug (DEBUG_MINI_PREVIEW, "END");
151 }
152
153 static void
154 gl_wdgt_mini_preview_instance_init (glWdgtMiniPreview * preview)
155 {
156         gl_debug (DEBUG_MINI_PREVIEW, "START");
157
158         preview->canvas = NULL;
159         preview->label_items = NULL;
160
161         gl_debug (DEBUG_MINI_PREVIEW, "END");
162 }
163
164 static void
165 gl_wdgt_mini_preview_finalize (GObject * object)
166 {
167         glWdgtMiniPreview *preview;
168         glWdgtMiniPreviewClass *class;
169
170         gl_debug (DEBUG_MINI_PREVIEW, "START");
171
172         g_return_if_fail (object != NULL);
173         g_return_if_fail (GL_IS_WDGT_MINI_PREVIEW (object));
174
175         preview = GL_WDGT_MINI_PREVIEW (object);
176
177         G_OBJECT_CLASS (parent_class)->finalize (object);
178
179         gl_debug (DEBUG_MINI_PREVIEW, "END");
180 }
181
182 GtkWidget *
183 gl_wdgt_mini_preview_new (gint height,
184                           gint width)
185 {
186         glWdgtMiniPreview *preview;
187
188         gl_debug (DEBUG_MINI_PREVIEW, "START");
189
190         preview = g_object_new (gl_wdgt_mini_preview_get_type (), NULL);
191
192         gl_wdgt_mini_preview_construct (preview, height, width);
193
194         gl_debug (DEBUG_MINI_PREVIEW, "END");
195
196         return GTK_WIDGET (preview);
197 }
198
199 /*--------------------------------------------------------------------------*/
200 /* Construct composite widget.                                              */
201 /*--------------------------------------------------------------------------*/
202 static void
203 gl_wdgt_mini_preview_construct (glWdgtMiniPreview * preview,
204                                 gint height,
205                                 gint width)
206 {
207         GtkWidget        *whbox;
208         GnomeCanvasGroup *group;
209         GtkStyle         *style;
210         guint             shadow_color;
211
212         gl_debug (DEBUG_MINI_PREVIEW, "START");
213
214         whbox = GTK_WIDGET (preview);
215
216         preview->height = height;
217         preview->width  = width;
218
219         /* create canvas */
220         gtk_widget_push_colormap (gdk_rgb_get_colormap ());
221         preview->canvas = gnome_canvas_new_aa ();
222         gtk_widget_pop_colormap ();
223         gtk_box_pack_start (GTK_BOX (whbox), preview->canvas, TRUE, TRUE, 0);
224         gtk_widget_set_size_request (preview->canvas, width, height);
225         gnome_canvas_set_scroll_region (GNOME_CANVAS (preview->canvas),
226                                         0.0, 0.0, width, height);
227
228         gnome_canvas_set_pixels_per_unit (GNOME_CANVAS (preview->canvas), 1.0);
229         group = gnome_canvas_root (GNOME_CANVAS (preview->canvas));
230
231         /* draw shadow */
232         style = gtk_widget_get_style (GTK_WIDGET(preview));
233         shadow_color = gl_color_from_gdk_color (&style->bg[GTK_STATE_ACTIVE]);
234         preview->shadow_item =
235                 gnome_canvas_item_new (group,
236                                        gnome_canvas_rect_get_type (),
237                                        "x1", (gdouble)SHADOW_X_OFFSET,
238                                        "y1", (gdouble)SHADOW_Y_OFFSET,
239                                        "x2", (gdouble)(SHADOW_X_OFFSET + width),
240                                        "y2", (gdouble)(SHADOW_Y_OFFSET + height),
241                                        "fill_color_rgba", shadow_color,
242                                        NULL);
243
244         /* draw an initial paper outline */
245         preview->paper_item =
246                 gnome_canvas_item_new (group,
247                                        gnome_canvas_rect_get_type (),
248                                        "x1", 0.0,
249                                        "y1", 0.0,
250                                        "x2", (gdouble)width,
251                                        "y2", (gdouble)height,
252                                        "width_pixels", 1,
253                                        "outline_color", "black",
254                                        "fill_color", "white",
255                                        NULL);
256
257         /* create empty list of label canvas items */
258         preview->label_items = NULL;
259         preview->labels_per_sheet = 0;
260
261         /* Event handler */
262         g_signal_connect (G_OBJECT (preview->canvas), "event",
263                           G_CALLBACK (canvas_event_cb), preview);
264
265
266         /* Style changed handler */
267         g_signal_connect (G_OBJECT (preview), "style_set",
268                           G_CALLBACK (style_set_cb), NULL);
269
270         gl_debug (DEBUG_MINI_PREVIEW, "END");
271 }
272
273 /****************************************************************************/
274 /* Set label for mini-preview to determine geometry.                        */
275 /****************************************************************************/
276 void gl_wdgt_mini_preview_set_label_by_name (glWdgtMiniPreview *preview,
277                                              const gchar       *name)
278 {
279         glTemplate *template;
280
281         gl_debug (DEBUG_MINI_PREVIEW, "START");
282
283         /* Fetch template */
284         template = gl_template_from_name (name);
285
286         gl_wdgt_mini_preview_set_template (preview, template);
287
288         gl_template_free( &template );
289
290         gl_debug (DEBUG_MINI_PREVIEW, "END");
291 }
292
293 /****************************************************************************/
294 /* Set label for mini-preview to determine geometry.                        */
295 /****************************************************************************/
296 void gl_wdgt_mini_preview_set_template (glWdgtMiniPreview *preview,
297                                         const glTemplate  *template)
298 {
299         gchar      *page_size;
300         gdouble     canvas_scale;
301         gdouble     w, h;
302         gdouble     offset_x, offset_y;
303         gdouble     shadow_x, shadow_y;
304
305         gl_debug (DEBUG_MINI_PREVIEW, "START");
306
307         gl_debug (DEBUG_MINI_PREVIEW, "page_size = %s, page_width = %g, page_height = %g",
308                   template->page_size, template->page_width, template->page_height);
309
310         /* get paper size and set scale */
311         w = preview->width - 4 - 2*SHADOW_X_OFFSET;
312         h = preview->height - 4 - 2*SHADOW_Y_OFFSET;
313         if ( (w/template->page_width) > (h/template->page_height) ) {
314                 canvas_scale = h / template->page_height;
315         } else {
316                 canvas_scale = w / template->page_width;
317         }
318         gnome_canvas_set_pixels_per_unit (GNOME_CANVAS (preview->canvas),
319                                           canvas_scale);
320         offset_x = (preview->width/canvas_scale - template->page_width) / 2.0;
321         offset_y = (preview->height/canvas_scale - template->page_height) / 2.0;
322
323         gnome_canvas_set_scroll_region (GNOME_CANVAS (preview->canvas),
324                                         -offset_x, -offset_y,
325                                         preview->width/canvas_scale - offset_x,
326                                         preview->height/canvas_scale - offset_y);
327
328         /* update shadow */
329         shadow_x = SHADOW_X_OFFSET/canvas_scale;
330         shadow_y = SHADOW_Y_OFFSET/canvas_scale;
331         gnome_canvas_item_set (preview->shadow_item,
332                                "x1", shadow_x,
333                                "y1", shadow_y,
334                                "x2", shadow_x + template->page_width,
335                                "y2", shadow_y + template->page_height,
336                                NULL);
337
338         /* update paper outline */
339         gnome_canvas_item_set (preview->paper_item,
340                                "x2", template->page_width,
341                                "y2", template->page_height,
342                                NULL);
343
344         /* update label items */
345         mini_outline_list_free (&preview->label_items);
346         preview->label_items =
347                 mini_outline_list_new (GNOME_CANVAS(preview->canvas),
348                                        template);
349
350         gl_debug (DEBUG_MINI_PREVIEW, "END");
351 }
352
353 /*--------------------------------------------------------------------------*/
354 /* PRIVATE.  Draw label outlines and return canvas item list.               */
355 /*--------------------------------------------------------------------------*/
356 static GList *
357 mini_outline_list_new (GnomeCanvas       *canvas,
358                        const glTemplate  *template)
359 {
360         GnomeCanvasGroup      *group = NULL;
361         GnomeCanvasItem       *item = NULL;
362         GList                 *list = NULL;
363         gint                   i, n_labels;
364         glTemplateOrigin      *origins;
365         gdouble                x1, y1, x2, y2, w, h;
366
367         gl_debug (DEBUG_MINI_PREVIEW, "START");
368
369         group = gnome_canvas_root (canvas);
370
371         /* draw mini label outlines */
372         n_labels = gl_template_get_n_labels (template);
373         origins  = gl_template_get_origins (template);
374         gl_template_get_label_size (template, &w, &h);
375         for ( i=0; i < n_labels; i++ ) {
376
377                 x1 = origins[i].x;
378                 y1 = origins[i].y;
379                 x2 = x1 + w;
380                 y2 = y1 + h;
381
382                 switch (template->label.style) {
383                 case GL_TEMPLATE_STYLE_RECT:
384                         item = gnome_canvas_item_new (group,
385                                                       gnome_canvas_rect_get_type(),
386                                                       "x1", x1,
387                                                       "y1", y1,
388                                                       "x2", x2,
389                                                       "y2", y2,
390                                                       "width_pixels", 1,
391                                                       "outline_color", "black",
392                                                       "fill_color", "white",
393                                                       NULL);
394                         break;
395                 case GL_TEMPLATE_STYLE_ROUND:
396                         item = gnome_canvas_item_new (group,
397                                                       gnome_canvas_ellipse_get_type(),
398                                                       "x1", x1,
399                                                       "y1", y1,
400                                                       "x2", x2,
401                                                       "y2", y2,
402                                                       "width_pixels", 1,
403                                                       "outline_color", "black",
404                                                       "fill_color", "white",
405                                                       NULL);
406                         break;
407                 case GL_TEMPLATE_STYLE_CD:
408                         if ( w == h ) {
409                                 item = gnome_canvas_item_new (group,
410                                                               gnome_canvas_ellipse_get_type(),
411                                                               "x1", x1,
412                                                               "y1", y1,
413                                                               "x2", x2,
414                                                               "y2", y2,
415                                                               "width_pixels", 1,
416                                                               "outline_color", "black",
417                                                               "fill_color", "white",
418                                                               NULL);
419                         } else {
420                                 item = cdbc_item (group, x1, y1, template);
421                         }
422                         break;
423                 default:
424                         g_warning ("Unknown label style");
425                         return list;
426                         break;
427                 }
428                 g_object_set_data (G_OBJECT (item), "i",
429                                    GINT_TO_POINTER (i+1));
430                 
431                 list = g_list_append (list, item);
432         }
433
434         gl_debug (DEBUG_MINI_PREVIEW, "END");
435         return list;
436 }
437
438 /*--------------------------------------------------------------------------*/
439 /* PRIVATE.  Draw label outlines and return canvas item list.               */
440 /*--------------------------------------------------------------------------*/
441 static void
442 mini_outline_list_free (GList ** list)
443 {
444         GnomeCanvasItem *item;
445         GList *p;
446
447         gl_debug (DEBUG_MINI_PREVIEW, "START");
448
449         if ( *list != NULL ) {
450
451                 for (p = *list; p != NULL; p = p->next) {
452                         item = GNOME_CANVAS_ITEM (p->data);
453                         gtk_object_destroy (GTK_OBJECT (item));
454                 }
455
456                 g_list_free (*list);
457                 *list = NULL;
458
459         }
460
461         gl_debug (DEBUG_MINI_PREVIEW, "END");
462 }
463
464 /*--------------------------------------------------------------------------*/
465 /* PRIVATE.  Canvas event handler, select first and last items.             */
466 /*--------------------------------------------------------------------------*/
467 static gint
468 canvas_event_cb (GnomeCanvas * canvas,
469                  GdkEvent * event,
470                  gpointer data)
471 {
472         glWdgtMiniPreview *preview = GL_WDGT_MINI_PREVIEW (data);
473         GnomeCanvasItem *item;
474         static gboolean dragging = FALSE;
475         static gint prev_i = 0, first, last;
476         gint i;
477         gdouble x, y;
478
479         gl_debug (DEBUG_MINI_PREVIEW, "START");
480
481         switch (event->type) {
482
483         case GDK_BUTTON_PRESS:
484                 gnome_canvas_window_to_world (canvas,
485                                               event->button.x, event->button.y,
486                                               &x, &y);
487                 switch (event->button.button) {
488                 case 1:
489                         /* Get item at cursor and make sure
490                            it's a label object ("i" is valid) */
491                         item = gnome_canvas_get_item_at (GNOME_CANVAS (canvas),
492                                                          x, y);
493                         if (item == NULL)
494                                 break;
495                         i = GPOINTER_TO_INT (g_object_get_data
496                                              (G_OBJECT (item), "i"));
497                         if (i == 0)
498                                 break;
499                         /* Go into dragging mode while remains pressed. */
500                         dragging = TRUE;
501                         gnome_canvas_item_grab (canvas->root,
502                                                 GDK_POINTER_MOTION_MASK |
503                                                 GDK_BUTTON_RELEASE_MASK |
504                                                 GDK_BUTTON_PRESS_MASK,
505                                                 NULL, event->button.time);
506                         g_signal_emit (G_OBJECT(preview),
507                                        wdgt_mini_preview_signals[CLICKED],
508                                        0, i);
509                         first = i;
510                         last = i;
511                         g_signal_emit (G_OBJECT(preview),
512                                        wdgt_mini_preview_signals[PRESSED],
513                                        0, first, last);
514                         prev_i = i;
515                         break;
516
517                 default:
518                         break;
519                 }
520                 break;
521
522         case GDK_BUTTON_RELEASE:
523                 gnome_canvas_window_to_world (canvas,
524                                               event->button.x, event->button.y,
525                                               &x, &y);
526                 switch (event->button.button) {
527                 case 1:
528                         /* Exit dragging mode */
529                         dragging = FALSE;
530                         gnome_canvas_item_ungrab (canvas->root, event->button.time);
531                         break;
532
533                 default:
534                         break;
535                 }
536                 break;
537
538         case GDK_MOTION_NOTIFY:
539                 gnome_canvas_window_to_world (canvas,
540                                               event->motion.x, event->motion.y,
541                                               &x, &y);
542                 if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
543                         /* Get item at cursor and
544                            make sure it's a label object ("i" is valid) */
545                         item = gnome_canvas_get_item_at (GNOME_CANVAS (canvas),
546                                                          x, y);
547                         if (item == NULL)
548                                 break;
549                         i = GPOINTER_TO_INT (g_object_get_data
550                                              (G_OBJECT (item), "i"));
551                         if (i == 0)
552                                 break;
553                         if (prev_i != i) {
554                                 /* Entered into a new item */
555                                 last = i;
556                                 g_signal_emit (G_OBJECT(preview),
557                                                wdgt_mini_preview_signals[PRESSED],
558                                                0,
559                                                MIN (first, last),
560                                                MAX (first, last));
561                                 prev_i = i;
562                         }
563                 }
564                 break;
565
566         default:
567                 break;
568         }
569
570         gl_debug (DEBUG_MINI_PREVIEW, "END");
571
572         return FALSE;
573 }
574
575 /****************************************************************************/
576 /* Highlight given label outlines.                                          */
577 /****************************************************************************/
578 void
579 gl_wdgt_mini_preview_highlight_range (glWdgtMiniPreview *preview,
580                                       gint               first_label,
581                                       gint               last_label)
582 {
583         GtkStyle         *style;
584         guint             select_color;
585         GnomeCanvasItem  *item = NULL;
586         GList            *p = NULL;
587         gint              i;
588
589         gl_debug (DEBUG_MINI_PREVIEW, "START");
590
591         style = gtk_widget_get_style (GTK_WIDGET(preview));
592         select_color = gl_color_from_gdk_color (&style->base[GTK_STATE_SELECTED]);
593         gl_debug (DEBUG_MINI_PREVIEW, "select color = 0x%08x", select_color);
594
595         for (p = preview->label_items, i = 1; p != NULL; i++, p = p->next) {
596
597                 item = GNOME_CANVAS_ITEM (p->data);
598
599                 if ((i >= first_label) && (i <= last_label)) {
600                         gnome_canvas_item_set (item,
601                                                "fill_color_rgba", select_color,
602                                                NULL);
603                 } else {
604                         gnome_canvas_item_set (item,
605                                                "fill_color", "white", NULL);
606                 }
607
608         }
609
610         preview->highlight_first = first_label;
611         preview->highlight_last =  last_label;
612
613         gl_debug (DEBUG_MINI_PREVIEW, "END");
614 }
615
616 /*--------------------------------------------------------------------------*/
617 /* PRIVATE.  Refresh colors, if style changed.                              */
618 /*--------------------------------------------------------------------------*/
619 static void
620 style_set_cb (GtkWidget        *widget,
621               GtkStyle         *previous_style,
622               gpointer          data)
623 {
624         glWdgtMiniPreview *preview = GL_WDGT_MINI_PREVIEW (widget);
625         GtkStyle         *style;
626         guint             shadow_color;
627
628         style = gtk_widget_get_style (GTK_WIDGET(preview));
629
630         shadow_color = gl_color_from_gdk_color (&style->bg[GTK_STATE_ACTIVE]);
631         gnome_canvas_item_set (preview->shadow_item,
632                                "fill_color_rgba", shadow_color,
633                                NULL);
634
635         gl_wdgt_mini_preview_highlight_range (preview,
636                                               preview->highlight_first,
637                                               preview->highlight_last);
638 }
639
640 /*--------------------------------------------------------------------------*/
641 /* PRIVATE.  Draw CD business card item (cut-off in w and/or h).            */
642 /*--------------------------------------------------------------------------*/
643 static GnomeCanvasItem *
644 cdbc_item (GnomeCanvasGroup *group,
645            gdouble           x1,
646            gdouble           y1,
647            const glTemplate *template)
648 {
649         GnomeCanvasPoints *points;
650         gint               i_coords, i_theta;
651         gdouble            theta1, theta2;
652         gdouble            x0, y0, w, h, r;
653         GnomeCanvasItem   *item;
654
655         gl_template_get_label_size (template, &w, &h);
656         r = template->label.cd.r1;
657         x0 = x1 + (w/2.0);
658         y0 = y1 + (h/2.0);
659
660         theta1 = (180.0/G_PI) * acos (w / (2.0*r));
661         theta2 = (180.0/G_PI) * asin (h / (2.0*r));
662
663         points = gnome_canvas_points_new (360/RES + 1);
664         i_coords = 0;
665
666         points->coords[i_coords++] = x0 + r * cos (theta1 * G_PI / 180.0);
667         points->coords[i_coords++] = y0 + r * sin (theta1 * G_PI / 180.0);
668
669         for ( i_theta = theta1 + RES; i_theta < theta2; i_theta +=RES ) {
670                 points->coords[i_coords++] = x0 + r * cos (i_theta * G_PI / 180.0);
671                 points->coords[i_coords++] = y0 + r * sin (i_theta * G_PI / 180.0);
672         }
673
674         points->coords[i_coords++] = x0 + r * cos (theta2 * G_PI / 180.0);
675         points->coords[i_coords++] = y0 + r * sin (theta2 * G_PI / 180.0);
676
677
678         if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
679                 points->coords[i_coords++] = x0 + r * cos ((180-theta2) * G_PI / 180.0);
680                 points->coords[i_coords++] = y0 + r * sin ((180-theta2) * G_PI / 180.0);
681         }
682
683         for ( i_theta = 180-theta2+RES; i_theta < (180-theta1); i_theta +=RES ) {
684                 points->coords[i_coords++] = x0 + r * cos (i_theta * G_PI / 180.0);
685                 points->coords[i_coords++] = y0 + r * sin (i_theta * G_PI / 180.0);
686         }
687
688         points->coords[i_coords++] = x0 + r * cos ((180-theta1) * G_PI / 180.0);
689         points->coords[i_coords++] = y0 + r * sin ((180-theta1) * G_PI / 180.0);
690
691         if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
692                 points->coords[i_coords++] = x0 + r * cos ((180+theta1) * G_PI / 180.0);
693                 points->coords[i_coords++] = y0 + r * sin ((180+theta1) * G_PI / 180.0);
694         }
695
696         for ( i_theta = 180+theta1+RES; i_theta < (180+theta2); i_theta +=RES ) {
697                 points->coords[i_coords++] = x0 + r * cos (i_theta * G_PI / 180.0);
698                 points->coords[i_coords++] = y0 + r * sin (i_theta * G_PI / 180.0);
699         }
700
701         points->coords[i_coords++] = x0 + r * cos ((180+theta2) * G_PI / 180.0);
702         points->coords[i_coords++] = y0 + r * sin ((180+theta2) * G_PI / 180.0);
703
704         if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
705                 points->coords[i_coords++] = x0 + r * cos ((360-theta2) * G_PI / 180.0);
706                 points->coords[i_coords++] = y0 + r * sin ((360-theta2) * G_PI / 180.0);
707         }
708
709         for ( i_theta = 360-theta2+RES; i_theta < (360-theta1); i_theta +=RES ) {
710                 points->coords[i_coords++] = x0 + r * cos (i_theta * G_PI / 180.0);
711                 points->coords[i_coords++] = y0 + r * sin (i_theta * G_PI / 180.0);
712         }
713
714         if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
715                 points->coords[i_coords++] = x0 + r * cos ((360-theta1) * G_PI / 180.0);
716                 points->coords[i_coords++] = y0 + r * sin ((360-theta1) * G_PI / 180.0);
717         }
718
719         points->num_points = i_coords / 2;
720
721
722         item = gnome_canvas_item_new (group,
723                                       gnome_canvas_polygon_get_type (),
724                                       "points", points,
725                                       "width_pixels", 1,
726                                       "outline_color", "black",
727                                       "fill_color", "white",
728                                       NULL);
729
730         gnome_canvas_points_free (points);
731
732         return item;
733 }
734
735 /****************************************************************************/
736 /* Change/set background color of preview.                                  */
737 /****************************************************************************/
738 void
739 gl_wdgt_mini_preview_set_bg_color (glWdgtMiniPreview *preview,
740                                    guint              color)
741 {
742         GdkColor *gdk_color;
743
744         gdk_color = gl_color_to_gdk_color (color);
745         gtk_widget_modify_bg (GTK_WIDGET(preview->canvas), GTK_STATE_NORMAL, gdk_color);
746         g_free (gdk_color);
747 }
748