[AdgStroke] Placeholder for arrange() virtual method
[adg.git] / adg / adg-stroke.c
blob5100863f784565261f9ab1e171205186fe84219c
1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007,2008,2009 Nicola Fontana <ntd at entidi.it>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
21 /**
22 * SECTION:adg-stroke
23 * @short_description: A stroked entity
25 * The #AdgStroke object is a stroked representation of an #AdgTrail model.
26 **/
28 /**
29 * AdgStroke:
31 * All fields are private and should not be used directly.
32 * Use its public methods instead.
33 **/
36 #include "adg-stroke.h"
37 #include "adg-stroke-private.h"
38 #include "adg-line-style.h"
39 #include "adg-intl.h"
41 #define PARENT_OBJECT_CLASS ((GObjectClass *) adg_stroke_parent_class)
44 enum {
45 PROP_0,
46 PROP_DRESS,
47 PROP_TRAIL
50 static void dispose (GObject *object);
51 static void get_property (GObject *object,
52 guint param_id,
53 GValue *value,
54 GParamSpec *pspec);
55 static void set_property (GObject *object,
56 guint param_id,
57 const GValue *value,
58 GParamSpec *pspec);
59 static void arrange (AdgEntity *entity);
60 static void render (AdgEntity *entity,
61 cairo_t *cr);
62 static gboolean set_trail (AdgStroke *stroke,
63 AdgTrail *trail);
64 static void unset_trail (AdgStroke *stroke);
67 G_DEFINE_TYPE(AdgStroke, adg_stroke, ADG_TYPE_ENTITY);
70 static void
71 adg_stroke_class_init(AdgStrokeClass *klass)
73 GObjectClass *gobject_class;
74 AdgEntityClass *entity_class;
75 GParamSpec *param;
77 gobject_class = (GObjectClass *) klass;
78 entity_class = (AdgEntityClass *) klass;
80 g_type_class_add_private(klass, sizeof(AdgStrokePrivate));
82 gobject_class->dispose = dispose;
83 gobject_class->get_property = get_property;
84 gobject_class->set_property = set_property;
86 entity_class->arrange = arrange;
87 entity_class->render = render;
89 param = adg_param_spec_dress("dress",
90 P_("Dress Style"),
91 P_("The dress style to use for stroking this entity"),
92 ADG_DRESS_LINE_REGULAR,
93 G_PARAM_READWRITE);
94 g_object_class_install_property(gobject_class, PROP_DRESS, param);
96 param = g_param_spec_object("trail",
97 P_("Trail"),
98 P_("The trail to be stroked"),
99 ADG_TYPE_TRAIL,
100 G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
101 g_object_class_install_property(gobject_class, PROP_TRAIL, param);
104 static void
105 adg_stroke_init(AdgStroke *stroke)
107 AdgStrokePrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(stroke,
108 ADG_TYPE_STROKE,
109 AdgStrokePrivate);
111 data->dress = ADG_DRESS_LINE_REGULAR;
112 data->trail = NULL;
114 stroke->data = data;
117 static void
118 dispose(GObject *object)
120 AdgStroke *stroke = (AdgStroke *) object;
122 adg_stroke_set_trail(stroke, NULL);
124 if (PARENT_OBJECT_CLASS->dispose != NULL)
125 PARENT_OBJECT_CLASS->dispose(object);
128 static void
129 get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
131 AdgStrokePrivate *data = ((AdgStroke *) object)->data;
133 switch (prop_id) {
134 case PROP_DRESS:
135 g_value_set_int(value, data->dress);
136 break;
137 case PROP_TRAIL:
138 g_value_set_object(value, &data->trail);
139 break;
140 default:
141 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
142 break;
146 static void
147 set_property(GObject *object, guint prop_id,
148 const GValue *value, GParamSpec *pspec)
150 AdgStroke *stroke;
151 AdgStrokePrivate *data;
153 stroke = (AdgStroke *) object;
154 data = stroke->data;
156 switch (prop_id) {
157 case PROP_DRESS:
158 adg_dress_set(&data->dress, g_value_get_int(value));
159 break;
160 case PROP_TRAIL:
161 set_trail(stroke, (AdgTrail *) g_value_get_object(value));
162 break;
163 default:
164 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
165 break;
171 * adg_stroke_new:
172 * @trail: the #AdgTrail to stroke
174 * Creates a new stroke entity.
176 * Returns: the newly created stroke entity
178 AdgStroke *
179 adg_stroke_new(AdgTrail *trail)
181 g_return_val_if_fail(ADG_IS_TRAIL(trail), NULL);
183 return g_object_new(ADG_TYPE_STROKE, "trail", trail, NULL);
187 * adg_stroke_get_dress:
188 * @stroke: an #AdgStroke
190 * Gets the line dress to be used in rendering @stroke.
192 * Returns: the current line dress
194 AdgDress
195 adg_stroke_get_dress(AdgStroke *stroke)
197 AdgStrokePrivate *data;
199 g_return_val_if_fail(ADG_IS_STROKE(stroke), ADG_DRESS_UNDEFINED);
201 data = stroke->data;
203 return data->dress;
207 * adg_stroke_set_dress:
208 * @stroke: an #AdgStroke
209 * @dress: the new #AdgDress to use
211 * Sets a new line dress for rendering @stroke. The new dress
212 * must be related to the original dress for this property:
213 * you cannot set a dress used for line styles to a dress
214 * managing fonts.
216 * The check is done by calling adg_dress_are_related() with
217 * @dress and the previous dress as arguments. Check out its
218 * documentation for details on what is a related dress.
220 void
221 adg_stroke_set_dress(AdgStroke *stroke, AdgDress dress)
223 AdgStrokePrivate *data;
225 g_return_if_fail(ADG_IS_STROKE(stroke));
227 data = stroke->data;
229 if (adg_dress_set(&data->dress, dress))
230 g_object_notify((GObject *) stroke, "dress");
234 * adg_stroke_get_trail:
235 * @stroke: an #AdgStroke
237 * Gets the #AdgTrail bound to this @stroke entity.
239 * Returns: the requested #AdgTrail or %NULL on errors
241 AdgTrail *
242 adg_stroke_get_trail(AdgStroke *stroke)
244 AdgStrokePrivate *data;
246 g_return_val_if_fail(ADG_IS_STROKE(stroke), NULL);
248 data = stroke->data;
250 return data->trail;
254 * adg_stroke_set_trail:
255 * @stroke: an #AdgStroke
256 * @trail: the new #AdgTrail to bind
258 * Sets @trail as the new trail to be stroked by @stroke.
260 void
261 adg_stroke_set_trail(AdgStroke *stroke, AdgTrail *trail)
263 g_return_if_fail(ADG_IS_STROKE(stroke));
265 if (set_trail(stroke, trail))
266 g_object_notify((GObject *) stroke, "trail");
270 static void
271 arrange(AdgEntity *entity)
275 static void
276 render(AdgEntity *entity, cairo_t *cr)
278 AdgStroke *stroke;
279 AdgStrokePrivate *data;
280 const cairo_path_t *cairo_path;
282 stroke = (AdgStroke *) entity;
283 data = stroke->data;
284 cairo_path = adg_trail_get_cairo_path(data->trail);
286 if (cairo_path != NULL) {
287 AdgLineStyle *line_style;
289 line_style = (AdgLineStyle *) adg_entity_style(entity, data->dress);
291 cairo_save(cr);
292 adg_entity_apply_local_matrix(entity, cr);
293 cairo_append_path(cr, cairo_path);
294 cairo_restore(cr);
296 adg_style_apply((AdgStyle *) line_style, cr);
297 cairo_stroke(cr);
301 static gboolean
302 set_trail(AdgStroke *stroke, AdgTrail *trail)
304 AdgEntity *entity;
305 AdgStrokePrivate *data;
307 entity = (AdgEntity *) stroke;
308 data = stroke->data;
310 if (trail == data->trail)
311 return FALSE;
313 if (data->trail != NULL) {
314 g_object_weak_unref((GObject *) data->trail,
315 (GWeakNotify) unset_trail, stroke);
316 adg_model_remove_dependency((AdgModel *) data->trail, entity);
319 data->trail = trail;
321 if (data->trail != NULL) {
322 g_object_weak_ref((GObject *) data->trail,
323 (GWeakNotify) unset_trail, stroke);
324 adg_model_add_dependency((AdgModel *) data->trail, entity);
327 return TRUE;
330 static void
331 unset_trail(AdgStroke *stroke)
333 AdgStrokePrivate *data = stroke->data;
335 if (data->trail != NULL) {
336 data->trail = NULL;
337 adg_entity_invalidate((AdgEntity *) stroke);