]> git.sur5r.net Git - glabels/blob - glabels2/src/wdgt-mini-preview.c
Use theme colors for shadow and selections.
[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                                                 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                                                 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 (glWdgtMiniPreview *preview,
277                                      gchar             *name)
278 {
279         glTemplate *template;
280         gchar      *page_size;
281         gdouble     canvas_scale;
282         gdouble     w, h;
283         gdouble     shadow_x, shadow_y;
284
285         gl_debug (DEBUG_MINI_PREVIEW, "START");
286
287         /* Fetch template */
288         template = gl_template_from_name (name);
289
290         gl_debug (DEBUG_MINI_PREVIEW, "page_size = %s, page_width = %g, page_height = %g",
291                   template->page_size, template->page_width, template->page_height);
292
293         /* get paper size and set scale */
294         w = preview->width - 4 - 2*SHADOW_X_OFFSET;
295         h = preview->height - 4 - 2*SHADOW_Y_OFFSET;
296         if ( (w/template->page_width) > (h/template->page_height) ) {
297                 canvas_scale = h / template->page_height;
298         } else {
299                 canvas_scale = w / template->page_width;
300         }
301         gnome_canvas_set_pixels_per_unit (GNOME_CANVAS (preview->canvas),
302                                           canvas_scale);
303 #if 0
304         gnome_canvas_set_scroll_region (GNOME_CANVAS (preview->canvas),
305                                         0.0, 0.0,
306                                         template->page_width, template->page_height);
307 #else
308         gnome_canvas_set_scroll_region (GNOME_CANVAS (preview->canvas),
309                                         0.0, 0.0,
310                                         preview->width/canvas_scale,
311                                         preview->height/canvas_scale);
312 #endif
313
314         /* update shadow */
315         shadow_x = SHADOW_X_OFFSET/canvas_scale;
316         shadow_y = SHADOW_Y_OFFSET/canvas_scale;
317         gnome_canvas_item_set (preview->shadow_item,
318                                "x1", shadow_x,
319                                "y1", shadow_y,
320                                "x2", shadow_x + template->page_width,
321                                "y2", shadow_y + template->page_height,
322                                NULL);
323
324         /* update paper outline */
325         gnome_canvas_item_set (preview->paper_item,
326                                "x2", template->page_width,
327                                "y2", template->page_height,
328                                NULL);
329
330         /* update label items */
331         mini_outline_list_free (&preview->label_items);
332         preview->label_items =
333                 mini_outline_list_new (GNOME_CANVAS(preview->canvas),
334                                        template);
335
336         gl_template_free( &template );
337         
338         gl_debug (DEBUG_MINI_PREVIEW, "END");
339 }
340
341 /*--------------------------------------------------------------------------*/
342 /* PRIVATE.  Draw label outlines and return canvas item list.               */
343 /*--------------------------------------------------------------------------*/
344 static GList *
345 mini_outline_list_new (GnomeCanvas *canvas,
346                        glTemplate  *template)
347 {
348         GnomeCanvasGroup      *group = NULL;
349         GnomeCanvasItem       *item = NULL;
350         GList                 *list = NULL;
351         gint                   i, n_labels;
352         glTemplateOrigin      *origins;
353         gdouble                x1, y1, x2, y2, w, h;
354
355         gl_debug (DEBUG_MINI_PREVIEW, "START");
356
357         group = gnome_canvas_root (canvas);
358
359         /* draw mini label outlines */
360         n_labels = gl_template_get_n_labels (template);
361         origins  = gl_template_get_origins (template);
362         gl_template_get_label_size (template, &w, &h);
363         for ( i=0; i < n_labels; i++ ) {
364
365                 x1 = origins[i].x;
366                 y1 = origins[i].y;
367                 x2 = x1 + w;
368                 y2 = y1 + h;
369
370                 switch (template->label.style) {
371                 case GL_TEMPLATE_STYLE_RECT:
372                         item = gnome_canvas_item_new (group,
373                                                       gnome_canvas_rect_get_type(),
374                                                       "x1", x1,
375                                                       "y1", y1,
376                                                       "x2", x2,
377                                                       "y2", y2,
378                                                       "width_pixels", 1,
379                                                       "outline_color", "black",
380                                                       "fill_color", "white",
381                                                       NULL);
382                         break;
383                 case GL_TEMPLATE_STYLE_ROUND:
384                         item = gnome_canvas_item_new (group,
385                                                       gnome_canvas_ellipse_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_CD:
396                         if ( w == h ) {
397                                 item = gnome_canvas_item_new (group,
398                                                               gnome_canvas_ellipse_get_type(),
399                                                               "x1", x1,
400                                                               "y1", y1,
401                                                               "x2", x2,
402                                                               "y2", y2,
403                                                               "width_pixels", 1,
404                                                               "outline_color", "black",
405                                                               "fill_color", "white",
406                                                               NULL);
407                         } else {
408                                 item = cdbc_item (group, x1, y1, template);
409                         }
410                         break;
411                 default:
412                         g_warning ("Unknown label style");
413                         return list;
414                         break;
415                 }
416                 g_object_set_data (G_OBJECT (item), "i",
417                                    GINT_TO_POINTER (i+1));
418                 
419                 list = g_list_append (list, item);
420         }
421
422         gl_debug (DEBUG_MINI_PREVIEW, "END");
423         return list;
424 }
425
426 /*--------------------------------------------------------------------------*/
427 /* PRIVATE.  Draw label outlines and return canvas item list.               */
428 /*--------------------------------------------------------------------------*/
429 static void
430 mini_outline_list_free (GList ** list)
431 {
432         GnomeCanvasItem *item;
433         GList *p;
434
435         gl_debug (DEBUG_MINI_PREVIEW, "START");
436
437         if ( *list != NULL ) {
438
439                 for (p = *list; p != NULL; p = p->next) {
440                         item = GNOME_CANVAS_ITEM (p->data);
441                         gtk_object_destroy (GTK_OBJECT (item));
442                 }
443
444                 g_list_free (*list);
445                 *list = NULL;
446
447         }
448
449         gl_debug (DEBUG_MINI_PREVIEW, "END");
450 }
451
452 /*--------------------------------------------------------------------------*/
453 /* PRIVATE.  Canvas event handler, select first and last items.             */
454 /*--------------------------------------------------------------------------*/
455 static gint
456 canvas_event_cb (GnomeCanvas * canvas,
457                  GdkEvent * event,
458                  gpointer data)
459 {
460         glWdgtMiniPreview *preview = GL_WDGT_MINI_PREVIEW (data);
461         GnomeCanvasItem *item;
462         static gboolean dragging = FALSE;
463         static gint prev_i = 0, first, last;
464         gint i;
465         gdouble x, y;
466
467         gl_debug (DEBUG_MINI_PREVIEW, "START");
468
469         switch (event->type) {
470
471         case GDK_BUTTON_PRESS:
472                 gnome_canvas_window_to_world (canvas,
473                                               event->button.x, event->button.y,
474                                               &x, &y);
475                 switch (event->button.button) {
476                 case 1:
477                         /* Get item at cursor and make sure
478                            it's a label object ("i" is valid) */
479                         item = gnome_canvas_get_item_at (GNOME_CANVAS (canvas),
480                                                          x, y);
481                         if (item == NULL)
482                                 break;
483                         i = GPOINTER_TO_INT (g_object_get_data
484                                              (G_OBJECT (item), "i"));
485                         if (i == 0)
486                                 break;
487                         /* Go into dragging mode while remains pressed. */
488                         dragging = TRUE;
489                         gnome_canvas_item_grab (canvas->root,
490                                                 GDK_POINTER_MOTION_MASK |
491                                                 GDK_BUTTON_RELEASE_MASK |
492                                                 GDK_BUTTON_PRESS_MASK,
493                                                 NULL, event->button.time);
494                         g_signal_emit (G_OBJECT(preview),
495                                        wdgt_mini_preview_signals[CLICKED],
496                                        0, i);
497                         first = i;
498                         last = i;
499                         g_signal_emit (G_OBJECT(preview),
500                                        wdgt_mini_preview_signals[PRESSED],
501                                        0, first, last);
502                         prev_i = i;
503                         break;
504
505                 default:
506                         break;
507                 }
508                 break;
509
510         case GDK_BUTTON_RELEASE:
511                 gnome_canvas_window_to_world (canvas,
512                                               event->button.x, event->button.y,
513                                               &x, &y);
514                 switch (event->button.button) {
515                 case 1:
516                         /* Exit dragging mode */
517                         dragging = FALSE;
518                         gnome_canvas_item_ungrab (canvas->root, event->button.time);
519                         break;
520
521                 default:
522                         break;
523                 }
524                 break;
525
526         case GDK_MOTION_NOTIFY:
527                 gnome_canvas_window_to_world (canvas,
528                                               event->motion.x, event->motion.y,
529                                               &x, &y);
530                 if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
531                         /* Get item at cursor and
532                            make sure it's a label object ("i" is valid) */
533                         item = gnome_canvas_get_item_at (GNOME_CANVAS (canvas),
534                                                          x, y);
535                         if (item == NULL)
536                                 break;
537                         i = GPOINTER_TO_INT (g_object_get_data
538                                              (G_OBJECT (item), "i"));
539                         if (i == 0)
540                                 break;
541                         if (prev_i != i) {
542                                 /* Entered into a new item */
543                                 last = i;
544                                 g_signal_emit (G_OBJECT(preview),
545                                                wdgt_mini_preview_signals[PRESSED],
546                                                0,
547                                                MIN (first, last),
548                                                MAX (first, last));
549                                 prev_i = i;
550                         }
551                 }
552                 break;
553
554         default:
555                 break;
556         }
557
558         gl_debug (DEBUG_MINI_PREVIEW, "END");
559
560         return FALSE;
561 }
562
563 /****************************************************************************/
564 /* Highlight given label outlines.                                          */
565 /****************************************************************************/
566 void
567 gl_wdgt_mini_preview_highlight_range (glWdgtMiniPreview *preview,
568                                       gint               first_label,
569                                       gint               last_label)
570 {
571         GtkStyle         *style;
572         guint             select_color;
573         GnomeCanvasItem  *item = NULL;
574         GList            *p = NULL;
575         gint              i;
576
577         gl_debug (DEBUG_MINI_PREVIEW, "START");
578
579         style = gtk_widget_get_style (GTK_WIDGET(preview));
580         select_color = gl_color_from_gdk_color (&style->base[GTK_STATE_SELECTED]);
581         gl_debug (DEBUG_MINI_PREVIEW, "select color = 0x%08x", select_color);
582
583         for (p = preview->label_items, i = 1; p != NULL; i++, p = p->next) {
584
585                 item = GNOME_CANVAS_ITEM (p->data);
586
587                 if ((i >= first_label) && (i <= last_label)) {
588                         gnome_canvas_item_set (item,
589                                                "fill_color_rgba", select_color,
590                                                NULL);
591                 } else {
592                         gnome_canvas_item_set (item,
593                                                "fill_color", "white", NULL);
594                 }
595
596         }
597
598         preview->highlight_first = first_label;
599         preview->highlight_last =  last_label;
600
601         gl_debug (DEBUG_MINI_PREVIEW, "END");
602 }
603
604 /*--------------------------------------------------------------------------*/
605 /* PRIVATE.  Refresh colors, if style changed.                              */
606 /*--------------------------------------------------------------------------*/
607 static void
608 style_set_cb (GtkWidget        *widget,
609               GtkStyle         *previous_style,
610               gpointer          data)
611 {
612         glWdgtMiniPreview *preview = GL_WDGT_MINI_PREVIEW (widget);
613         GtkStyle         *style;
614         guint             shadow_color;
615
616         style = gtk_widget_get_style (GTK_WIDGET(preview));
617
618         shadow_color = gl_color_from_gdk_color (&style->bg[GTK_STATE_ACTIVE]);
619         gnome_canvas_item_set (preview->shadow_item,
620                                "fill_color_rgba", shadow_color,
621                                NULL);
622
623         gl_wdgt_mini_preview_highlight_range (preview,
624                                               preview->highlight_first,
625                                               preview->highlight_last);
626 }
627
628 /*--------------------------------------------------------------------------*/
629 /* PRIVATE.  Draw CD business card item (cut-off in w and/or h).            */
630 /*--------------------------------------------------------------------------*/
631 static GnomeCanvasItem *
632 cdbc_item (GnomeCanvasGroup *group,
633            gdouble           x1,
634            gdouble           y1,
635            glTemplate       *template)
636 {
637         GnomeCanvasPoints *points;
638         gint               i_coords, i_theta;
639         gdouble            theta1, theta2;
640         gdouble            x0, y0, w, h, r;
641         GnomeCanvasItem   *item;
642
643         gl_template_get_label_size (template, &w, &h);
644         r = template->label.cd.r1;
645         x0 = x1 + (w/2.0);
646         y0 = y1 + (h/2.0);
647
648         theta1 = (180.0/G_PI) * acos (w / (2.0*r));
649         theta2 = (180.0/G_PI) * asin (h / (2.0*r));
650
651         points = gnome_canvas_points_new (360/RES + 1);
652         i_coords = 0;
653
654         points->coords[i_coords++] = x0 + r * cos (theta1 * G_PI / 180.0);
655         points->coords[i_coords++] = y0 + r * sin (theta1 * G_PI / 180.0);
656
657         for ( i_theta = theta1 + RES; i_theta < theta2; i_theta +=RES ) {
658                 points->coords[i_coords++] = x0 + r * cos (i_theta * G_PI / 180.0);
659                 points->coords[i_coords++] = y0 + r * sin (i_theta * G_PI / 180.0);
660         }
661
662         points->coords[i_coords++] = x0 + r * cos (theta2 * G_PI / 180.0);
663         points->coords[i_coords++] = y0 + r * sin (theta2 * G_PI / 180.0);
664
665
666         if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
667                 points->coords[i_coords++] = x0 + r * cos ((180-theta2) * G_PI / 180.0);
668                 points->coords[i_coords++] = y0 + r * sin ((180-theta2) * G_PI / 180.0);
669         }
670
671         for ( i_theta = 180-theta2+RES; i_theta < (180-theta1); i_theta +=RES ) {
672                 points->coords[i_coords++] = x0 + r * cos (i_theta * G_PI / 180.0);
673                 points->coords[i_coords++] = y0 + r * sin (i_theta * G_PI / 180.0);
674         }
675
676         points->coords[i_coords++] = x0 + r * cos ((180-theta1) * G_PI / 180.0);
677         points->coords[i_coords++] = y0 + r * sin ((180-theta1) * G_PI / 180.0);
678
679         if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
680                 points->coords[i_coords++] = x0 + r * cos ((180+theta1) * G_PI / 180.0);
681                 points->coords[i_coords++] = y0 + r * sin ((180+theta1) * G_PI / 180.0);
682         }
683
684         for ( i_theta = 180+theta1+RES; i_theta < (180+theta2); i_theta +=RES ) {
685                 points->coords[i_coords++] = x0 + r * cos (i_theta * G_PI / 180.0);
686                 points->coords[i_coords++] = y0 + r * sin (i_theta * G_PI / 180.0);
687         }
688
689         points->coords[i_coords++] = x0 + r * cos ((180+theta2) * G_PI / 180.0);
690         points->coords[i_coords++] = y0 + r * sin ((180+theta2) * G_PI / 180.0);
691
692         if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
693                 points->coords[i_coords++] = x0 + r * cos ((360-theta2) * G_PI / 180.0);
694                 points->coords[i_coords++] = y0 + r * sin ((360-theta2) * G_PI / 180.0);
695         }
696
697         for ( i_theta = 360-theta2+RES; i_theta < (360-theta1); i_theta +=RES ) {
698                 points->coords[i_coords++] = x0 + r * cos (i_theta * G_PI / 180.0);
699                 points->coords[i_coords++] = y0 + r * sin (i_theta * G_PI / 180.0);
700         }
701
702         if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
703                 points->coords[i_coords++] = x0 + r * cos ((360-theta1) * G_PI / 180.0);
704                 points->coords[i_coords++] = y0 + r * sin ((360-theta1) * G_PI / 180.0);
705         }
706
707         points->num_points = i_coords / 2;
708
709
710         item = gnome_canvas_item_new (group,
711                                       gnome_canvas_polygon_get_type (),
712                                       "points", points,
713                                       "width_pixels", 1,
714                                       "outline_color", "black",
715                                       "fill_color", "white",
716                                       NULL);
717
718         gnome_canvas_points_free (points);
719
720         return item;
721 }
722