[AdgStroke] Using AdgDress instead of AdgContext
[adg.git] / adg / adg-stroke.c
blob2480f2015949efc4e93d584924081f2ae6d48568
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-intl.h"
40 #define PARENT_OBJECT_CLASS ((GObjectClass *) adg_stroke_parent_class)
43 enum {
44 PROP_0,
45 PROP_TRAIL,
46 PROP_DRESS
49 static void dispose (GObject *object);
50 static void get_property (GObject *object,
51 guint param_id,
52 GValue *value,
53 GParamSpec *pspec);
54 static void set_property (GObject *object,
55 guint param_id,
56 const GValue *value,
57 GParamSpec *pspec);
58 static gboolean render (AdgEntity *entity,
59 cairo_t *cr);
60 static gboolean set_trail (AdgStroke *stroke,
61 AdgTrail *trail);
62 static void unset_trail (AdgStroke *stroke);
65 G_DEFINE_TYPE(AdgStroke, adg_stroke, ADG_TYPE_ENTITY);
68 static void
69 adg_stroke_class_init(AdgStrokeClass *klass)
71 GObjectClass *gobject_class;
72 AdgEntityClass *entity_class;
73 GParamSpec *param;
75 gobject_class = (GObjectClass *) klass;
76 entity_class = (AdgEntityClass *) klass;
78 g_type_class_add_private(klass, sizeof(AdgStrokePrivate));
80 gobject_class->dispose = dispose;
81 gobject_class->get_property = get_property;
82 gobject_class->set_property = set_property;
84 entity_class->render = render;
86 param = adg_param_spec_dress("dress",
87 P_("Dress Style"),
88 P_("The dress style to use for stroking this entity"),
89 ADG_DRESS_LINE_MODEL,
90 G_PARAM_READWRITE);
91 g_object_class_install_property(gobject_class, PROP_DRESS, param);
93 param = g_param_spec_object("trail",
94 P_("Trail"),
95 P_("The trail to be stroked"),
96 ADG_TYPE_TRAIL,
97 G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
98 g_object_class_install_property(gobject_class, PROP_TRAIL, param);
101 static void
102 adg_stroke_init(AdgStroke *stroke)
104 AdgStrokePrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(stroke,
105 ADG_TYPE_STROKE,
106 AdgStrokePrivate);
108 data->trail = NULL;
109 data->dress = ADG_DRESS_LINE_MODEL;
111 stroke->data = data;
114 static void
115 dispose(GObject *object)
117 AdgStroke *stroke = (AdgStroke *) object;
119 adg_stroke_set_trail(stroke, NULL);
121 if (PARENT_OBJECT_CLASS->dispose != NULL)
122 PARENT_OBJECT_CLASS->dispose(object);
125 static void
126 get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
128 AdgStrokePrivate *data = ((AdgStroke *) object)->data;
130 switch (prop_id) {
131 case PROP_DRESS:
132 g_value_set_int(value, data->dress);
133 break;
134 case PROP_TRAIL:
135 g_value_set_object(value, &data->trail);
136 break;
137 default:
138 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
139 break;
143 static void
144 set_property(GObject *object, guint prop_id,
145 const GValue *value, GParamSpec *pspec)
147 AdgStroke *stroke;
148 AdgStrokePrivate *data;
150 stroke = (AdgStroke *) object;
151 data = stroke->data;
153 switch (prop_id) {
154 case PROP_DRESS:
155 adg_dress_set(&data->dress, g_value_get_int(value));
156 break;
157 case PROP_TRAIL:
158 set_trail(stroke, (AdgTrail *) g_value_get_object(value));
159 break;
160 default:
161 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
162 break;
168 * adg_stroke_new:
169 * @trail: the #AdgTrail to stroke
171 * Creates a new stroke entity.
173 * Returns: the newly created stroke entity
175 AdgStroke *
176 adg_stroke_new(AdgTrail *trail)
178 g_return_val_if_fail(ADG_IS_TRAIL(trail), NULL);
180 return g_object_new(ADG_TYPE_STROKE, "trail", trail, NULL);
184 * adg_stroke_get_dress:
185 * @stroke: an #AdgStroke
187 * Gets the line dress to be used in rendering @stroke.
189 * Returns: the current line dress
191 AdgDress
192 adg_stroke_get_dress(AdgStroke *stroke)
194 AdgStrokePrivate *data;
196 g_return_val_if_fail(ADG_IS_STROKE(stroke), ADG_DRESS_UNDEFINED);
198 data = stroke->data;
200 return data->dress;
204 * adg_stroke_set_dress:
205 * @stroke: an #AdgStroke
206 * @dress: the new #AdgDress to use
208 * Sets a new line dress for rendering @stroke. The new dress
209 * must be related to the original dress for this property:
210 * you cannot set a dress used for line styles to a dress
211 * managing fonts.
213 * The check is done by calling adg_dress_are_related() with
214 * @dress and the previous dress as arguments. Check out its
215 * documentation for details on what is a related dress.
217 void
218 adg_stroke_set_dress(AdgStroke *stroke, AdgDress dress)
220 AdgStrokePrivate *data;
222 g_return_if_fail(ADG_IS_STROKE(stroke));
224 data = stroke->data;
226 if (adg_dress_set(&data->dress, dress))
227 g_object_notify((GObject *) stroke, "dress");
231 * adg_stroke_get_trail:
232 * @stroke: an #AdgStroke
234 * Gets the #AdgTrail binded to this @stroke entity.
236 * Returns: the requested #AdgTrail or %NULL on errors
238 AdgTrail *
239 adg_stroke_get_trail(AdgStroke *stroke)
241 AdgStrokePrivate *data;
243 g_return_val_if_fail(ADG_IS_STROKE(stroke), NULL);
245 data = stroke->data;
247 return data->trail;
251 * adg_stroke_set_trail:
252 * @stroke: an #AdgStroke
253 * @trail: the new #AdgTrail to bind
255 * Sets @trail as the new trail to be stroked by @stroke.
257 void
258 adg_stroke_set_trail(AdgStroke *stroke, AdgTrail *trail)
260 g_return_if_fail(ADG_IS_STROKE(stroke));
262 if (set_trail(stroke, trail))
263 g_object_notify((GObject *) stroke, "trail");
267 static gboolean
268 render(AdgEntity *entity, cairo_t *cr)
270 AdgStroke *stroke;
271 AdgStrokePrivate *data;
272 const cairo_path_t *cairo_path;
274 stroke = (AdgStroke *) entity;
275 data = stroke->data;
276 cairo_path = adg_trail_get_cairo_path(data->trail);
278 if (cairo_path != NULL) {
279 cairo_save(cr);
280 adg_entity_apply_local_matrix(entity, cr);
281 cairo_append_path(cr, cairo_path);
282 cairo_restore(cr);
284 adg_entity_apply_dress(entity, data->dress, cr);
285 cairo_stroke(cr);
288 return TRUE;
291 static gboolean
292 set_trail(AdgStroke *stroke, AdgTrail *trail)
294 AdgEntity *entity;
295 AdgStrokePrivate *data;
297 entity = (AdgEntity *) stroke;
298 data = stroke->data;
300 if (trail == data->trail)
301 return FALSE;
303 if (data->trail != NULL) {
304 g_object_weak_unref((GObject *) data->trail,
305 (GWeakNotify) unset_trail, stroke);
306 adg_model_remove_dependency((AdgModel *) data->trail, entity);
309 data->trail = trail;
311 if (data->trail != NULL) {
312 g_object_weak_ref((GObject *) data->trail,
313 (GWeakNotify) unset_trail, stroke);
314 adg_model_add_dependency((AdgModel *) data->trail, entity);
317 return TRUE;
320 static void
321 unset_trail(AdgStroke *stroke)
323 AdgStrokePrivate *data = stroke->data;
325 if (data->trail != NULL) {
326 data->trail = NULL;
327 adg_entity_invalidate((AdgEntity *) stroke);