]> git.cworth.org Git - wordgame/blob - demo-item.c
Fix randomizing of letter positions to never end up on top of each other
[wordgame] / demo-item.c
1 /*
2  * GooCanvas Demo. Copyright (C) 2006 Damon Chaplin.
3  * Released under the GNU LGPL license. See COPYING for details.
4  *
5  * demo-item.c - a simple demo item.
6  */
7 #include <math.h>
8
9 #include "goocanvas.h"
10 #include "demo-item.h"
11
12 /* Use the GLib convenience macro to define the type. GooDemoItem is the
13    class struct, goo_demo_item is the function prefix, and our class is a
14    subclass of GOO_TYPE_CANVAS_ITEM_SIMPLE. */
15 G_DEFINE_TYPE (GooDemoItem, goo_demo_item, GOO_TYPE_CANVAS_ITEM_SIMPLE)
16
17 /* The standard object initialization function. */
18     static void
19 goo_demo_item_init (GooDemoItem *demo_item)
20 {
21     demo_item->size = 0.0;
22 }
23
24 void
25 goo_demo_item_move_to (GooCanvasItem    *item,
26                        gdouble           x,
27                        gdouble           y)
28 {
29     cairo_matrix_t matrix;
30
31     cairo_matrix_init_translate (&matrix, x, y);
32     goo_canvas_item_set_transform (item, &matrix);
33 }
34
35 /* The convenience function to create new items. This should start with a 
36    parent argument and end with a variable list of object properties to fit
37    in with the standard canvas items. */
38 GooCanvasItem*
39 goo_demo_item_new (GooCanvasItem      *parent,
40                    gdouble             x,
41                    gdouble             y,
42                    gdouble             size,
43                    char                letter,
44                    ...)
45 {
46     GooCanvasItem *item;
47     GooDemoItem *demo_item;
48     const char *first_property;
49     va_list var_args;
50
51     item = g_object_new (GOO_TYPE_DEMO_ITEM, NULL);
52
53     demo_item = (GooDemoItem*) item;
54     demo_item->size = size;
55     demo_item->letter = letter;
56
57     va_start (var_args, letter);
58     first_property = va_arg (var_args, char*);
59     if (first_property)
60         g_object_set_valist ((GObject*) item, first_property, var_args);
61     va_end (var_args);
62
63     if (parent)
64     {
65         goo_canvas_item_add_child (parent, item, -1);
66         g_object_unref (item);
67     }
68
69     goo_demo_item_move_to (item, x, y);
70
71     return item;
72 }
73
74 /* The update method. This is called when the canvas is initially shown and
75    also whenever the object is updated and needs to change its size and/or
76    shape. It should calculate its new bounds, storing them in simple->bounds,
77    and it should convert these to device coordinates. */
78 static void
79 goo_demo_item_update  (GooCanvasItemSimple *simple,
80                        cairo_t             *cr)
81 {
82     GooDemoItem *demo_item = (GooDemoItem*) simple;
83
84     /* Compute the new bounds. */
85     simple->bounds.x1 = 0;
86     simple->bounds.y1 = 0;
87     simple->bounds.x2 = demo_item->size;
88     simple->bounds.y2 = demo_item->size;
89
90     /* Convert to device coordinates. */
91     goo_canvas_item_simple_user_bounds_to_device (simple, cr, &simple->bounds);
92 }
93
94 /* The paint method. This should draw the item on the given cairo_t, using
95    the item's own coordinate space. */
96 static void
97 goo_demo_item_paint (GooCanvasItemSimple *simple,
98                      cairo_t             *cr,
99                      GooCanvasBounds     *bounds)
100 {
101     GooDemoItem *item = (GooDemoItem*) simple;
102     cairo_pattern_t *gradient;
103     cairo_text_extents_t extents;
104     int rad = (int) (item->size / 2);
105     int cx = item->size / 2;
106     int cy = cx;
107     double spot_angle = M_PI / 4.0;
108     double spot_rad = rad / 2.0;
109     char string[2];
110
111     cairo_save (cr);
112
113     gradient = cairo_pattern_create_radial (cx - spot_rad * cos (spot_angle),
114                                             cy - spot_rad * sin (spot_angle),
115                                             0.0,
116                                             cx - spot_rad * cos (spot_angle),
117                                             cy - spot_rad * sin (spot_angle),
118                                             rad + spot_rad);
119     cairo_pattern_add_color_stop_rgb (gradient, 0.0, 1.0, 1.0, 1.0);
120     cairo_pattern_add_color_stop_rgb (gradient, 1.0, 0.33, 0.33, 0.33);
121
122     cairo_set_source (cr, gradient);
123
124     cairo_arc (cr,
125                cx, cy,
126                rad, 0, 2 * M_PI);
127
128     cairo_fill (cr);
129
130     cairo_select_font_face (cr, "mono",
131                             CAIRO_FONT_SLANT_NORMAL,
132                             CAIRO_FONT_WEIGHT_BOLD);
133     cairo_set_font_size (cr, 1.8 * rad);
134
135     string[0] = item->letter;
136     string[1] = '\0';
137     cairo_text_extents (cr, string, &extents);
138     cairo_move_to (cr,
139                    cx - extents.width / 2 - extents.x_bearing,
140                    cy - extents.height / 2 - extents.y_bearing);
141
142     cairo_set_source_rgb (cr, 0.2, 0.3, 0.8);
143     cairo_show_text (cr, string);
144
145     cairo_restore (cr);
146 }
147
148 /* Hit detection. This should check if the given coordinate (in the item's
149    coordinate space) is within the item. If it is it should return the item,
150    otherwise it should return NULL. */
151 static GooCanvasItem*
152 goo_demo_item_get_item_at (GooCanvasItemSimple *simple,
153                            gdouble              x,
154                            gdouble              y,
155                            cairo_t             *cr,
156                            gboolean             is_pointer_event)
157 {
158     GooDemoItem *demo_item = (GooDemoItem*) simple;
159
160     if (x < 0 || (x > demo_item->size)
161         || y < 0 || (y > demo_item->size))
162         return NULL;
163
164     return (GooCanvasItem*) simple;
165 }
166
167 /* The class initialization function. Here we set the class' update(), paint()
168    and get_item_at() methods. */
169 static void
170 goo_demo_item_class_init (GooDemoItemClass *klass)
171 {
172     GooCanvasItemSimpleClass *simple_class = (GooCanvasItemSimpleClass*) klass;
173
174     simple_class->update        = goo_demo_item_update;
175     simple_class->paint         = goo_demo_item_paint;
176     simple_class->get_item_at   = goo_demo_item_get_item_at;
177 }