[ADG] Avoid to forcibly set the CTM on the cr
[adg.git] / src / adg / adg-arrow.c
blobb535a4a5fa62a86876f27a3e2fb0a5151346dd72
1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007,2008,2009,2010 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-arrow
23 * @short_description: Arrow rendering related stuff
25 * Contains parameters on how to draw arrows, providing a way to register a
26 * custom rendering callback.
27 **/
29 /**
30 * AdgArrow:
32 * All fields are private and should not be used directly.
33 * Use its public methods instead.
34 **/
37 #include "adg-internal.h"
38 #include "adg-arrow.h"
39 #include "adg-arrow-private.h"
40 #include "adg-path.h"
43 G_DEFINE_TYPE(AdgArrow, adg_arrow, ADG_TYPE_MARKER);
45 enum {
46 PROP_0,
47 PROP_ANGLE
51 static void _adg_get_property (GObject *object,
52 guint prop_id,
53 GValue *value,
54 GParamSpec *pspec);
55 static void _adg_set_property (GObject *object,
56 guint prop_id,
57 const GValue *value,
58 GParamSpec *pspec);
59 static void _adg_arrange (AdgEntity *entity);
60 static void _adg_render (AdgEntity *entity,
61 cairo_t *cr);
62 static AdgModel * _adg_create_model (AdgMarker *marker);
65 static void
66 adg_arrow_class_init(AdgArrowClass *klass)
68 GObjectClass *gobject_class;
69 AdgEntityClass *entity_class;
70 AdgMarkerClass *marker_class;
71 GParamSpec *param;
73 gobject_class = (GObjectClass *) klass;
74 entity_class = (AdgEntityClass *) klass;
75 marker_class = (AdgMarkerClass *) klass;
77 g_type_class_add_private(klass, sizeof(AdgArrowPrivate));
79 gobject_class->set_property = _adg_set_property;
80 gobject_class->get_property = _adg_get_property;
82 entity_class->arrange = _adg_arrange;
83 entity_class->render = _adg_render;
85 marker_class->create_model = _adg_create_model;
87 param = g_param_spec_double("angle",
88 P_("Arrow Angle"),
89 P_("The opening angle of the arrow"),
90 -G_PI, G_PI, G_PI / 6,
91 G_PARAM_READWRITE);
92 g_object_class_install_property(gobject_class, PROP_ANGLE, param);
95 static void
96 adg_arrow_init(AdgArrow *arrow)
98 AdgArrowPrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(arrow,
99 ADG_TYPE_ARROW,
100 AdgArrowPrivate);
102 data->angle = G_PI/6;
104 arrow->data = data;
107 static void
108 _adg_get_property(GObject *object, guint prop_id,
109 GValue *value, GParamSpec *pspec)
111 AdgArrowPrivate *data = ((AdgArrow *) object)->data;
113 switch (prop_id) {
114 case PROP_ANGLE:
115 g_value_set_double(value, data->angle);
116 break;
117 default:
118 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
119 break;
123 static void
124 _adg_set_property(GObject *object, guint prop_id,
125 const GValue *value, GParamSpec *pspec)
127 AdgArrowPrivate *data = ((AdgArrow *) object)->data;
129 switch (prop_id) {
130 case PROP_ANGLE:
131 data->angle = cpml_angle(g_value_get_double(value));
132 break;
133 default:
134 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
135 break;
141 * adg_arrow_new:
142 * @trail: the #AdgTrail to arrow
144 * Creates a new undefined arrow entity. The position must be defined
145 * by setting the #AdgMarker:trail and #AdgMarker:pos properties.
146 * By default, an arrow as #AdgEntity:local-method set to #ADG_MIX_PARENT.
148 * Returns: the newly created arrow entity
150 AdgArrow *
151 adg_arrow_new(void)
153 return g_object_new(ADG_TYPE_ARROW,
154 "local-method", ADG_MIX_PARENT,
155 NULL);
159 * adg_arrow_new_with_trail:
160 * @trail: the #AdgTrail where the arrow should be added
161 * @pos: the position ratio on @trail
163 * Creates a new arrow on the first segment on @trail at position
164 * @pos, where @pos is a ratio of the @trail length (being %0 the
165 * start point, %1 the end point, %0.5 the middle point and so on).
166 * By default, an arrow as #AdgEntity:local-method set to #ADG_MIX_PARENT.
168 * Returns: the newly created arrow entity
170 AdgArrow *
171 adg_arrow_new_with_trail(AdgTrail *trail, gdouble pos)
173 return g_object_new(ADG_TYPE_ARROW,
174 "local-method", ADG_MIX_PARENT,
175 "trail", trail,
176 "n-segment", 1,
177 "pos", pos,
178 NULL);
182 * adg_arrow_set_angle:
183 * @arrow: an #AdgArrow
184 * @angle: the new angle
186 * Sets a new angle: @angle will be the new opening angle of @arrow.
187 * Changing the arrow angle will invalidate @arrow.
189 void
190 adg_arrow_set_angle(AdgArrow *arrow, gdouble angle)
192 g_return_if_fail(ADG_IS_ARROW(arrow));
193 g_object_set(arrow, "angle", angle, NULL);
197 * adg_arrow_get_angle:
198 * @arrow: an #AdgArrow
200 * Gets the current angle of @arrow.
202 * Returns: the arrow angle, in radians
204 gdouble
205 adg_arrow_get_angle(AdgArrow *arrow)
207 AdgArrowPrivate *data;
209 g_return_val_if_fail(ADG_IS_ARROW(arrow), 0);
211 data = arrow->data;
213 return data->angle;
217 static void
218 _adg_arrange(AdgEntity *entity)
220 /* TODO */
223 static void
224 _adg_render(AdgEntity *entity, cairo_t *cr)
226 AdgModel *model;
227 const cairo_path_t *cairo_path;
229 model = adg_marker_model((AdgMarker *) entity);
230 cairo_path = adg_trail_get_cairo_path((AdgTrail *) model);
232 if (cairo_path != NULL) {
233 cairo_save(cr);
234 cairo_transform(cr, adg_entity_get_global_matrix(entity));
235 cairo_transform(cr, adg_entity_get_local_matrix(entity));
236 cairo_append_path(cr, cairo_path);
237 cairo_restore(cr);
239 cairo_fill(cr);
243 static AdgModel *
244 _adg_create_model(AdgMarker *marker)
246 AdgArrowPrivate *data;
247 AdgPath *path;
248 CpmlPair p1, p2;
250 data = ((AdgArrow *) marker)->data;
251 path = adg_path_new();
252 cpml_vector_from_angle(&p1, data->angle / 2);
253 p2.x = p1.x;
254 p2.y = -p1.y;
256 adg_path_move_to_explicit(path, 0, 0);
257 adg_path_line_to(path, &p1);
258 adg_path_line_to(path, &p2);
259 adg_path_close(path);
261 return (AdgModel *) path;