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)
49 PROP_MODEL_TRANSFORMATION
,
50 PROP_PAPER_TRANSFORMATION
54 static void containerable_init (GContainerableIface
*iface
);
55 static void get_property (GObject
*object
,
59 static void set_property (GObject
*object
,
63 static const AdgMatrix
*
64 get_model_matrix (AdgEntity
*entity
);
65 static const AdgMatrix
*
66 get_paper_matrix (AdgEntity
*entity
);
67 static void model_matrix_changed (AdgEntity
*entity
,
68 AdgMatrix
*parent_matrix
);
69 static void paper_matrix_changed (AdgEntity
*entity
,
70 AdgMatrix
*parent_matrix
);
71 static GSList
* get_children (GContainerable
*containerable
);
72 static gboolean
add (GContainerable
*containerable
,
73 GChildable
*childable
);
74 static gboolean
remove (GContainerable
*containerable
,
75 GChildable
*childable
);
76 static void render (AdgEntity
*entity
,
80 G_DEFINE_TYPE_EXTENDED (AdgContainer
, adg_container
,
82 G_IMPLEMENT_INTERFACE (G_TYPE_CONTAINERABLE
,
87 adg_container_class_init (AdgContainerClass
*klass
)
89 GObjectClass
*gobject_class
;
90 AdgEntityClass
*entity_class
;
93 gobject_class
= (GObjectClass
*) klass
;
94 entity_class
= (AdgEntityClass
*) klass
;
96 g_type_class_add_private (klass
, sizeof (AdgContainerPrivate
));
98 gobject_class
->get_property
= get_property
;
99 gobject_class
->set_property
= set_property
;
100 gobject_class
->dispose
= g_containerable_dispose
;
102 entity_class
->model_matrix_changed
= model_matrix_changed
;
103 entity_class
->paper_matrix_changed
= paper_matrix_changed
;
104 entity_class
->get_model_matrix
= get_model_matrix
;
105 entity_class
->get_paper_matrix
= get_paper_matrix
;
106 entity_class
->render
= render
;
108 g_object_class_override_property (gobject_class
, PROP_CHILD
, "child");
110 param
= g_param_spec_boxed ("model-transformation",
111 P_("The model transformation"),
112 P_("The model transformation to be applied to this container and its children entities"),
115 g_object_class_install_property (gobject_class
, PROP_MODEL_TRANSFORMATION
, param
);
117 param
= g_param_spec_boxed ("paper-transformation",
118 P_("The paper transformation"),
119 P_("The paper transformation to be applied to this container and its children entities"),
122 g_object_class_install_property (gobject_class
, PROP_PAPER_TRANSFORMATION
, param
);
126 containerable_init (GContainerableIface
*iface
)
128 iface
->get_children
= get_children
;
130 iface
->remove
= remove
;
134 adg_container_init (AdgContainer
*container
)
136 AdgContainerPrivate
*priv
= G_TYPE_INSTANCE_GET_PRIVATE (container
,
138 AdgContainerPrivate
);
140 priv
->children
= NULL
;
141 cairo_matrix_init_identity (&priv
->model_transformation
);
142 cairo_matrix_init_identity (&priv
->paper_transformation
);
143 cairo_matrix_init_identity (&priv
->model_matrix
);
144 cairo_matrix_init_identity (&priv
->paper_matrix
);
146 container
->priv
= priv
;
150 get_property (GObject
*object
,
155 AdgContainer
*container
= (AdgContainer
*) object
;
159 case PROP_MODEL_TRANSFORMATION
:
160 g_value_set_boxed (value
, &container
->priv
->model_transformation
);
162 case PROP_PAPER_TRANSFORMATION
:
163 g_value_set_boxed (value
, &container
->priv
->paper_transformation
);
166 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
172 set_property (GObject
*object
,
177 AdgContainer
*container
= (AdgContainer
*) object
;
182 g_containerable_add ((GContainerable
*) container
, g_value_get_object (value
));
184 case PROP_MODEL_TRANSFORMATION
:
185 adg_matrix_set (&container
->priv
->model_transformation
,
186 g_value_get_boxed (value
));
188 case PROP_PAPER_TRANSFORMATION
:
189 adg_matrix_set (&container
->priv
->paper_transformation
,
190 g_value_get_boxed (value
));
193 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
199 get_children (GContainerable
*containerable
)
201 AdgContainer
*container
= (AdgContainer
*) containerable
;
203 return g_slist_copy (container
->priv
->children
);
207 add (GContainerable
*containerable
,
208 GChildable
*childable
)
210 AdgContainer
*container
= (AdgContainer
*) containerable
;
212 container
->priv
->children
= g_slist_append (container
->priv
->children
, childable
);
217 remove (GContainerable
*containerable
,
218 GChildable
*childable
)
220 AdgContainer
*container
;
223 container
= (AdgContainer
*) containerable
;
224 node
= g_slist_find (container
->priv
->children
, childable
);
229 container
->priv
->children
= g_slist_delete_link (container
->priv
->children
, node
);
235 model_matrix_changed (AdgEntity
*entity
,
236 AdgMatrix
*parent_matrix
)
238 AdgContainer
*container
= (AdgContainer
*) entity
;
240 PARENT_CLASS
->model_matrix_changed (entity
, parent_matrix
);
243 cairo_matrix_multiply (&container
->priv
->model_matrix
, parent_matrix
,
244 &container
->priv
->model_transformation
);
246 adg_matrix_set (&container
->priv
->model_matrix
,
247 &container
->priv
->model_transformation
);
249 g_containerable_propagate_by_name ((GContainerable
*) entity
,
250 "model-matrix-changed",
251 &container
->priv
->model_matrix
);
255 paper_matrix_changed (AdgEntity
*entity
,
256 AdgMatrix
*parent_matrix
)
258 AdgContainer
*container
= (AdgContainer
*) entity
;
260 PARENT_CLASS
->paper_matrix_changed (entity
, parent_matrix
);
263 cairo_matrix_multiply (&container
->priv
->paper_matrix
, parent_matrix
,
264 &container
->priv
->paper_transformation
);
266 adg_matrix_set (&container
->priv
->paper_matrix
,
267 &container
->priv
->paper_transformation
);
269 g_containerable_propagate_by_name ((GContainerable
*) entity
,
270 "paper-matrix-changed",
271 &container
->priv
->paper_matrix
);
274 static const AdgMatrix
*
275 get_model_matrix (AdgEntity
*entity
)
277 return &((AdgContainer
*) entity
)->priv
->model_matrix
;
280 static const AdgMatrix
*
281 get_paper_matrix (AdgEntity
*entity
)
283 return &((AdgContainer
*) entity
)->priv
->paper_matrix
;
288 render (AdgEntity
*entity
,
291 cairo_set_matrix (cr
, adg_entity_get_model_matrix (entity
));
292 g_containerable_propagate_by_name ((GContainerable
*) entity
, "render", cr
);
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
);