[AdgPoint] First implementation
[adg.git] / adg / adg-point.c
blobbe24f7fb339e372019a8f5076769f93f364274df
1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007,2008,2009 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, either
29 * set explicitely throught adg_point_set() and adg_point_set_explicit()
30 * or taken from a model with adg_point_set_from_model(). It can be
31 * thought as an #AdgPair on steroid, because it adds named pair
32 * support to a simple pairs, and thus enabling coordinates depending
33 * on #AdgModel instances.
34 **/
36 /**
37 * ADG_POINT_PAIR:
38 * @point: an #AdgPoint
40 * #AdgPoint is an evolution of the pair concept, but internally the
41 * relevant data is still kept by an #AdgPair struct. This macro
42 * gets this struct. Being declared at the start of the #AdgPoint
43 * struct, it'd suffice to cast the point to an #AdgPair too.
45 * Returns: the pair of @point
46 **/
48 /**
49 * AdgPoint:
51 * This is an opaque struct: all its fields are privates.
52 **/
55 #include "adg-point.h"
57 #include <string.h>
60 struct _AdgPoint {
61 AdgPair pair;
62 AdgModel *model;
63 gchar *name;
66 GType
67 adg_point_get_type(void)
69 static int type = 0;
71 if (G_UNLIKELY(type == 0))
72 type = g_boxed_type_register_static("AdgPoint",
73 (GBoxedCopyFunc) adg_point_dup,
74 (GBoxedFreeFunc) adg_point_destroy);
76 return type;
79 /**
80 * adg_point_copy:
81 * @point: an #AdgPoint
82 * @src: the source point to copy
84 * Copies @src into @point.
86 * Returns: @point
87 **/
88 AdgPoint *
89 adg_point_copy(AdgPoint *point, const AdgPoint *src)
91 g_return_val_if_fail(point != NULL, NULL);
92 g_return_val_if_fail(src != NULL, NULL);
94 if (src->model != NULL)
95 g_object_ref(src->model);
97 if (point->model != NULL)
98 g_object_unref(point->model);
100 return memcpy(point, src, sizeof(AdgPoint));
104 * adg_point_dup:
105 * @point: an #AdgPoint structure
107 * Duplicates @point.
109 * Returns: the duplicated #AdgPoint struct or %NULL on errors
111 AdgPoint *
112 adg_point_dup(const AdgPoint *point)
114 g_return_val_if_fail(point != NULL, NULL);
116 if (point->model != NULL)
117 g_object_ref(point->model);
119 return g_memdup(point, sizeof(AdgPoint));
123 * adg_point_new:
125 * Creates a new empty #AdgPoint. The returned pointer
126 * should be freed with adg_point_destroy() when no longer needed.
128 * Returns: a newly created #AdgPoint
130 AdgPoint *
131 adg_point_new(void)
133 return g_new0(AdgPoint, 1);
137 * adg_point_destroy:
138 * @point: an #AdgPoint
140 * Destroys the @point instance, unreferencing the internal model if
141 * @point is linked to a named pair.
143 void
144 adg_point_destroy(AdgPoint *point)
146 g_return_if_fail(point != NULL);
148 adg_point_set_from_model(point, NULL, NULL);
150 g_free(point);
154 * adg_point_set:
155 * @point: an #AdgPoint
156 * @pair: the #AdgPair to use
158 * Sets an explicit pair in @point by using the given @pair. If
159 * @point was linked to a named pair in a model, this link is
160 * dropped before setting the pair.
162 void
163 adg_point_set(AdgPoint *point, const AdgPair *pair)
165 g_return_if_fail(point != NULL);
166 g_return_if_fail(pair != NULL);
168 adg_point_set_explicit(point, pair->x, pair->y);
172 * adg_point_set_explicit:
173 * @point: an #AdgPoint
174 * @x: the x coordinate of the point
175 * @y: the y coordinate of the point
177 * Works in the same way of adg_point_set() but accept direct numbers
178 * instead of an #AdgPair structure.
180 void
181 adg_point_set_explicit(AdgPoint *point, gdouble x, gdouble y)
183 g_return_if_fail(point != NULL);
185 /* Unlink the named pair dependency, if any */
186 adg_point_set_from_model(point, NULL, NULL);
188 point->pair.x = x;
189 point->pair.y = y;
193 * adg_point_set_from_model:
194 * @point: an #AdgPair
195 * @model: the #AdgModel
196 * @name: the id of a named pair in @model
198 * Links the @name named pair of @model to @point, so any subsequent
199 * call to adg_point_update() will read the named pair content. A
200 * new reference is added to @model while the previous model (if any)
201 * is unreferenced.
203 * It is allowed to use %NULL as @model, in which case the link
204 * between @point and the named pair is dropped.
206 void
207 adg_point_set_from_model(AdgPoint *point, AdgModel *model, const gchar *name)
209 g_return_if_fail(point != NULL);
211 /* Check if unlinking a yet unlinked point */
212 if (model == NULL && point->model == NULL)
213 return;
215 /* Ensure the name is not NULL if the model is specified */
216 if (model != NULL) {
217 g_return_if_fail(name != NULL);
220 /* Check if the named pair is different from the old one */
221 if (model == point->model && strcmp(point->name, name) == 0)
222 return;
224 if (model != NULL)
225 g_object_ref(model);
227 if (point->model != NULL) {
228 /* Remove the old named pair */
229 g_object_unref(point->model);
230 g_free(point->name);
231 point->model = NULL;
232 point->name = NULL;
235 if (model != NULL) {
236 /* Set the new named pair */
237 point->model = model;
238 point->name = g_strdup(name);
241 adg_point_update(point);
245 * adg_point_update:
246 * @point: an #AdgPoint
248 * Updates the pair of @point. If @point is an explicit pair (either
249 * if set with adg_point_set() or adg_point_set_explicit()), no action
250 * is taken. If @point is linked to a named pair, instead, the internal
251 * pair is updated with the value returned by adg_model_get_named_pair().
253 void
254 adg_point_update(AdgPoint *point)
256 const AdgPair *pair;
258 g_return_if_fail(point != NULL);
260 /* A point with explicit coordinates does not need to be updated */
261 if (point->model == NULL)
262 return;
264 pair = adg_model_get_named_pair(point->model, point->name);
266 cpml_pair_copy(&point->pair, pair);