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 * much in the same way as the #AdgContainer does, but allowing the
27 * alignment of the content with an arbitrary fraction of the boundaring
28 * box of the content itsself.
30 * To specify the alignment fraction, use adg_alignment_set_factor() and
31 * related methods or directly set the #AdgAlignment:factor property.
32 * For example, to center the children either in x and y, you can call
33 * adg_alignment_set_factor_explicit(alignment, 0.5, 0.5). To align them
34 * on the right, specify a (0, 1) factor.
36 * The displacement is done by modifing the global matrix at the end of
43 * All fields are private and should not be used directly.
44 * Use its public methods instead.
47 #include "adg-alignment.h"
48 #include "adg-alignment-private.h"
51 #define PARENT_ENTITY_CLASS ((AdgEntityClass *) adg_alignment_parent_class)
59 static void get_property (GObject
*object
,
63 static void set_property (GObject
*object
,
67 static void arrange (AdgEntity
*entity
);
68 static gboolean
set_factor (AdgAlignment
*alignment
,
69 const AdgPair
*factor
);
72 G_DEFINE_TYPE(AdgAlignment
, adg_alignment
, ADG_TYPE_CONTAINER
);
76 adg_alignment_class_init(AdgAlignmentClass
*klass
)
78 GObjectClass
*gobject_class
;
79 AdgEntityClass
*entity_class
;
82 gobject_class
= (GObjectClass
*) klass
;
83 entity_class
= (AdgEntityClass
*) klass
;
85 g_type_class_add_private(klass
, sizeof(AdgAlignmentPrivate
));
87 gobject_class
->get_property
= get_property
;
88 gobject_class
->set_property
= set_property
;
90 entity_class
->arrange
= arrange
;
92 param
= g_param_spec_boxed("factor",
94 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"),
97 g_object_class_install_property(gobject_class
, PROP_FACTOR
, param
);
101 adg_alignment_init(AdgAlignment
*alignment
)
103 AdgAlignmentPrivate
*data
= G_TYPE_INSTANCE_GET_PRIVATE(alignment
,
105 AdgAlignmentPrivate
);
110 alignment
->data
= data
;
114 get_property(GObject
*object
, guint prop_id
, GValue
*value
, GParamSpec
*pspec
)
116 AdgAlignmentPrivate
*data
= ((AdgAlignment
*) object
)->data
;
120 g_value_set_boxed(value
, &data
->factor
);
123 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
129 set_property(GObject
*object
,
130 guint prop_id
, const GValue
*value
, GParamSpec
*pspec
)
132 AdgAlignment
*alignment
= (AdgAlignment
*) object
;
136 set_factor(alignment
, g_value_get_boxed(value
));
139 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
146 * @factor: the alignment factor
148 * Creates a new alignment container with the specified factor.
150 * Returns: the newly created alignment
153 adg_alignment_new(const AdgPair
*factor
)
155 return g_object_new(ADG_TYPE_ALIGNMENT
, "factor", factor
, NULL
);
159 * adg_alignment_new_explicit:
160 * @x_factor: x component of the factor
161 * @y_factor: y component of the factor
163 * Convenient function that creates a new alignment accepting explicit
166 * Returns: the newly created alignment
169 adg_alignment_new_explicit(gdouble x_factor
, gdouble y_factor
)
176 return adg_alignment_new(&factor
);
180 * adg_alignment_get_factor:
181 * @alignment: an #AdgAlignment container
183 * Gets the value of the #AdgAlignment:factor property. The returned
184 * pair is owned by @alignment and must not be modified or freed.
186 * Returns: the factor pair
189 adg_alignment_get_factor(AdgAlignment
*alignment
)
191 AdgAlignmentPrivate
*data
;
193 g_return_val_if_fail(ADG_IS_ALIGNMENT(alignment
), NULL
);
195 data
= alignment
->data
;
197 return &data
->factor
;
201 * adg_alignment_set_factor:
202 * @alignment: an #AdgAlignment container
203 * @factor: the new factor
205 * Sets a the #AdgAlignment:factor property to @factor on @alignment.
206 * The factor is applied to the @alignment extents to compute the
207 * displacement of the content, providing a way to for instance center
208 * the content either vertically or horizontally. A pair factor of
209 * (%0.5, %0) means the content will be centered horizontally in
210 * reference to the normal flow without @alignment.
213 adg_alignment_set_factor(AdgAlignment
*alignment
, const AdgPair
*factor
)
215 g_return_if_fail(ADG_IS_ALIGNMENT(alignment
));
216 g_return_if_fail(factor
!= NULL
);
218 if (set_factor(alignment
, factor
))
219 g_object_notify((GObject
*) alignment
, "factor");
223 * adg_alignment_set_factor_explicit:
224 * @alignment: an #AdgAlignment container
225 * @x_factor: x component of the factor
226 * @y_factor: y component of the factor
228 * Convenient wrapper around adg_alignment_set_factor() that accepts
229 * explicit factors instead of an #AdgPair value.
232 adg_alignment_set_factor_explicit(AdgAlignment
*alignment
,
233 gdouble x_factor
, gdouble y_factor
)
240 adg_alignment_set_factor(alignment
, &factor
);
245 arrange(AdgEntity
*entity
)
247 AdgAlignmentPrivate
*data
;
248 const CpmlExtents
*extents
;
251 if (PARENT_ENTITY_CLASS
->arrange
)
252 PARENT_ENTITY_CLASS
->arrange(entity
);
254 extents
= adg_entity_get_extents(entity
);
256 /* The children are displaced only if the extents are valid */
257 if (!extents
->is_defined
)
260 data
= ((AdgAlignment
*) entity
)->data
;
261 cairo_matrix_init_translate(&shift
,
262 -extents
->size
.x
* data
->factor
.x
,
263 -extents
->size
.y
* data
->factor
.y
);
265 /* The real job: modify the global matrix aligning this container
266 * accordingly to the #AdgAlignment:factor property */
267 adg_entity_transform_global_map(entity
, &shift
, ADG_TRANSFORM_BEFORE
);
268 adg_entity_global_changed(entity
);
270 /* Restore the old global map */
271 shift
.x0
= -shift
.x0
;
272 shift
.y0
= -shift
.y0
;
273 adg_entity_transform_global_map(entity
, &shift
, ADG_TRANSFORM_BEFORE
);
277 set_factor(AdgAlignment
*alignment
, const AdgPair
*factor
)
279 AdgAlignmentPrivate
*data
= alignment
->data
;
281 if (adg_pair_equal(&data
->factor
, factor
))
284 data
->factor
= *factor
;