[AdgLDim] Quote management throught maps
[adg.git] / adg / adg-stroke.c
blobd92a7583b2f2c2c3272d00a430386abe8b3153fb
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 gboolean render (AdgEntity *entity,
60 cairo_t *cr);
61 static gboolean set_trail (AdgStroke *stroke,
62 AdgTrail *trail);
63 static void unset_trail (AdgStroke *stroke);
66 G_DEFINE_TYPE(AdgStroke, adg_stroke, ADG_TYPE_ENTITY);
69 static void
70 adg_stroke_class_init(AdgStrokeClass *klass)
72 GObjectClass *gobject_class;
73 AdgEntityClass *entity_class;
74 GParamSpec *param;
76 gobject_class = (GObjectClass *) klass;
77 entity_class = (AdgEntityClass *) klass;
79 g_type_class_add_private(klass, sizeof(AdgStrokePrivate));
81 gobject_class->dispose = dispose;
82 gobject_class->get_property = get_property;
83 gobject_class->set_property = set_property;
85 entity_class->render = render;
87 param = adg_param_spec_dress("dress",
88 P_("Dress Style"),
89 P_("The dress style to use for stroking this entity"),
90 ADG_DRESS_LINE_REGULAR,
91 G_PARAM_READWRITE);
92 g_object_class_install_property(gobject_class, PROP_DRESS, param);
94 param = g_param_spec_object("trail",
95 P_("Trail"),
96 P_("The trail to be stroked"),
97 ADG_TYPE_TRAIL,
98 G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
99 g_object_class_install_property(gobject_class, PROP_TRAIL, param);
102 static void
103 adg_stroke_init(AdgStroke *stroke)
105 AdgStrokePrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(stroke,
106 ADG_TYPE_STROKE,
107 AdgStrokePrivate);
109 data->dress = ADG_DRESS_LINE_REGULAR;
110 data->trail = NULL;
112 stroke->data = data;
115 static void
116 dispose(GObject *object)
118 AdgStroke *stroke = (AdgStroke *) object;
120 adg_stroke_set_trail(stroke, NULL);
122 if (PARENT_OBJECT_CLASS->dispose != NULL)
123 PARENT_OBJECT_CLASS->dispose(object);
126 static void
127 get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
129 AdgStrokePrivate *data = ((AdgStroke *) object)->data;
131 switch (prop_id) {
132 case PROP_DRESS:
133 g_value_set_int(value, data->dress);
134 break;
135 case PROP_TRAIL:
136 g_value_set_object(value, &data->trail);
137 break;
138 default:
139 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
140 break;
144 static void
145 set_property(GObject *object, guint prop_id,
146 const GValue *value, GParamSpec *pspec)
148 AdgStroke *stroke;
149 AdgStrokePrivate *data;
151 stroke = (AdgStroke *) object;
152 data = stroke->data;
154 switch (prop_id) {
155 case PROP_DRESS:
156 adg_dress_set(&data->dress, g_value_get_int(value));
157 break;
158 case PROP_TRAIL:
159 set_trail(stroke, (AdgTrail *) g_value_get_object(value));
160 break;
161 default:
162 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
163 break;
169 * adg_stroke_new:
170 * @trail: the #AdgTrail to stroke
172 * Creates a new stroke entity.
174 * Returns: the newly created stroke entity
176 AdgStroke *
177 adg_stroke_new(AdgTrail *trail)
179 g_return_val_if_fail(ADG_IS_TRAIL(trail), NULL);
181 return g_object_new(ADG_TYPE_STROKE, "trail", trail, NULL);
185 * adg_stroke_get_dress:
186 * @stroke: an #AdgStroke
188 * Gets the line dress to be used in rendering @stroke.
190 * Returns: the current line dress
192 AdgDress
193 adg_stroke_get_dress(AdgStroke *stroke)
195 AdgStrokePrivate *data;
197 g_return_val_if_fail(ADG_IS_STROKE(stroke), ADG_DRESS_UNDEFINED);
199 data = stroke->data;
201 return data->dress;
205 * adg_stroke_set_dress:
206 * @stroke: an #AdgStroke
207 * @dress: the new #AdgDress to use
209 * Sets a new line dress for rendering @stroke. The new dress
210 * must be related to the original dress for this property:
211 * you cannot set a dress used for line styles to a dress
212 * managing fonts.
214 * The check is done by calling adg_dress_are_related() with
215 * @dress and the previous dress as arguments. Check out its
216 * documentation for details on what is a related dress.
218 void
219 adg_stroke_set_dress(AdgStroke *stroke, AdgDress dress)
221 AdgStrokePrivate *data;
223 g_return_if_fail(ADG_IS_STROKE(stroke));
225 data = stroke->data;
227 if (adg_dress_set(&data->dress, dress))
228 g_object_notify((GObject *) stroke, "dress");
232 * adg_stroke_get_trail:
233 * @stroke: an #AdgStroke
235 * Gets the #AdgTrail binded to this @stroke entity.
237 * Returns: the requested #AdgTrail or %NULL on errors
239 AdgTrail *
240 adg_stroke_get_trail(AdgStroke *stroke)
242 AdgStrokePrivate *data;
244 g_return_val_if_fail(ADG_IS_STROKE(stroke), NULL);
246 data = stroke->data;
248 return data->trail;
252 * adg_stroke_set_trail:
253 * @stroke: an #AdgStroke
254 * @trail: the new #AdgTrail to bind
256 * Sets @trail as the new trail to be stroked by @stroke.
258 void
259 adg_stroke_set_trail(AdgStroke *stroke, AdgTrail *trail)
261 g_return_if_fail(ADG_IS_STROKE(stroke));
263 if (set_trail(stroke, trail))
264 g_object_notify((GObject *) stroke, "trail");
268 static gboolean
269 render(AdgEntity *entity, cairo_t *cr)
271 AdgStroke *stroke;
272 AdgStrokePrivate *data;
273 const cairo_path_t *cairo_path;
275 stroke = (AdgStroke *) entity;
276 data = stroke->data;
277 cairo_path = adg_trail_get_cairo_path(data->trail);
279 if (cairo_path != NULL) {
280 AdgLineStyle *line_style;
282 line_style = (AdgLineStyle *) adg_entity_style(entity, data->dress);
284 cairo_save(cr);
285 adg_entity_apply_local_matrix(entity, cr);
286 cairo_append_path(cr, cairo_path);
287 cairo_restore(cr);
289 adg_style_apply((AdgStyle *) line_style, cr);
290 cairo_stroke(cr);
293 return TRUE;
296 static gboolean
297 set_trail(AdgStroke *stroke, AdgTrail *trail)
299 AdgEntity *entity;
300 AdgStrokePrivate *data;
302 entity = (AdgEntity *) stroke;
303 data = stroke->data;
305 if (trail == data->trail)
306 return FALSE;
308 if (data->trail != NULL) {
309 g_object_weak_unref((GObject *) data->trail,
310 (GWeakNotify) unset_trail, stroke);
311 adg_model_remove_dependency((AdgModel *) data->trail, entity);
314 data->trail = trail;
316 if (data->trail != NULL) {
317 g_object_weak_ref((GObject *) data->trail,
318 (GWeakNotify) unset_trail, stroke);
319 adg_model_add_dependency((AdgModel *) data->trail, entity);
322 return TRUE;
325 static void
326 unset_trail(AdgStroke *stroke)
328 AdgStrokePrivate *data = stroke->data;
330 if (data->trail != NULL) {
331 data->trail = NULL;
332 adg_entity_invalidate((AdgEntity *) stroke);