s/2008,2009/2008,2009,2010/
[adg.git] / adg / adg-point.c
blob02ab21e3a64f4e9b1fb56bd63ae2462f36479d1e
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-point
23 * @Section_Id:AdgPoint
24 * @title: AdgPoint
25 * @short_description: A struct holding x, y coordinates
26 * (either named or explicit)
28 * AdgPoint is an opaque structure that manages 2D coordinates,
29 * either set explicitely throught adg_point_set_pair() and
30 * adg_point_set_pair_explicit() or taken from a model with
31 * adg_point_set_pair_from_model(). It can be thought as an
32 * #AdgPair on steroid, because it adds named pair support to
33 * a simple pair, enabling coordinates depending on #AdgModel.
34 **/
36 /**
37 * AdgPoint:
39 * This is an opaque struct: all its fields are privates.
40 **/
43 #include "adg-internal.h"
44 #include "adg-point.h"
45 #include <string.h>
48 struct _AdgPoint {
49 AdgPair pair;
50 AdgModel *model;
51 gchar *name;
52 gboolean is_uptodate;
55 GType
56 adg_point_get_type(void)
58 static int type = 0;
60 if (G_UNLIKELY(type == 0))
61 type = g_boxed_type_register_static("AdgPoint",
62 (GBoxedCopyFunc) adg_point_dup,
63 (GBoxedFreeFunc) adg_point_destroy);
65 return type;
68 /**
69 * adg_point_dup:
70 * @point: an #AdgPoint structure
72 * Duplicates @point. This operation also adds a new reference
73 * to the internal model if @point is linked to a named pair.
75 * The returned value should be freed with adg_point_destroy()
76 * when no longer needed.
78 * Returns: the duplicated #AdgPoint struct or %NULL on errors
79 **/
80 AdgPoint *
81 adg_point_dup(const AdgPoint *point)
83 g_return_val_if_fail(point != NULL, NULL);
85 if (point->model != NULL)
86 g_object_ref(point->model);
88 return g_memdup(point, sizeof(AdgPoint));
91 /**
92 * adg_point_new:
94 * Creates a new empty #AdgPoint. The returned pointer
95 * should be freed with adg_point_destroy() when no longer needed.
97 * The returned value should be freed with adg_point_destroy()
98 * when no longer needed.
100 * Returns: a newly created #AdgPoint
102 AdgPoint *
103 adg_point_new(void)
105 return g_new0(AdgPoint, 1);
109 * adg_point_destroy:
110 * @point: an #AdgPoint
112 * Destroys the @point instance, unreferencing the internal model if
113 * @point is linked to a named pair.
115 void
116 adg_point_destroy(AdgPoint *point)
118 g_return_if_fail(point != NULL);
120 adg_point_set_pair_from_model(point, NULL, NULL);
122 g_free(point);
126 * adg_point_copy:
127 * @point: an #AdgPoint
128 * @src: the source point to copy
130 * Copies @src into @point. If @point was linked to a named pair, the
131 * reference to the old model is dropped. Similary, if @src is linked
132 * to a model, a new reference to this new model is added.
134 void
135 adg_point_copy(AdgPoint *point, const AdgPoint *src)
137 g_return_if_fail(point != NULL);
138 g_return_if_fail(src != NULL);
140 if (src->model != NULL)
141 g_object_ref(src->model);
143 if (point->model != NULL)
144 g_object_unref(point->model);
146 memcpy(point, src, sizeof(AdgPoint));
150 * adg_point_set_pair:
151 * @point: an #AdgPoint
152 * @pair: the #AdgPair to use
154 * Sets an explicit pair in @point by using the given @pair. If
155 * @point was linked to a named pair in a model, this link is
156 * dropped before setting the pair.
158 void
159 adg_point_set_pair(AdgPoint *point, const AdgPair *pair)
161 g_return_if_fail(point != NULL);
162 g_return_if_fail(pair != NULL);
164 adg_point_set_pair_explicit(point, pair->x, pair->y);
168 * adg_point_set_pair_explicit:
169 * @point: an #AdgPoint
170 * @x: the x coordinate of the point
171 * @y: the y coordinate of the point
173 * Works in the same way of adg_point_set_pair() but accept direct numbers
174 * instead of an #AdgPair structure.
176 void
177 adg_point_set_pair_explicit(AdgPoint *point, gdouble x, gdouble y)
179 g_return_if_fail(point != NULL);
181 /* Unlink the named pair dependency, if any */
182 adg_point_set_pair_from_model(point, NULL, NULL);
184 point->pair.x = x;
185 point->pair.y = y;
186 point->is_uptodate = TRUE;
190 * adg_point_set_pair_from_model:
191 * @point: an #AdgPoint
192 * @model: the #AdgModel
193 * @name: the id of a named pair in @model
195 * Links the @name named pair of @model to @point, so any subsequent
196 * call to adg_point_update() will read the named pair content. A
197 * new reference is added to @model while the previous model (if any)
198 * is unreferenced.
200 * It is allowed to use %NULL as @model, in which case the link
201 * between @point and the named pair is dropped.
203 void
204 adg_point_set_pair_from_model(AdgPoint *point,
205 AdgModel *model, const gchar *name)
207 g_return_if_fail(point != NULL);
208 g_return_if_fail(model == NULL || name != NULL);
210 /* Check if unlinking a yet unlinked point */
211 if (model == NULL && point->model == NULL)
212 return;
214 /* Return if the named pair is not changed */
215 if (model == point->model &&
216 (model == NULL || strcmp(point->name, name) == 0)) {
217 return;
220 if (model != NULL)
221 g_object_ref(model);
223 if (point->model != NULL) {
224 /* Remove the old named pair */
225 g_object_unref(point->model);
226 g_free(point->name);
227 point->model = NULL;
228 point->name = NULL;
231 point->is_uptodate = FALSE;
233 if (model != NULL) {
234 /* Set the new named pair */
235 point->model = model;
236 point->name = g_strdup(name);
241 * adg_point_get_pair:
242 * @point: an #AdgPoint
244 * #AdgPoint is an evolution of the pair concept, but internally the
245 * relevant data is still stored in an #AdgPair struct. This function
246 * gets this struct, optionally updating the internal value from the
247 * linked named pair if necessary.
249 * Returns: the pair of @point
251 const AdgPair *
252 adg_point_get_pair(AdgPoint *point)
254 g_return_val_if_fail(point != NULL, NULL);
256 if (!point->is_uptodate) {
257 const AdgPair *pair;
259 if (point->model == NULL) {
260 /* A point with explicit coordinates not up to date
261 * is an unexpected condition */
262 g_warning(_("%s: trying to get a pair from an undefined point"),
263 G_STRLOC);
264 return NULL;
267 pair = adg_model_get_named_pair(point->model, point->name);
269 if (pair == NULL) {
270 g_warning(_("%s: `%s' named pair not found in `%s' model instance"),
271 G_STRLOC, point->name,
272 g_type_name(G_TYPE_FROM_INSTANCE(point->model)));
273 return NULL;
276 cpml_pair_copy(&point->pair, pair);
279 return (AdgPair *) point;
283 * adg_point_invalidate:
284 * @point: an #AdgPoint
286 * Invalidates @point, forcing a refresh of its internal #AdgPair if
287 * the point is linked to a named pair. If @point is explicitely set,
288 * this function has no effect.
290 void
291 adg_point_invalidate(AdgPoint *point)
293 g_return_if_fail(point != NULL);
295 if (point->model != NULL)
296 point->is_uptodate = FALSE;