[AdgEntity] Emits "{global,local}-changed" on parent changed
[adg.git] / adg / adg-point.c
blobadef5129e75eddbed7e821a35b30dcb491a5fb38
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 pair, thus enabling coordinates depending
33 * on #AdgModel instances.
34 **/
36 /**
37 * AdgPoint:
39 * This is an opaque struct: all its fields are privates.
40 **/
43 #include "adg-point.h"
44 #include "adg-intl.h"
46 #include <string.h>
49 struct _AdgPoint {
50 AdgPair pair;
51 AdgModel *model;
52 gchar *name;
53 gboolean is_uptodate;
56 GType
57 adg_point_get_type(void)
59 static int type = 0;
61 if (G_UNLIKELY(type == 0))
62 type = g_boxed_type_register_static("AdgPoint",
63 (GBoxedCopyFunc) adg_point_dup,
64 (GBoxedFreeFunc) adg_point_destroy);
66 return type;
69 /**
70 * adg_point_copy:
71 * @point: an #AdgPoint
72 * @src: the source point to copy
74 * Copies @src into @point. If @point was linked to a named pair, the
75 * reference to the old model is dropped. Similary, if @src is linked
76 * to a model, a new reference to this new model is added.
78 * Returns: @point
79 **/
80 AdgPoint *
81 adg_point_copy(AdgPoint *point, const AdgPoint *src)
83 g_return_val_if_fail(point != NULL, NULL);
84 g_return_val_if_fail(src != NULL, NULL);
86 if (src->model != NULL)
87 g_object_ref(src->model);
89 if (point->model != NULL)
90 g_object_unref(point->model);
92 return memcpy(point, src, sizeof(AdgPoint));
95 /**
96 * adg_point_dup:
97 * @point: an #AdgPoint structure
99 * Duplicates @point. This operation also adds a new reference
100 * to the internal model if @point is linked to a named pair.
102 * Returns: the duplicated #AdgPoint struct or %NULL on errors
104 AdgPoint *
105 adg_point_dup(const AdgPoint *point)
107 g_return_val_if_fail(point != NULL, NULL);
109 if (point->model != NULL)
110 g_object_ref(point->model);
112 return g_memdup(point, sizeof(AdgPoint));
116 * adg_point_new:
118 * Creates a new empty #AdgPoint. The returned pointer
119 * should be freed with adg_point_destroy() when no longer needed.
121 * Returns: a newly created #AdgPoint
123 AdgPoint *
124 adg_point_new(void)
126 return g_new0(AdgPoint, 1);
130 * adg_point_destroy:
131 * @point: an #AdgPoint
133 * Destroys the @point instance, unreferencing the internal model if
134 * @point is linked to a named pair.
136 void
137 adg_point_destroy(AdgPoint *point)
139 g_return_if_fail(point != NULL);
141 adg_point_set_from_model(point, NULL, NULL);
143 g_free(point);
147 * adg_point_pair:
148 * @point: an #AdgPoint
150 * #AdgPoint is an evolution of the pair concept, but internally the
151 * relevant data is still stored in an #AdgPair struct. This function
152 * gets this struct, optionally updating the internal value from the
153 * linked named pair if necessary.
155 * Returns: the pair of @point
157 const AdgPair *
158 adg_point_pair(AdgPoint *point)
160 if (!point->is_uptodate) {
161 const AdgPair *pair;
163 if (point->model == NULL) {
164 /* A point with explicit coordinates not up to date
165 * is an unexpected condition */
166 g_warning(_("%s: trying to get a pair from an undefined point"),
167 G_STRLOC);
168 return NULL;
171 pair = adg_model_named_pair(point->model, point->name);
173 if (pair == NULL) {
174 g_warning(_("%s: `%s' named pair not found in `%s' model instance"),
175 G_STRLOC, point->name,
176 g_type_name(G_TYPE_FROM_INSTANCE(point->model)));
177 return NULL;
180 cpml_pair_copy(&point->pair, pair);
183 return (AdgPair *) point;
187 * adg_point_set:
188 * @point: an #AdgPoint
189 * @pair: the #AdgPair to use
191 * Sets an explicit pair in @point by using the given @pair. If
192 * @point was linked to a named pair in a model, this link is
193 * dropped before setting the pair.
195 void
196 adg_point_set(AdgPoint *point, const AdgPair *pair)
198 g_return_if_fail(point != NULL);
199 g_return_if_fail(pair != NULL);
201 adg_point_set_explicit(point, pair->x, pair->y);
205 * adg_point_set_explicit:
206 * @point: an #AdgPoint
207 * @x: the x coordinate of the point
208 * @y: the y coordinate of the point
210 * Works in the same way of adg_point_set() but accept direct numbers
211 * instead of an #AdgPair structure.
213 void
214 adg_point_set_explicit(AdgPoint *point, gdouble x, gdouble y)
216 g_return_if_fail(point != NULL);
218 /* Unlink the named pair dependency, if any */
219 adg_point_set_from_model(point, NULL, NULL);
221 point->pair.x = x;
222 point->pair.y = y;
223 point->is_uptodate = TRUE;
227 * adg_point_set_from_model:
228 * @point: an #AdgPoint
229 * @model: the #AdgModel
230 * @name: the id of a named pair in @model
232 * Links the @name named pair of @model to @point, so any subsequent
233 * call to adg_point_update() will read the named pair content. A
234 * new reference is added to @model while the previous model (if any)
235 * is unreferenced.
237 * It is allowed to use %NULL as @model, in which case the link
238 * between @point and the named pair is dropped.
240 void
241 adg_point_set_from_model(AdgPoint *point, AdgModel *model, const gchar *name)
243 g_return_if_fail(point != NULL);
245 /* Check if unlinking a yet unlinked point */
246 if (model == NULL && point->model == NULL)
247 return;
249 /* Ensure the name is not NULL if the model is specified */
250 if (model != NULL) {
251 g_return_if_fail(name != NULL);
254 /* Check if the named pair is different from the old one */
255 if (model == point->model && strcmp(point->name, name) == 0)
256 return;
258 if (model != NULL)
259 g_object_ref(model);
261 if (point->model != NULL) {
262 /* Remove the old named pair */
263 g_object_unref(point->model);
264 g_free(point->name);
265 point->model = NULL;
266 point->name = NULL;
269 point->is_uptodate = FALSE;
271 if (model != NULL) {
272 /* Set the new named pair */
273 point->model = model;
274 point->name = g_strdup(name);
279 * adg_point_invalidate:
280 * @point: an #AdgPoint
282 * Invalidates @point, forcing a refresh of its internal #AdgPair if
283 * the point is linked to a named pair. If @point is explicitely set,
284 * this function has no effect.
286 void
287 adg_point_invalidate(AdgPoint *point)
289 g_return_if_fail(point != NULL);
291 if (point->model != NULL)
292 point->is_uptodate = FALSE;