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