doc: update copyright line for 2021
[adg.git] / src / adg / adg-arrow.c
blobd48f04c96eb959bcb9488c2fac3fc3cd8d66e4a2
1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007-2021 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 * <note><para>
29 * By default, the #AdgEntity:local-mix property is set to #ADG_MIX_PARENT
30 * on #AdgArrow entities.
31 * </para></note>
33 * Since: 1.0
34 **/
36 /**
37 * AdgArrow:
39 * All fields are private and should not be used directly.
40 * Use its public methods instead.
42 * Since: 1.0
43 **/
46 #include "adg-internal.h"
47 #include "adg-model.h"
48 #include "adg-trail.h"
49 #include "adg-path.h"
50 #include "adg-marker.h"
52 #include "adg-arrow.h"
53 #include "adg-arrow-private.h"
56 G_DEFINE_TYPE_WITH_PRIVATE(AdgArrow, adg_arrow, ADG_TYPE_MARKER)
58 enum {
59 PROP_0,
60 PROP_ANGLE
64 static void _adg_get_property (GObject *object,
65 guint prop_id,
66 GValue *value,
67 GParamSpec *pspec);
68 static void _adg_set_property (GObject *object,
69 guint prop_id,
70 const GValue *value,
71 GParamSpec *pspec);
72 static void _adg_arrange (AdgEntity *entity);
73 static void _adg_render (AdgEntity *entity,
74 cairo_t *cr);
75 static AdgModel * _adg_create_model (AdgMarker *marker);
78 static void
79 adg_arrow_class_init(AdgArrowClass *klass)
81 GObjectClass *gobject_class;
82 AdgEntityClass *entity_class;
83 AdgMarkerClass *marker_class;
84 GParamSpec *param;
86 gobject_class = (GObjectClass *) klass;
87 entity_class = (AdgEntityClass *) klass;
88 marker_class = (AdgMarkerClass *) klass;
90 gobject_class->set_property = _adg_set_property;
91 gobject_class->get_property = _adg_get_property;
93 entity_class->arrange = _adg_arrange;
94 entity_class->render = _adg_render;
96 marker_class->create_model = _adg_create_model;
98 param = g_param_spec_double("angle",
99 P_("Arrow Angle"),
100 P_("The opening angle of the arrow"),
101 -G_PI, G_PI, G_PI / 6,
102 G_PARAM_READWRITE);
103 g_object_class_install_property(gobject_class, PROP_ANGLE, param);
106 static void
107 adg_arrow_init(AdgArrow *arrow)
109 AdgArrowPrivate *data = adg_arrow_get_instance_private(arrow);
111 data->angle = G_PI/6;
113 adg_entity_set_local_mix((AdgEntity *) arrow, ADG_MIX_PARENT);
116 static void
117 _adg_get_property(GObject *object, guint prop_id,
118 GValue *value, GParamSpec *pspec)
120 AdgArrowPrivate *data = adg_arrow_get_instance_private((AdgArrow *) object);
122 switch (prop_id) {
123 case PROP_ANGLE:
124 g_value_set_double(value, data->angle);
125 break;
126 default:
127 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
128 break;
132 static void
133 _adg_set_property(GObject *object, guint prop_id,
134 const GValue *value, GParamSpec *pspec)
136 AdgArrowPrivate *data = adg_arrow_get_instance_private((AdgArrow *) object);
138 switch (prop_id) {
139 case PROP_ANGLE:
140 data->angle = cpml_angle(g_value_get_double(value));
141 break;
142 default:
143 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
144 break;
150 * adg_arrow_new:
152 * Creates a new undefined arrow entity. The position must be defined
153 * by setting the #AdgMarker:trail and #AdgMarker:pos properties.
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, NULL);
166 * adg_arrow_new_with_trail:
167 * @trail: the #AdgTrail where the arrow should be added
168 * @pos: the position ratio on @trail
170 * Creates a new arrow on the first segment on @trail at position
171 * @pos, where @pos is a ratio of the @trail length (being 0 the
172 * start point, 1 the end point, 0.5 the middle point and so on).
173 * By default, an arrow as #AdgEntity:local-mix set to #ADG_MIX_PARENT.
175 * Returns: the newly created arrow entity
177 * Since: 1.0
179 AdgArrow *
180 adg_arrow_new_with_trail(AdgTrail *trail, gdouble pos)
182 return g_object_new(ADG_TYPE_ARROW,
183 "local-mix", ADG_MIX_PARENT,
184 "trail", trail,
185 "n-segment", 1,
186 "pos", pos,
187 NULL);
191 * adg_arrow_set_angle:
192 * @arrow: an #AdgArrow
193 * @angle: the new angle
195 * Sets a new angle: @angle will be the new opening angle of @arrow.
196 * Changing the arrow angle will invalidate @arrow.
198 * Since: 1.0
200 void
201 adg_arrow_set_angle(AdgArrow *arrow, gdouble angle)
203 g_return_if_fail(ADG_IS_ARROW(arrow));
204 g_object_set(arrow, "angle", angle, NULL);
208 * adg_arrow_get_angle:
209 * @arrow: an #AdgArrow
211 * Gets the current angle of @arrow.
213 * Returns: the arrow angle, in radians
215 * Since: 1.0
217 gdouble
218 adg_arrow_get_angle(AdgArrow *arrow)
220 AdgArrowPrivate *data;
222 g_return_val_if_fail(ADG_IS_ARROW(arrow), 0);
224 data = adg_arrow_get_instance_private(arrow);
225 return data->angle;
229 static void
230 _adg_arrange(AdgEntity *entity)
232 AdgModel *model;
233 const CpmlExtents *extents;
234 CpmlExtents new_extents;
236 model = adg_marker_model((AdgMarker *) entity);
237 if (model == NULL)
238 return;
240 extents = adg_trail_get_extents((AdgTrail *) model);
241 if (extents == NULL)
242 return;
244 cpml_extents_copy(&new_extents, extents);
245 cpml_extents_transform(&new_extents, adg_entity_get_local_matrix(entity));
246 adg_entity_set_extents(entity, &new_extents);
249 static void
250 _adg_render(AdgEntity *entity, cairo_t *cr)
252 AdgModel *model;
253 const cairo_path_t *cairo_path;
255 model = adg_marker_model((AdgMarker *) entity);
256 if (model == NULL)
257 return;
259 cairo_path = adg_trail_get_cairo_path((AdgTrail *) model);
261 if (cairo_path != NULL) {
262 cairo_save(cr);
263 cairo_transform(cr, adg_entity_get_global_matrix(entity));
264 cairo_transform(cr, adg_entity_get_local_matrix(entity));
265 cairo_append_path(cr, cairo_path);
266 cairo_restore(cr);
268 cairo_fill(cr);
272 static AdgModel *
273 _adg_create_model(AdgMarker *marker)
275 AdgArrowPrivate *data;
276 AdgPath *path;
277 CpmlPair p1, p2;
279 data = adg_arrow_get_instance_private((AdgArrow *) marker);
280 path = adg_path_new();
281 cpml_vector_from_angle(&p1, data->angle / 2);
282 p2.x = p1.x;
283 p2.y = -p1.y;
285 adg_path_move_to_explicit(path, 0, 0);
286 adg_path_line_to(path, &p1);
287 adg_path_line_to(path, &p2);
288 adg_path_close(path);
290 return (AdgModel *) path;