Implemented adg_line_style_new()
[adg.git] / adg / adg-container.c
blob2319882254ffb1e2fa0ffb624d0b637f082536d7
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.
21 /**
22 * SECTION:container
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"
38 #include "adg-intl.h"
40 #include <gcontainer/gcontainer.h>
42 #define PARENT_CLASS ((AdgEntityClass *) adg_container_parent_class)
45 enum
47 PROP_0,
48 PROP_CHILD,
49 PROP_MODEL_TRANSFORMATION,
50 PROP_PAPER_TRANSFORMATION
54 static void containerable_init (GContainerableIface *iface);
55 static void get_property (GObject *object,
56 guint prop_id,
57 GValue *value,
58 GParamSpec *pspec);
59 static void set_property (GObject *object,
60 guint prop_id,
61 const GValue *value,
62 GParamSpec *pspec);
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,
77 cairo_t *cr);
80 G_DEFINE_TYPE_EXTENDED (AdgContainer, adg_container,
81 ADG_TYPE_ENTITY, 0,
82 G_IMPLEMENT_INTERFACE (G_TYPE_CONTAINERABLE,
83 containerable_init))
86 static void
87 adg_container_class_init (AdgContainerClass *klass)
89 GObjectClass *gobject_class;
90 AdgEntityClass *entity_class;
91 GParamSpec *param;
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"),
113 ADG_TYPE_MATRIX,
114 G_PARAM_READWRITE);
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"),
120 ADG_TYPE_MATRIX,
121 G_PARAM_READWRITE);
122 g_object_class_install_property (gobject_class, PROP_PAPER_TRANSFORMATION, param);
125 static void
126 containerable_init (GContainerableIface *iface)
128 iface->get_children = get_children;
129 iface->add = add;
130 iface->remove = remove;
133 static void
134 adg_container_init (AdgContainer *container)
136 AdgContainerPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (container,
137 ADG_TYPE_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;
149 static void
150 get_property (GObject *object,
151 guint prop_id,
152 GValue *value,
153 GParamSpec *pspec)
155 AdgContainer *container = (AdgContainer *) object;
157 switch (prop_id)
159 case PROP_MODEL_TRANSFORMATION:
160 g_value_set_boxed (value, &container->priv->model_transformation);
161 break;
162 case PROP_PAPER_TRANSFORMATION:
163 g_value_set_boxed (value, &container->priv->paper_transformation);
164 break;
165 default:
166 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
167 break;
171 static void
172 set_property (GObject *object,
173 guint prop_id,
174 const GValue *value,
175 GParamSpec *pspec)
177 AdgContainer *container = (AdgContainer *) object;
179 switch (prop_id)
181 case PROP_CHILD:
182 g_containerable_add ((GContainerable *) container, g_value_get_object (value));
183 break;
184 case PROP_MODEL_TRANSFORMATION:
185 adg_matrix_set (&container->priv->model_transformation,
186 g_value_get_boxed (value));
187 break;
188 case PROP_PAPER_TRANSFORMATION:
189 adg_matrix_set (&container->priv->paper_transformation,
190 g_value_get_boxed (value));
191 break;
192 default:
193 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
198 static GSList *
199 get_children (GContainerable *containerable)
201 AdgContainer *container = (AdgContainer *) containerable;
203 return g_slist_copy (container->priv->children);
206 static gboolean
207 add (GContainerable *containerable,
208 GChildable *childable)
210 AdgContainer *container = (AdgContainer *) containerable;
212 container->priv->children = g_slist_append (container->priv->children, childable);
213 return TRUE;
216 static gboolean
217 remove (GContainerable *containerable,
218 GChildable *childable)
220 AdgContainer *container;
221 GSList *node;
223 container = (AdgContainer *) containerable;
224 node = g_slist_find (container->priv->children, childable);
226 if (!node)
227 return FALSE;
229 container->priv->children = g_slist_delete_link (container->priv->children, node);
230 return TRUE;
234 static void
235 model_matrix_changed (AdgEntity *entity,
236 AdgMatrix *parent_matrix)
238 AdgContainer *container = (AdgContainer *) entity;
240 PARENT_CLASS->model_matrix_changed (entity, parent_matrix);
242 if (parent_matrix)
243 cairo_matrix_multiply (&container->priv->model_matrix, parent_matrix,
244 &container->priv->model_transformation);
245 else
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);
254 static void
255 paper_matrix_changed (AdgEntity *entity,
256 AdgMatrix *parent_matrix)
258 AdgContainer *container = (AdgContainer *) entity;
260 PARENT_CLASS->paper_matrix_changed (entity, parent_matrix);
262 if (parent_matrix)
263 cairo_matrix_multiply (&container->priv->paper_matrix, parent_matrix,
264 &container->priv->paper_transformation);
265 else
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;
287 static void
288 render (AdgEntity *entity,
289 cairo_t *cr)
291 cairo_set_matrix (cr, adg_entity_get_model_matrix (entity));
292 g_containerable_propagate_by_name ((GContainerable *) entity, "render", cr);
296 const AdgMatrix *
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;
303 void
304 adg_container_set_model_transformation (AdgContainer *container,
305 AdgMatrix *transformation)
307 AdgEntity *entity;
308 AdgEntity *parent;
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);
322 const AdgMatrix *
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;
329 void
330 adg_container_set_paper_transformation (AdgContainer *container,
331 AdgMatrix *transformation)
333 AdgEntity *entity;
334 AdgEntity *parent;
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);