adg: inherit AdgDress from GEnum
[adg.git] / src / adg / adg-stroke.c
blob2bfc3142db75fd2e997f9718d6c5bb7558310a41
1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007,2008,2009,2010,2011,2012,2013 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.
27 * Since: 1.0
28 **/
30 /**
31 * AdgStroke:
33 * All fields are private and should not be used directly.
34 * Use its public methods instead.
36 * Since: 1.0
37 **/
40 #include "adg-internal.h"
41 #include "adg-dress.h"
42 #include "adg-style.h"
43 #include "adg-dash.h"
44 #include "adg-line-style.h"
45 #include "adg-model.h"
46 #include "adg-trail.h"
48 #include "adg-stroke.h"
49 #include "adg-stroke-private.h"
51 #define _ADG_OLD_OBJECT_CLASS ((GObjectClass *) adg_stroke_parent_class)
52 #define _ADG_OLD_ENTITY_CLASS ((AdgEntityClass *) adg_stroke_parent_class)
55 G_DEFINE_TYPE(AdgStroke, adg_stroke, ADG_TYPE_ENTITY)
57 enum {
58 PROP_0,
59 PROP_LINE_DRESS,
60 PROP_TRAIL
64 static void _adg_dispose (GObject *object);
65 static void _adg_get_property (GObject *object,
66 guint param_id,
67 GValue *value,
68 GParamSpec *pspec);
69 static void _adg_set_property (GObject *object,
70 guint param_id,
71 const GValue *value,
72 GParamSpec *pspec);
73 static void _adg_global_changed (AdgEntity *entity);
74 static void _adg_local_changed (AdgEntity *entity);
75 static void _adg_arrange (AdgEntity *entity);
76 static void _adg_render (AdgEntity *entity,
77 cairo_t *cr);
78 static void _adg_unset_trail (AdgStroke *stroke);
81 static void
82 adg_stroke_class_init(AdgStrokeClass *klass)
84 GObjectClass *gobject_class;
85 AdgEntityClass *entity_class;
86 GParamSpec *param;
88 gobject_class = (GObjectClass *) klass;
89 entity_class = (AdgEntityClass *) klass;
91 g_type_class_add_private(klass, sizeof(AdgStrokePrivate));
93 gobject_class->dispose = _adg_dispose;
94 gobject_class->get_property = _adg_get_property;
95 gobject_class->set_property = _adg_set_property;
97 entity_class->global_changed = _adg_global_changed;
98 entity_class->local_changed = _adg_local_changed;
99 entity_class->arrange = _adg_arrange;
100 entity_class->render = _adg_render;
102 param = adg_param_spec_dress("line-dress",
103 P_("Line Dress"),
104 P_("The dress to use for stroking this entity"),
105 ADG_DRESS_LINE_STROKE,
106 G_PARAM_READWRITE);
107 g_object_class_install_property(gobject_class, PROP_LINE_DRESS, param);
109 param = g_param_spec_object("trail",
110 P_("Trail"),
111 P_("The trail to be stroked"),
112 ADG_TYPE_TRAIL,
113 G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
114 g_object_class_install_property(gobject_class, PROP_TRAIL, param);
117 static void
118 adg_stroke_init(AdgStroke *stroke)
120 AdgStrokePrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(stroke,
121 ADG_TYPE_STROKE,
122 AdgStrokePrivate);
124 data->line_dress = ADG_DRESS_LINE_STROKE;
125 data->trail = NULL;
127 stroke->data = data;
130 static void
131 _adg_dispose(GObject *object)
133 AdgStroke *stroke = (AdgStroke *) object;
135 adg_stroke_set_trail(stroke, NULL);
137 if (_ADG_OLD_OBJECT_CLASS->dispose)
138 _ADG_OLD_OBJECT_CLASS->dispose(object);
141 static void
142 _adg_get_property(GObject *object, guint prop_id,
143 GValue *value, GParamSpec *pspec)
145 AdgStrokePrivate *data = ((AdgStroke *) object)->data;
147 switch (prop_id) {
148 case PROP_LINE_DRESS:
149 g_value_set_enum(value, data->line_dress);
150 break;
151 case PROP_TRAIL:
152 g_value_set_object(value, data->trail);
153 break;
154 default:
155 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
156 break;
160 static void
161 _adg_set_property(GObject *object, guint prop_id,
162 const GValue *value, GParamSpec *pspec)
164 AdgStrokePrivate *data = ((AdgStroke *) object)->data;
165 AdgTrail *old_trail;
167 switch (prop_id) {
168 case PROP_LINE_DRESS:
169 data->line_dress = g_value_get_enum(value);
170 break;
171 case PROP_TRAIL:
172 old_trail = data->trail;
173 data->trail = g_value_get_object(value);
175 if (data->trail != old_trail) {
176 if (data->trail) {
177 g_object_weak_ref((GObject *) data->trail,
178 (GWeakNotify) _adg_unset_trail, object);
179 adg_model_add_dependency((AdgModel *) data->trail,
180 (AdgEntity *) object);
182 if (old_trail) {
183 g_object_weak_unref((GObject *) old_trail,
184 (GWeakNotify) _adg_unset_trail, object);
185 adg_model_remove_dependency((AdgModel *) old_trail,
186 (AdgEntity *) object);
189 break;
190 default:
191 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
192 break;
198 * adg_stroke_new:
199 * @trail: the #AdgTrail to stroke
201 * Creates a new stroke entity based on the @trail model.
202 * @trail can be %NULL, in which case an empty stroke is created.
204 * Returns: the newly created stroke entity
206 * Since: 1.0
208 AdgStroke *
209 adg_stroke_new(AdgTrail *trail)
211 return g_object_new(ADG_TYPE_STROKE, "trail", trail, NULL);
215 * adg_stroke_set_line_dress:
216 * @stroke: an #AdgStroke
217 * @dress: the new #AdgDress to use
219 * Sets a new line dress for rendering @stroke. The new dress
220 * must be related to the original dress for this property:
221 * you cannot set a dress used for line styles to a dress
222 * managing fonts.
224 * The check is done by calling adg_dress_are_related() with
225 * @dress and the previous dress as arguments. Check out its
226 * documentation for details on what is a related dress.
228 * Since: 1.0
230 void
231 adg_stroke_set_line_dress(AdgStroke *stroke, AdgDress dress)
233 g_return_if_fail(ADG_IS_STROKE(stroke));
234 g_object_set(stroke, "line-dress", dress, NULL);
238 * adg_stroke_get_line_dress:
239 * @stroke: an #AdgStroke
241 * Gets the line dress to be used in rendering @stroke.
243 * Returns: (transfer none): the current line dress.
245 * Since: 1.0
247 AdgDress
248 adg_stroke_get_line_dress(AdgStroke *stroke)
250 AdgStrokePrivate *data;
252 g_return_val_if_fail(ADG_IS_STROKE(stroke), ADG_DRESS_UNDEFINED);
254 data = stroke->data;
256 return data->line_dress;
260 * adg_stroke_set_trail:
261 * @stroke: an #AdgStroke
262 * @trail: the new #AdgTrail to bind
264 * Sets @trail as the new trail to be stroked by @stroke.
266 * Since: 1.0
268 void
269 adg_stroke_set_trail(AdgStroke *stroke, AdgTrail *trail)
271 g_return_if_fail(ADG_IS_STROKE(stroke));
272 g_object_set(stroke, "trail", trail, NULL);
276 * adg_stroke_get_trail:
277 * @stroke: an #AdgStroke
279 * Gets the #AdgTrail bound to this @stroke entity.
280 * The returned trail is owned by @stroke and should not
281 * be freed or modified.
283 * Returns: (transfer none): the requested #AdgTrail or %NULL on errors.
285 * Since: 1.0
287 AdgTrail *
288 adg_stroke_get_trail(AdgStroke *stroke)
290 AdgStrokePrivate *data;
292 g_return_val_if_fail(ADG_IS_STROKE(stroke), NULL);
294 data = stroke->data;
296 return data->trail;
300 static void
301 _adg_global_changed(AdgEntity *entity)
303 if (_ADG_OLD_ENTITY_CLASS->global_changed)
304 _ADG_OLD_ENTITY_CLASS->global_changed(entity);
306 adg_entity_invalidate(entity);
309 static void
310 _adg_local_changed(AdgEntity *entity)
312 if (_ADG_OLD_ENTITY_CLASS->local_changed)
313 _ADG_OLD_ENTITY_CLASS->local_changed(entity);
315 adg_entity_invalidate(entity);
318 static void
319 _adg_arrange(AdgEntity *entity)
321 AdgStroke *stroke;
322 AdgStrokePrivate *data;
323 CpmlExtents extents;
325 /* Check for cached result */
326 if (adg_entity_get_extents(entity)->is_defined)
327 return;
329 stroke = (AdgStroke *) entity;
330 data = stroke->data;
332 cpml_extents_copy(&extents, adg_trail_get_extents(data->trail));
333 cpml_extents_transform(&extents, adg_entity_get_local_matrix(entity));
334 cpml_extents_transform(&extents, adg_entity_get_global_matrix(entity));
336 adg_entity_set_extents(entity, &extents);
339 static void
340 _adg_render(AdgEntity *entity, cairo_t *cr)
342 AdgStroke *stroke;
343 AdgStrokePrivate *data;
344 const cairo_path_t *cairo_path;
346 stroke = (AdgStroke *) entity;
347 data = stroke->data;
348 cairo_path = adg_trail_get_cairo_path(data->trail);
350 if (cairo_path != NULL) {
351 cairo_transform(cr, adg_entity_get_global_matrix(entity));
353 cairo_save(cr);
354 cairo_transform(cr, adg_entity_get_local_matrix(entity));
355 cairo_append_path(cr, cairo_path);
356 cairo_restore(cr);
358 adg_entity_apply_dress(entity, data->line_dress, cr);
359 cairo_stroke(cr);
363 static void
364 _adg_unset_trail(AdgStroke *stroke)
366 g_object_set(stroke, "trail", NULL, NULL);