1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007,2008,2009,2010,2011,2012,2013 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.
23 * @Section_Id: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 * #CpmlPair on steroid, because it adds named pair support to
33 * a simple pair, enabling coordinates depending on #AdgModel.
41 * This is an opaque struct: all its fields are privates.
47 #include "adg-internal.h"
48 #include "adg-model.h"
51 #include "adg-point.h"
63 adg_point_get_type(void)
65 static GType type
= 0;
67 if (G_UNLIKELY(type
== 0))
68 type
= g_boxed_type_register_static("AdgPoint",
69 (GBoxedCopyFunc
) adg_point_dup
,
70 (GBoxedFreeFunc
) adg_point_destroy
);
78 * Creates a new empty #AdgPoint. The returned pointer
79 * should be freed with adg_point_destroy() when no longer needed.
81 * Returns: a newly created #AdgPoint
88 return g_new0(AdgPoint
, 1);
95 * Duplicates @src. This operation also adds a new reference
96 * to the internal model if @src is linked to a named pair.
98 * The returned value should be freed with adg_point_destroy()
99 * when no longer needed.
101 * Returns: the duplicated #AdgPoint struct or %NULL on errors
106 adg_point_dup(const AdgPoint
*src
)
110 g_return_val_if_fail(src
!= NULL
, NULL
);
113 g_object_ref(src
->model
);
115 point
= g_memdup(src
, sizeof(AdgPoint
));
116 point
->name
= g_strdup(src
->name
);
123 * @point: an #AdgPoint
125 * Destroys the @point instance, unreferencing the internal model if
126 * @point is linked to a named pair.
131 adg_point_destroy(AdgPoint
*point
)
133 g_return_if_fail(point
!= NULL
);
135 adg_point_unset(point
);
141 * @point: an #AdgPoint
142 * @src: the source point to copy
144 * Copies @src into @point. If the old content of @point was linked
145 * to the named pair of a model, the reference to that model is
146 * dropped. Similary, if @src is a named pair, a new reference to
147 * the new model is added.
152 adg_point_copy(AdgPoint
*point
, const AdgPoint
*src
)
154 g_return_if_fail(point
!= NULL
);
155 g_return_if_fail(src
!= NULL
);
157 if (src
->model
!= NULL
)
158 g_object_ref(src
->model
);
160 if (point
->model
!= NULL
)
161 g_object_unref(point
->model
);
163 if (point
->name
!= NULL
)
166 memcpy(point
, src
, sizeof(AdgPoint
));
167 point
->name
= g_strdup(src
->name
);
171 * adg_point_set_pair:
172 * @point: an #AdgPoint
173 * @pair: the #CpmlPair to use
175 * Sets an explicit pair in @point by using the given @pair. If
176 * @point was linked to a named pair in a model, this link is
177 * dropped before setting the pair.
182 adg_point_set_pair(AdgPoint
*point
, const CpmlPair
*pair
)
184 g_return_if_fail(point
!= NULL
);
185 g_return_if_fail(pair
!= NULL
);
187 adg_point_set_pair_explicit(point
, pair
->x
, pair
->y
);
191 * adg_point_set_pair_explicit:
192 * @point: an #AdgPoint
193 * @x: the x coordinate of the point
194 * @y: the y coordinate of the point
196 * Works in the same way of adg_point_set_pair() but accept direct numbers
197 * instead of an #CpmlPair structure.
202 adg_point_set_pair_explicit(AdgPoint
*point
, gdouble x
, gdouble y
)
204 g_return_if_fail(point
!= NULL
);
206 adg_point_unset(point
);
209 point
->up_to_date
= TRUE
;
213 * adg_point_set_pair_from_model:
214 * @point: an #AdgPoint
215 * @model: the #AdgModel
216 * @name: the id of a named pair in @model
218 * Links the @name named pair of @model to @point, so any subsequent
219 * call to adg_point_get_pair() will return the named pair value.
220 * A new reference is added to @model while the previous model (if any)
226 adg_point_set_pair_from_model(AdgPoint
*point
,
227 AdgModel
*model
, const gchar
*name
)
229 g_return_if_fail(point
!= NULL
);
230 g_return_if_fail(ADG_IS_MODEL(model
));
231 g_return_if_fail(name
!= NULL
);
233 /* Return if the new named pair is the same of the old one */
234 if (model
== point
->model
&& strcmp(point
->name
, name
) == 0)
240 /* Remove the old named pair */
241 g_object_unref(point
->model
);
245 /* Set the new named pair */
246 point
->up_to_date
= FALSE
;
247 point
->model
= model
;
248 point
->name
= g_strdup(name
);
252 * adg_point_invalidate:
253 * @point: an #AdgPoint
255 * Invalidates @point, forcing a refresh of its internal #CpmlPair if
256 * the point is linked to a named pair. If @point is explicitely set,
257 * this function has no effect.
262 adg_point_invalidate(AdgPoint
*point
)
264 g_return_if_fail(point
!= NULL
);
266 if (point
->model
!= NULL
)
267 point
->up_to_date
= FALSE
;
272 * @point: a pointer to an #AdgPoint
274 * Unsets @point by resetting the internal %up_to_date flag and
275 * (eventually) unlinking it from the named pair it is bound to.
276 * After this call the content of @point is undefined, so a
277 * subsequent call to adg_point_get_pair() will return %NULL
283 adg_point_unset(AdgPoint
*point
)
285 g_return_if_fail(point
!= NULL
);
288 /* Remove the old named pair */
289 g_object_unref(point
->model
);
293 point
->up_to_date
= FALSE
;
300 * @point: a pointer to an #AdgPoint
302 * Updates the internal #CpmlPair of @point. The internal
303 * implementation is protected against multiple calls so it
304 * can be called more times without harms.
306 * Returns: %TRUE if @point has been updated or %FALSE on errors,
307 * i.e. when it is bound to a non-existent named pair.
312 adg_point_update(AdgPoint
*point
)
315 const CpmlPair
*pair
;
317 g_return_val_if_fail(point
!= NULL
, FALSE
);
319 if (point
->up_to_date
)
322 model
= point
->model
;
324 /* A point with explicit coordinates not up to date
325 * is an unexpected condition */
326 g_warning(_("%s: trying to get a pair from an undefined point"),
331 pair
= adg_model_get_named_pair(model
, point
->name
);
335 cpml_pair_copy(&point
->pair
, pair
);
336 point
->up_to_date
= TRUE
;
341 * adg_point_get_pair:
342 * @point: an #AdgPoint
344 * #AdgPoint is an evolution of the pair concept but internally the
345 * relevant data is still stored in an #CpmlPair struct. This function
346 * returns a copy of the internally owned pair.
349 * The #CpmlPair is the first field of an #AdgPoint struct so casting
350 * is allowed between them and, in fact, it is often more convenient
351 * than calling this function. Just remember to update the internal
352 * pair by using adg_point_update() before.
355 * Returns: (transfer full): the pair of @point or %NULL if the named pair does not exist
360 adg_point_get_pair(AdgPoint
*point
)
362 g_return_val_if_fail(point
!= NULL
, NULL
);
364 if (! adg_point_update(point
))
367 return cpml_pair_dup(& point
->pair
);
371 * adg_point_get_model:
372 * @point: an #AdgPoint
374 * Gets the source model of the named pair bound to @point, or
375 * returns %NULL if @point is an explicit pair. The returned
376 * value is owned by @point.
378 * Returns: (transfer none): an #AdgModel or %NULL.
383 adg_point_get_model(const AdgPoint
*point
)
385 g_return_val_if_fail(point
!= NULL
, NULL
);
390 * adg_point_get_name:
391 * @point: an #AdgPoint
393 * Gets the name of the named pair bound to @point, or returns
394 * %NULL if @point is an explicit pair. The returned value is
395 * owned by @point and should not be modified or freed.
397 * Returns: the name of the named pair or %NULL
402 adg_point_get_name(const AdgPoint
*point
)
404 g_return_val_if_fail(point
!= NULL
, NULL
);
410 * @point1: the first point to compare
411 * @point2: the second point to compare
413 * Compares @point1 and @point2 and returns %TRUE if the points are
414 * equals. The comparison is made by checking also the named pairs
415 * they are bound to. If you want to compare only their coordinates,
416 * use cpml_pair_equal() directly on the #AdgPoint structs:
419 * if (adg_point_update(point1) &&
420 * adg_point_update(point2) &&
421 * cpml_pair_equal((CpmlPair *) point1, (CpmlPair *) point2))
427 * %NULL points are handled gracefully.
429 * Returns: %TRUE if @point1 is equal to @point2, %FALSE otherwise
434 adg_point_equal(const AdgPoint
*point1
, const AdgPoint
*point2
)
436 if (point1
== point2
)
439 if (point1
== NULL
|| point2
== NULL
)
442 /* Check if the points are not bound to the same model
443 * or if only one of the two points is explicit */
444 if (point1
->model
!= point2
->model
)
447 /* Handle points bound to named pairs */
448 if (point1
->model
!= NULL
)
449 return g_strcmp0(point1
->name
, point2
->name
) == 0;
451 /* Handle points with explicit coordinates */
452 return cpml_pair_equal(&point1
->pair
, &point2
->pair
);