Implemented stlye slots on AdgArrowStyle
[adg.git] / adg / adg-context.c
blob4590628b12cf832811c480426680416ea9f186d0
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:context
23 * @title: AdgContext
24 * @short_description: Base class for styling the rendering process
26 * The context is a collection of styles, one for each #AdgStyle derived
27 * class. To achieve this result, there is a common register where all
28 * the style derived class are stored and every #AdgContext instance keeps
29 * its own register of style instances (one instance per class).
31 * Although this could be implemented by accessing the underlying registers
32 * using GType id, to be able to access efficiently, that is O(1) magnitude,
33 * the concept of slot was introduced.
35 * The slot serves the same purpose than a GType, that is identify a type
36 * class, but the slots are a strict sequence starting from 0, useful to be
37 * used as an array index.
40 #include "adg-context.h"
41 #include "adg-context-private.h"
42 #include "adg-intl.h"
44 #define PARENT_CLASS ((AdgEntityClass *) adg_context_parent_class)
47 static void fill_style_slots (GPtrArray *style_slots,
48 guint last_slot);
50 static GPtrArray *class_slots = NULL;
53 G_DEFINE_TYPE (AdgContext, adg_context, G_TYPE_OBJECT)
56 static void
57 adg_context_class_init (AdgContextClass *klass)
59 g_type_class_add_private (klass, sizeof (AdgContextPrivate));
62 static void
63 adg_context_init (AdgContext *context)
65 AdgContextPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (context,
66 ADG_TYPE_CONTEXT,
67 AdgContextPrivate);
68 priv->style_slots = g_ptr_array_sized_new (class_slots ? class_slots->len : 10);
69 context->priv = priv;
73 /**
74 * adg_context_get_slot:
75 * @type: an #AdgStyle type
77 * Gets the slot associated to @type. If not found, registers a new
78 * style family by assigning a new slot id to it: the internal register
79 * will keep a reference to this style class.
81 * Return value: the requested slot id
82 **/
83 AdgStyleSlot
84 adg_context_get_slot (GType type)
86 AdgStyleClass *klass = g_type_class_ref (type);
88 g_return_val_if_fail (ADG_IS_STYLE_CLASS (klass), -1);
90 if G_UNLIKELY (class_slots == NULL)
92 class_slots = g_ptr_array_sized_new (10);
94 else
96 guint n;
97 for (n = 0; n < class_slots->len; ++ n)
98 if (class_slots->pdata[n] == klass)
99 return n;
102 g_ptr_array_add (class_slots, klass);
103 return class_slots->len - 1;
107 * adg_context_new:
109 * Constructs a new empty context.
111 * Return value: a new context
113 AdgContext *
114 adg_context_new (void)
116 return g_object_new (ADG_TYPE_CONTEXT, NULL);
120 * adg_context_get_style:
121 * @context: an #AdgContext instance
122 * @slot: the style slot where to get the style
124 * Gets a style instance from the specified @slot of @context.
126 * Return value: the style instance
128 AdgStyle *
129 adg_context_get_style (AdgContext *context,
130 AdgStyleSlot slot)
132 GPtrArray *style_slots;
134 g_return_val_if_fail (ADG_IS_CONTEXT (context), NULL);
135 g_return_val_if_fail (slot >= 0 && slot < class_slots->len, NULL);
137 style_slots = context->priv->style_slots;
139 if G_UNLIKELY (slot >= style_slots->len)
140 fill_style_slots (style_slots, slot);
142 return (AdgStyle *) g_ptr_array_index (style_slots, slot);
146 * adg_context_set_style:
147 * @context: an #AdgContext instance
148 * @style: the new style to include
150 * Sets a new style inside @context. The old style (if any)
151 * will be unreferenced while a new reference will be added to @style.
153 void
154 adg_context_set_style (AdgContext *context,
155 AdgStyle *style)
157 AdgStyleSlot slot;
158 GPtrArray *style_slots;
160 g_return_if_fail (ADG_IS_CONTEXT (context));
161 g_return_if_fail (ADG_IS_STYLE (style));
163 slot = adg_context_get_slot (G_TYPE_FROM_INSTANCE (style));
164 style_slots = context->priv->style_slots;
166 g_object_ref (style);
168 if G_LIKELY (slot < style_slots->len)
170 g_object_unref (style_slots->pdata[slot]);
171 style_slots->pdata[slot] = style;
173 else
175 fill_style_slots (style_slots, slot-1);
176 g_ptr_array_add (style_slots, style);
181 static void
182 fill_style_slots (GPtrArray *style_slots,
183 guint last_slot)
185 AdgStyleClass *klass;
186 AdgStyle *style;
187 guint n;
189 for (n = style_slots->len; n <= last_slot; ++ n)
191 klass = (AdgStyleClass *) g_ptr_array_index (class_slots, n);
192 style = adg_style_get_default (klass);
193 g_object_ref ((GObject *) style);
194 g_ptr_array_add (style_slots, style);