[AdgMarker] Added missing APIs
[adg.git] / adg / adg-arrow.c
blob5b3785f53da29daefc2f47a19059e2390d938315
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 enum {
44 PROP_0,
45 PROP_ANGLE
49 static void get_property (GObject *object,
50 guint prop_id,
51 GValue *value,
52 GParamSpec *pspec);
53 static void set_property (GObject *object,
54 guint prop_id,
55 const GValue *value,
56 GParamSpec *pspec);
57 static void arrange (AdgEntity *entity);
58 static void render (AdgEntity *entity,
59 cairo_t *cr);
60 static AdgModel * create_model (AdgMarker *marker);
61 static gboolean set_angle (AdgArrow *arrow,
62 gdouble angle);
65 G_DEFINE_TYPE(AdgArrow, adg_arrow, ADG_TYPE_MARKER);
68 static void
69 adg_arrow_class_init(AdgArrowClass *klass)
71 GObjectClass *gobject_class;
72 AdgEntityClass *entity_class;
73 AdgMarkerClass *marker_class;
74 GParamSpec *param;
76 gobject_class = (GObjectClass *) klass;
77 entity_class = (AdgEntityClass *) klass;
78 marker_class = (AdgMarkerClass *) klass;
80 g_type_class_add_private(klass, sizeof(AdgArrowPrivate));
82 gobject_class->set_property = set_property;
83 gobject_class->get_property = get_property;
85 entity_class->arrange = arrange;
86 entity_class->render = render;
88 marker_class->create_model = create_model;
90 param = g_param_spec_double("angle",
91 P_("Arrow Angle"),
92 P_("The opening angle of the arrow"),
93 0, G_PI*2, G_PI/6,
94 G_PARAM_READWRITE);
95 g_object_class_install_property(gobject_class, PROP_ANGLE, param);
98 static void
99 adg_arrow_init(AdgArrow *arrow)
101 AdgArrowPrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(arrow,
102 ADG_TYPE_ARROW,
103 AdgArrowPrivate);
105 data->angle = G_PI/6;
107 arrow->data = data;
110 static void
111 get_property(GObject *object,
112 guint prop_id, GValue *value, GParamSpec *pspec)
114 AdgArrowPrivate *data = ((AdgArrow *) object)->data;
116 switch (prop_id) {
117 case PROP_ANGLE:
118 g_value_set_double(value, data->angle);
119 break;
120 default:
121 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
122 break;
126 static void
127 set_property(GObject *object,
128 guint prop_id, const GValue *value, GParamSpec *pspec)
130 AdgArrow *arrow = (AdgArrow *) object;
132 switch (prop_id) {
133 case PROP_ANGLE:
134 set_angle(arrow, g_value_get_double(value));
135 break;
136 default:
137 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
138 break;
144 * adg_arrow_new:
145 * @trail: the #AdgTrail to arrow
147 * Creates a new undefined arrow entity. The position must be defined
148 * by setting the #AdgMarker:trail and #AdgMarker:pos properties.
150 * Returns: the newly created arrow entity
152 AdgArrow *
153 adg_arrow_new(void)
155 return g_object_new(ADG_TYPE_ARROW, 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 @trail at position @pos, where @pos is
164 * a ratio of the @trail length (%0 is the start point, %1 the end
165 * point, %0.5 the middle point and so on).
167 * Returns: the newly created arrow entity
169 AdgArrow *
170 adg_arrow_new_with_trail(AdgTrail *trail, gdouble pos)
172 return g_object_new(ADG_TYPE_ARROW,
173 "trail", trail,
174 "pos", pos,
175 NULL);
179 * adg_arrow_set_angle:
180 * @arrow: an #AdgArrow
181 * @angle: the new angle
183 * Sets a new angle: @angle will be the new opening angle of @arrow.
184 * Changing the arrow angle will invalidate @arrow.
186 void
187 adg_arrow_set_angle(AdgArrow *arrow, gdouble angle)
189 g_return_if_fail(ADG_IS_ARROW(arrow));
191 if (set_angle(arrow, angle))
192 g_object_notify((GObject *) arrow, "angle");
196 * adg_arrow_get_angle:
197 * @arrow: an #AdgArrow
199 * Gets the current angle of @arrow.
201 * Returns: the arrow angle, in radians
203 gdouble
204 adg_arrow_get_angle(AdgArrow *arrow)
206 AdgArrowPrivate *data;
208 g_return_val_if_fail(ADG_IS_ARROW(arrow), 0);
210 data = arrow->data;
212 return data->angle;
216 static void
217 arrange(AdgEntity *entity)
219 /* TODO */
222 static void
223 render(AdgEntity *entity, cairo_t *cr)
225 AdgModel *model;
226 const cairo_path_t *cairo_path;
228 model = adg_marker_model((AdgMarker *) entity);
229 cairo_path = adg_trail_get_cairo_path((AdgTrail *) model);
231 if (cairo_path != NULL) {
232 cairo_save(cr);
233 cairo_transform(cr, adg_entity_get_local_matrix(entity));
234 cairo_append_path(cr, cairo_path);
235 cairo_restore(cr);
237 cairo_fill(cr);
241 static AdgModel *
242 create_model(AdgMarker *marker)
244 AdgArrowPrivate *data;
245 AdgPath *path;
246 CpmlPair p1, p2;
248 data = ((AdgArrow *) marker)->data;
249 path = adg_path_new();
250 cpml_vector_from_angle(&p1, data->angle / 2);
251 p2.x = p1.x;
252 p2.y = -p1.y;
254 adg_path_move_to_explicit(path, 0, 0);
255 adg_path_line_to(path, &p1);
256 adg_path_line_to(path, &p2);
257 adg_path_close(path);
259 return (AdgModel *) path;
262 static gboolean
263 set_angle(AdgArrow *arrow, gdouble angle)
265 AdgArrowPrivate *data = arrow->data;
267 if (angle == data->angle)
268 return FALSE;
270 data->angle = angle;
271 adg_entity_invalidate((AdgEntity *) arrow);
273 return TRUE;