1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007-2008, 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 Library 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 * Library 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., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
23 * @title: AdgContainer
24 * @short_description: Base class for entity that can contain other entities
26 * The #AdgContainer is an entity that implements the #GContainerable interface.
27 * Each AdgContainer has its paper matrix (#AdgContainer:paper_matrix) to be
28 * used on paper-dependent references (such as font and arrow sizes, line
29 * thickness etc...) and a model matrix usually applied to the model view. See
30 * http://www.entidi.it/adg/tutorial/view/3 for details on this topic.
32 * This means an AdgContainer can be thought as a group of entities with the
33 * same geometrical identity (same scale, reference point ecc...).
36 #include "adg-container.h"
37 #include "adg-container-private.h"
40 #include <gcontainer/gcontainer.h>
42 #define PARENT_CLASS ((AdgEntityClass *) adg_container_parent_class)
48 PROP_MODEL_TRANSFORMATION
,
49 PROP_PAPER_TRANSFORMATION
53 static void containerable_init (GContainerableIface
*iface
);
54 static void get_property (GObject
*object
,
58 static void set_property (GObject
*object
,
62 static const AdgMatrix
*get_model_matrix (AdgEntity
*entity
);
63 static const AdgMatrix
*get_paper_matrix (AdgEntity
*entity
);
64 static void model_matrix_changed (AdgEntity
*entity
,
65 AdgMatrix
*parent_matrix
);
66 static void paper_matrix_changed (AdgEntity
*entity
,
67 AdgMatrix
*parent_matrix
);
68 static GSList
* get_children (GContainerable
*containerable
);
69 static gboolean
add (GContainerable
*containerable
,
70 GChildable
*childable
);
71 static gboolean
remove (GContainerable
*containerable
,
72 GChildable
*childable
);
73 static void invalidate (AdgEntity
*entity
);
74 static void render (AdgEntity
*entity
,
78 G_DEFINE_TYPE_EXTENDED(AdgContainer
, adg_container
,
80 G_IMPLEMENT_INTERFACE(G_TYPE_CONTAINERABLE
,
85 adg_container_class_init(AdgContainerClass
*klass
)
87 GObjectClass
*gobject_class
;
88 AdgEntityClass
*entity_class
;
91 gobject_class
= (GObjectClass
*) klass
;
92 entity_class
= (AdgEntityClass
*) klass
;
94 g_type_class_add_private(klass
, sizeof(AdgContainerPrivate
));
96 gobject_class
->get_property
= get_property
;
97 gobject_class
->set_property
= set_property
;
98 gobject_class
->dispose
= g_containerable_dispose
;
100 entity_class
->model_matrix_changed
= model_matrix_changed
;
101 entity_class
->paper_matrix_changed
= paper_matrix_changed
;
102 entity_class
->get_model_matrix
= get_model_matrix
;
103 entity_class
->get_paper_matrix
= get_paper_matrix
;
104 entity_class
->invalidate
= invalidate
;
105 entity_class
->render
= render
;
107 g_object_class_override_property(gobject_class
, PROP_CHILD
, "child");
109 param
= g_param_spec_boxed("model-transformation",
110 P_("The model transformation"),
111 P_("The model transformation to be applied to this container and its children entities"),
112 ADG_TYPE_MATRIX
, G_PARAM_READWRITE
);
113 g_object_class_install_property(gobject_class
,
114 PROP_MODEL_TRANSFORMATION
, param
);
116 param
= g_param_spec_boxed("paper-transformation",
117 P_("The paper transformation"),
118 P_("The paper transformation to be applied to this container and its children entities"),
119 ADG_TYPE_MATRIX
, G_PARAM_READWRITE
);
120 g_object_class_install_property(gobject_class
,
121 PROP_PAPER_TRANSFORMATION
, param
);
125 containerable_init(GContainerableIface
*iface
)
127 iface
->get_children
= get_children
;
129 iface
->remove
= remove
;
133 adg_container_init(AdgContainer
*container
)
135 AdgContainerPrivate
*priv
= G_TYPE_INSTANCE_GET_PRIVATE(container
,
137 AdgContainerPrivate
);
139 priv
->children
= NULL
;
140 cairo_matrix_init_identity(&priv
->model_transformation
);
141 cairo_matrix_init_identity(&priv
->paper_transformation
);
142 cairo_matrix_init_identity(&priv
->model_matrix
);
143 cairo_matrix_init_identity(&priv
->paper_matrix
);
145 container
->priv
= priv
;
149 get_property(GObject
*object
, guint prop_id
, GValue
*value
, GParamSpec
*pspec
)
151 AdgContainer
*container
= (AdgContainer
*) object
;
154 case PROP_MODEL_TRANSFORMATION
:
155 g_value_set_boxed(value
, &container
->priv
->model_transformation
);
157 case PROP_PAPER_TRANSFORMATION
:
158 g_value_set_boxed(value
, &container
->priv
->paper_transformation
);
161 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
167 set_property(GObject
*object
,
168 guint prop_id
, const GValue
*value
, GParamSpec
*pspec
)
170 AdgContainer
*container
= (AdgContainer
*) object
;
174 g_containerable_add((GContainerable
*) container
,
175 g_value_get_object(value
));
177 case PROP_MODEL_TRANSFORMATION
:
178 adg_matrix_set(&container
->priv
->model_transformation
,
179 g_value_get_boxed(value
));
181 case PROP_PAPER_TRANSFORMATION
:
182 adg_matrix_set(&container
->priv
->paper_transformation
,
183 g_value_get_boxed(value
));
186 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
192 get_children(GContainerable
*containerable
)
194 AdgContainer
*container
= (AdgContainer
*) containerable
;
196 return g_slist_copy(container
->priv
->children
);
200 add(GContainerable
*containerable
, GChildable
*childable
)
202 AdgContainer
*container
= (AdgContainer
*) containerable
;
204 container
->priv
->children
=
205 g_slist_append(container
->priv
->children
, childable
);
210 remove(GContainerable
*containerable
, GChildable
*childable
)
212 AdgContainer
*container
;
215 container
= (AdgContainer
*) containerable
;
216 node
= g_slist_find(container
->priv
->children
, childable
);
221 container
->priv
->children
=
222 g_slist_delete_link(container
->priv
->children
, node
);
228 model_matrix_changed(AdgEntity
*entity
, AdgMatrix
*parent_matrix
)
230 AdgContainer
*container
= (AdgContainer
*) entity
;
232 PARENT_CLASS
->model_matrix_changed(entity
, parent_matrix
);
235 cairo_matrix_multiply(&container
->priv
->model_matrix
,
237 &container
->priv
->model_transformation
);
239 adg_matrix_set(&container
->priv
->model_matrix
,
240 &container
->priv
->model_transformation
);
242 g_containerable_propagate_by_name((GContainerable
*) entity
,
243 "model-matrix-changed",
244 &container
->priv
->model_matrix
);
248 paper_matrix_changed(AdgEntity
*entity
, AdgMatrix
*parent_matrix
)
250 AdgContainer
*container
= (AdgContainer
*) entity
;
252 PARENT_CLASS
->paper_matrix_changed(entity
, parent_matrix
);
255 cairo_matrix_multiply(&container
->priv
->paper_matrix
,
257 &container
->priv
->paper_transformation
);
259 adg_matrix_set(&container
->priv
->paper_matrix
,
260 &container
->priv
->paper_transformation
);
262 g_containerable_propagate_by_name((GContainerable
*) entity
,
263 "paper-matrix-changed",
264 &container
->priv
->paper_matrix
);
267 static const AdgMatrix
*
268 get_model_matrix(AdgEntity
*entity
)
270 return &((AdgContainer
*) entity
)->priv
->model_matrix
;
273 static const AdgMatrix
*
274 get_paper_matrix(AdgEntity
*entity
)
276 return &((AdgContainer
*) entity
)->priv
->paper_matrix
;
281 invalidate(AdgEntity
*entity
)
283 g_containerable_propagate_by_name((GContainerable
*) entity
,
288 render(AdgEntity
*entity
, cairo_t
*cr
)
290 cairo_set_matrix(cr
, adg_entity_get_model_matrix(entity
));
291 g_containerable_propagate_by_name((GContainerable
*) entity
,
297 adg_container_get_model_transformation(AdgContainer
*container
)
299 g_return_val_if_fail(ADG_IS_CONTAINER(container
), NULL
);
300 return &container
->priv
->model_transformation
;
304 adg_container_set_model_transformation(AdgContainer
*container
,
305 AdgMatrix
*transformation
)
309 const AdgMatrix
*parent_matrix
;
311 g_return_if_fail(ADG_IS_CONTAINER(container
));
312 g_return_if_fail(transformation
!= NULL
);
314 entity
= (AdgEntity
*) container
;
315 parent
= (AdgEntity
*) g_childable_get_parent((GChildable
*) entity
);
316 parent_matrix
= parent
? adg_entity_get_model_matrix(parent
) : NULL
;
318 adg_matrix_set(&container
->priv
->model_transformation
, transformation
);
319 adg_entity_model_matrix_changed(entity
, parent_matrix
);
323 adg_container_get_paper_transformation(AdgContainer
*container
)
325 g_return_val_if_fail(ADG_IS_CONTAINER(container
), NULL
);
326 return &container
->priv
->paper_transformation
;
330 adg_container_set_paper_transformation(AdgContainer
*container
,
331 AdgMatrix
*transformation
)
335 const AdgMatrix
*parent_matrix
;
337 g_return_if_fail(ADG_IS_CONTAINER(container
));
338 g_return_if_fail(transformation
!= NULL
);
340 entity
= (AdgEntity
*) container
;
341 parent
= (AdgEntity
*) g_childable_get_parent((GChildable
*) entity
);
342 parent_matrix
= parent
? adg_entity_get_paper_matrix(parent
) : NULL
;
344 adg_matrix_set(&container
->priv
->paper_transformation
, transformation
);
345 adg_entity_paper_matrix_changed(entity
, parent_matrix
);