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.
22 * SECTION:adg-alignment
23 * @short_description: Base class for entity that can contain other entities
25 * The #AdgAlignment is an entity that can contains more sub-entities.
26 * Moreover, it can apply a common transformation to local and/or global
27 * maps: see http://adg.entidi.com/tutorial/view/3 for further details.
33 * All fields are private and should not be used directly.
34 * Use its public methods instead.
37 #include "adg-alignment.h"
38 #include "adg-alignment-private.h"
39 #include "adg-entity-private.h"
42 #define PARENT_ENTITY_CLASS ((AdgEntityClass *) adg_alignment_parent_class)
51 static void get_property (GObject
*object
,
55 static void set_property (GObject
*object
,
59 static void global_changed (AdgEntity
*entity
);
60 static void arrange (AdgEntity
*entity
);
61 static gboolean
set_factor (AdgAlignment
*alignment
,
62 const AdgPair
*factor
);
65 G_DEFINE_TYPE(AdgAlignment
, adg_alignment
, ADG_TYPE_CONTAINER
);
69 adg_alignment_class_init(AdgAlignmentClass
*klass
)
71 GObjectClass
*gobject_class
;
72 AdgEntityClass
*entity_class
;
75 gobject_class
= (GObjectClass
*) klass
;
76 entity_class
= (AdgEntityClass
*) klass
;
78 g_type_class_add_private(klass
, sizeof(AdgAlignmentPrivate
));
80 gobject_class
->get_property
= get_property
;
81 gobject_class
->set_property
= set_property
;
83 entity_class
->global_changed
= global_changed
;
84 entity_class
->arrange
= arrange
;
86 param
= g_param_spec_boxed("factor",
88 P_("Portion of extents, either in x and y, the content will be displaced: a (0.5, 0.5) factor means the origin is the middle point of the extents"),
91 g_object_class_install_property(gobject_class
, PROP_FACTOR
, param
);
95 adg_alignment_init(AdgAlignment
*alignment
)
97 AdgAlignmentPrivate
*data
= G_TYPE_INSTANCE_GET_PRIVATE(alignment
,
104 alignment
->data
= data
;
108 get_property(GObject
*object
, guint prop_id
, GValue
*value
, GParamSpec
*pspec
)
110 AdgAlignmentPrivate
*data
= ((AdgAlignment
*) object
)->data
;
114 g_value_set_boxed(value
, &data
->factor
);
117 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
123 set_property(GObject
*object
,
124 guint prop_id
, const GValue
*value
, GParamSpec
*pspec
)
126 AdgAlignment
*alignment
= (AdgAlignment
*) object
;
130 set_factor(alignment
, g_value_get_boxed(value
));
133 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
140 * @factor: the alignment factor
142 * Creates a new alignment container with the specified factor.
144 * Returns: the newly created alignment
147 adg_alignment_new(const AdgPair
*factor
)
149 return g_object_new(ADG_TYPE_ALIGNMENT
, "factor", factor
, NULL
);
153 * adg_alignment_new_explicit:
154 * @x_factor: x component of the factor
155 * @y_factor: y component of the factor
157 * Convenient function that creates a new alignment accepting explicit
160 * Returns: the newly created alignment
163 adg_alignment_new_explicit(gdouble x_factor
, gdouble y_factor
)
170 return adg_alignment_new(&factor
);
174 * adg_alignment_get_factor:
175 * @alignment: an #AdgAlignment container
177 * Gets the value of the #AdgAlignment:factor property. The returned
178 * pair is owned by @alignment and must not be modified or freed.
180 * Returns: the factor pair
183 adg_alignment_get_factor(AdgAlignment
*alignment
)
185 AdgAlignmentPrivate
*data
;
187 g_return_val_if_fail(ADG_IS_ALIGNMENT(alignment
), NULL
);
189 data
= alignment
->data
;
191 return &data
->factor
;
195 * adg_alignment_set_factor:
196 * @alignment: an #AdgAlignment container
197 * @factor: the new factor
199 * Sets a the #AdgAlignment:factor property to @factor on @alignment.
200 * The factor is applied to the @alignment extents to compute the
201 * displacement of the content, providing a way to for instance center
202 * the content either vertically or horizontally. A pair factor of
203 * (%0.5, %0) means the content will be centered horizontally in
204 * reference to the normal flow without @alignment.
207 adg_alignment_set_factor(AdgAlignment
*alignment
, const AdgPair
*factor
)
209 g_return_if_fail(ADG_IS_ALIGNMENT(alignment
));
210 g_return_if_fail(factor
!= NULL
);
212 if (set_factor(alignment
, factor
))
213 g_object_notify((GObject
*) alignment
, "factor");
217 * adg_alignment_set_factor_explicit:
218 * @alignment: an #AdgAlignment container
219 * @x_factor: x component of the factor
220 * @y_factor: y component of the factor
222 * Convenient wrapper around adg_alignment_set_factor() that accepts
223 * explicit factors instead of an #AdgPair value.
226 adg_alignment_set_factor_explicit(AdgAlignment
*alignment
,
227 gdouble x_factor
, gdouble y_factor
)
234 adg_alignment_set_factor(alignment
, &factor
);
239 global_changed(AdgEntity
*entity
)
241 AdgEntityClass
*entity_class
;
242 AdgEntityPrivate
*entity_data
;
243 CpmlExtents
*extents
;
247 entity_class
= g_type_class_ref(ADG_TYPE_ENTITY
);
248 entity_data
= entity
->data
;
249 extents
= &entity_data
->extents
;
250 global
= &entity_data
->global_matrix
;
252 if (extents
->is_defined
) {
253 /* The entities are displaced only if the extents are valid */
254 AdgAlignmentPrivate
*data
= ((AdgAlignment
*) entity
)->data
;
256 cpml_pair_copy(&shift
, &extents
->size
);
257 cpml_pair_mul(&shift
, &data
->factor
);
259 cpml_pair_sub(&extents
->org
, &shift
);
265 if (entity_class
->global_changed
!= NULL
)
266 entity_class
->global_changed(entity
);
268 g_type_class_unref(entity_class
);
270 /* The real job: temporarily modify the global matrix
271 * to align the contained entities */
272 global
->x0
-= shift
.x
;
273 global
->y0
-= shift
.y
;
275 adg_container_propagate_by_name((AdgContainer
*) entity
, "global-changed");
277 global
->x0
+= shift
.x
;
278 global
->y0
+= shift
.y
;
282 arrange(AdgEntity
*entity
)
284 PARENT_ENTITY_CLASS
->arrange(entity
);
286 /* Force a recomputation of the children position */
287 adg_entity_global_changed(entity
);
291 set_factor(AdgAlignment
*alignment
, const AdgPair
*factor
)
293 AdgAlignmentPrivate
*data
= alignment
->data
;
295 if (adg_pair_equal(&data
->factor
, factor
))
298 data
->factor
= *factor
;