adg: renamed AdgMixMethod to AdgMix
[adg.git] / src / adg / adg-arrow.c
blob1b4c44caa4affa6e91b365e27c9e2fc11fd1cb45
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-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.
28 * Since: 1.0
29 **/
31 /**
32 * AdgArrow:
34 * All fields are private and should not be used directly.
35 * Use its public methods instead.
37 * Since: 1.0
38 **/
41 #include "adg-internal.h"
42 #include "adg-model.h"
43 #include "adg-trail.h"
44 #include "adg-path.h"
45 #include "adg-marker.h"
47 #include "adg-arrow.h"
48 #include "adg-arrow-private.h"
51 G_DEFINE_TYPE(AdgArrow, adg_arrow, ADG_TYPE_MARKER)
53 enum {
54 PROP_0,
55 PROP_ANGLE
59 static void _adg_get_property (GObject *object,
60 guint prop_id,
61 GValue *value,
62 GParamSpec *pspec);
63 static void _adg_set_property (GObject *object,
64 guint prop_id,
65 const GValue *value,
66 GParamSpec *pspec);
67 static void _adg_arrange (AdgEntity *entity);
68 static void _adg_render (AdgEntity *entity,
69 cairo_t *cr);
70 static AdgModel * _adg_create_model (AdgMarker *marker);
73 static void
74 adg_arrow_class_init(AdgArrowClass *klass)
76 GObjectClass *gobject_class;
77 AdgEntityClass *entity_class;
78 AdgMarkerClass *marker_class;
79 GParamSpec *param;
81 gobject_class = (GObjectClass *) klass;
82 entity_class = (AdgEntityClass *) klass;
83 marker_class = (AdgMarkerClass *) klass;
85 g_type_class_add_private(klass, sizeof(AdgArrowPrivate));
87 gobject_class->set_property = _adg_set_property;
88 gobject_class->get_property = _adg_get_property;
90 entity_class->arrange = _adg_arrange;
91 entity_class->render = _adg_render;
93 marker_class->create_model = _adg_create_model;
95 param = g_param_spec_double("angle",
96 P_("Arrow Angle"),
97 P_("The opening angle of the arrow"),
98 -G_PI, G_PI, G_PI / 6,
99 G_PARAM_READWRITE);
100 g_object_class_install_property(gobject_class, PROP_ANGLE, param);
103 static void
104 adg_arrow_init(AdgArrow *arrow)
106 AdgArrowPrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(arrow,
107 ADG_TYPE_ARROW,
108 AdgArrowPrivate);
110 data->angle = G_PI/6;
112 arrow->data = data;
115 static void
116 _adg_get_property(GObject *object, guint prop_id,
117 GValue *value, GParamSpec *pspec)
119 AdgArrowPrivate *data = ((AdgArrow *) object)->data;
121 switch (prop_id) {
122 case PROP_ANGLE:
123 g_value_set_double(value, data->angle);
124 break;
125 default:
126 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
127 break;
131 static void
132 _adg_set_property(GObject *object, guint prop_id,
133 const GValue *value, GParamSpec *pspec)
135 AdgArrowPrivate *data = ((AdgArrow *) object)->data;
137 switch (prop_id) {
138 case PROP_ANGLE:
139 data->angle = cpml_angle(g_value_get_double(value));
140 break;
141 default:
142 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
143 break;
149 * adg_arrow_new:
151 * Creates a new undefined arrow entity. The position must be defined
152 * by setting the #AdgMarker:trail and #AdgMarker:pos properties.
153 * By default, an arrow as #AdgEntity:local-mix set to #ADG_MIX_PARENT.
155 * Returns: the newly created arrow entity
157 * Since: 1.0
159 AdgArrow *
160 adg_arrow_new(void)
162 return g_object_new(ADG_TYPE_ARROW,
163 "local-mix", ADG_MIX_PARENT,
164 NULL);
168 * adg_arrow_new_with_trail:
169 * @trail: the #AdgTrail where the arrow should be added
170 * @pos: the position ratio on @trail
172 * Creates a new arrow on the first segment on @trail at position
173 * @pos, where @pos is a ratio of the @trail length (being %0 the
174 * start point, %1 the end point, %0.5 the middle point and so on).
175 * By default, an arrow as #AdgEntity:local-mix set to #ADG_MIX_PARENT.
177 * Returns: the newly created arrow entity
179 * Since: 1.0
181 AdgArrow *
182 adg_arrow_new_with_trail(AdgTrail *trail, gdouble pos)
184 return g_object_new(ADG_TYPE_ARROW,
185 "local-mix", ADG_MIX_PARENT,
186 "trail", trail,
187 "n-segment", 1,
188 "pos", pos,
189 NULL);
193 * adg_arrow_set_angle:
194 * @arrow: an #AdgArrow
195 * @angle: the new angle
197 * Sets a new angle: @angle will be the new opening angle of @arrow.
198 * Changing the arrow angle will invalidate @arrow.
200 * Since: 1.0
202 void
203 adg_arrow_set_angle(AdgArrow *arrow, gdouble angle)
205 g_return_if_fail(ADG_IS_ARROW(arrow));
206 g_object_set(arrow, "angle", angle, NULL);
210 * adg_arrow_get_angle:
211 * @arrow: an #AdgArrow
213 * Gets the current angle of @arrow.
215 * Returns: the arrow angle, in radians
217 * Since: 1.0
219 gdouble
220 adg_arrow_get_angle(AdgArrow *arrow)
222 AdgArrowPrivate *data;
224 g_return_val_if_fail(ADG_IS_ARROW(arrow), 0);
226 data = arrow->data;
228 return data->angle;
232 static void
233 _adg_arrange(AdgEntity *entity)
235 AdgModel *model;
236 const CpmlExtents *extents;
237 CpmlExtents new_extents;
239 model = adg_marker_model((AdgMarker *) entity);
240 if (model == NULL)
241 return;
243 extents = adg_trail_get_extents((AdgTrail *) model);
244 if (extents == NULL)
245 return;
247 cpml_extents_copy(&new_extents, extents);
248 cpml_extents_transform(&new_extents, adg_entity_get_local_matrix(entity));
249 adg_entity_set_extents(entity, &new_extents);
252 static void
253 _adg_render(AdgEntity *entity, cairo_t *cr)
255 AdgModel *model;
256 const cairo_path_t *cairo_path;
258 model = adg_marker_model((AdgMarker *) entity);
259 if (model == NULL)
260 return;
262 cairo_path = adg_trail_get_cairo_path((AdgTrail *) model);
264 if (cairo_path != NULL) {
265 cairo_save(cr);
266 cairo_transform(cr, adg_entity_get_global_matrix(entity));
267 cairo_transform(cr, adg_entity_get_local_matrix(entity));
268 cairo_append_path(cr, cairo_path);
269 cairo_restore(cr);
271 cairo_fill(cr);
275 static AdgModel *
276 _adg_create_model(AdgMarker *marker)
278 AdgArrowPrivate *data;
279 AdgPath *path;
280 CpmlPair p1, p2;
282 data = ((AdgArrow *) marker)->data;
283 path = adg_path_new();
284 cpml_vector_from_angle(&p1, data->angle / 2);
285 p2.x = p1.x;
286 p2.y = -p1.y;
288 adg_path_move_to_explicit(path, 0, 0);
289 adg_path_line_to(path, &p1);
290 adg_path_line_to(path, &p2);
291 adg_path_close(path);
293 return (AdgModel *) path;