No issues found
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /*
3 * st-theme-context.c: holds global information about a tree of styled objects
4 *
5 * Copyright 2009, 2010 Red Hat, Inc.
6 * Copyright 2009 Florian Mç«Żllner
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as
10 * published by the Free Software Foundation, either version 2.1 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope it will be useful, but WITHOUT ANY
14 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include <config.h>
23
24 #include "st-texture-cache.h"
25 #include "st-theme.h"
26 #include "st-theme-context.h"
27
28 struct _StThemeContext {
29 GObject parent;
30
31 PangoFontDescription *font;
32 StThemeNode *root_node;
33 StTheme *theme;
34 };
35
36 struct _StThemeContextClass {
37 GObjectClass parent_class;
38 };
39
40 #define DEFAULT_FONT "sans-serif 10"
41
42 enum
43 {
44 CHANGED,
45
46 LAST_SIGNAL
47 };
48
49 static guint signals[LAST_SIGNAL] = { 0, };
50
51 G_DEFINE_TYPE (StThemeContext, st_theme_context, G_TYPE_OBJECT)
52
53 static void on_icon_theme_changed (StTextureCache *cache,
54 StThemeContext *context);
55 static void st_theme_context_changed (StThemeContext *context);
56
57 static void
58 st_theme_context_finalize (GObject *object)
59 {
60 StThemeContext *context = ST_THEME_CONTEXT (object);
61
62 g_signal_handlers_disconnect_by_func (st_texture_cache_get_default (),
63 (gpointer) on_icon_theme_changed,
64 context);
65 g_signal_handlers_disconnect_by_func (clutter_get_default_backend (),
66 (gpointer) st_theme_context_changed,
67 context);
68
69 if (context->root_node)
70 g_object_unref (context->root_node);
71 if (context->theme)
72 g_object_unref (context->theme);
73
74 pango_font_description_free (context->font);
75
76 G_OBJECT_CLASS (st_theme_context_parent_class)->finalize (object);
77 }
78
79 static void
80 st_theme_context_class_init (StThemeContextClass *klass)
81 {
82 GObjectClass *object_class = G_OBJECT_CLASS (klass);
83
84 object_class->finalize = st_theme_context_finalize;
85
86 signals[CHANGED] =
87 g_signal_new ("changed",
88 G_TYPE_FROM_CLASS (klass),
89 G_SIGNAL_RUN_LAST,
90 0, /* no default handler slot */
91 NULL, NULL, NULL,
92 G_TYPE_NONE, 0);
93 }
94
95 static void
96 st_theme_context_init (StThemeContext *context)
97 {
98 context->font = pango_font_description_from_string (DEFAULT_FONT);
99
100 g_signal_connect (st_texture_cache_get_default (),
101 "icon-theme-changed",
102 G_CALLBACK (on_icon_theme_changed),
103 context);
104 g_signal_connect_swapped (clutter_get_default_backend (),
105 "resolution-changed",
106 G_CALLBACK (st_theme_context_changed),
107 context);
108 }
109
110 /**
111 * st_theme_context_new:
112 *
113 * Create a new theme context not associated with any #ClutterStage.
114 * This can be useful in testing scenarios, or if using StThemeContext
115 * with something other than #ClutterActor objects, but you generally
116 * should use st_theme_context_get_for_stage() instead.
117 */
118 StThemeContext *
119 st_theme_context_new (void)
120 {
121 StThemeContext *context;
122
123 context = g_object_new (ST_TYPE_THEME_CONTEXT, NULL);
124
125 return context;
126 }
127
128 static void
129 on_stage_destroy (ClutterStage *stage)
130 {
131 StThemeContext *context = st_theme_context_get_for_stage (stage);
132
133 g_object_set_data (G_OBJECT (stage), "st-theme-context", NULL);
134 g_object_unref (context);
135 }
136
137 static gboolean
138 emit_changed (StThemeContext *context)
139 {
140 g_signal_emit (context, signals[CHANGED], 0);
141 return FALSE;
142 }
143
144 static void
145 st_theme_context_changed (StThemeContext *context)
146 {
147 StThemeNode *old_root = context->root_node;
148 context->root_node = NULL;
149
150 emit_changed (context);
151
152 if (old_root)
153 g_object_unref (old_root);
154 }
155
156 static void
157 on_icon_theme_changed (StTextureCache *cache,
158 StThemeContext *context)
159 {
160 /* Note that an icon theme change isn't really a change of the StThemeContext;
161 * the style information has changed. But since the style factors into the
162 * icon_name => icon lookup, faking a theme context change is a good way
163 * to force users such as StIcon to look up icons again. Don't bother recreating
164 * the root node, though. */
165 g_idle_add ((GSourceFunc) emit_changed, context);
166 }
167
168 /**
169 * st_theme_context_get_for_stage:
170 * @stage: a #ClutterStage
171 *
172 * Gets a singleton theme context associated with the stage.
173 *
174 * Return value: (transfer none): the singleton theme context for the stage
175 */
176 StThemeContext *
177 st_theme_context_get_for_stage (ClutterStage *stage)
178 {
179 StThemeContext *context;
180
181 g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL);
182
183 context = g_object_get_data (G_OBJECT (stage), "st-theme-context");
184 if (context)
185 return context;
186
187 context = st_theme_context_new ();
188 g_object_set_data (G_OBJECT (stage), "st-theme-context", context);
189 g_signal_connect (stage, "destroy",
190 G_CALLBACK (on_stage_destroy), NULL);
191
192 return context;
193 }
194
195 /**
196 * st_theme_context_set_theme:
197 * @context: a #StThemeContext
198 *
199 * Sets the default set of theme stylesheets for the context. This theme will
200 * be used for the root node and for nodes descending from it, unless some other
201 * style is explicitely specified.
202 */
203 void
204 st_theme_context_set_theme (StThemeContext *context,
205 StTheme *theme)
206 {
207 g_return_if_fail (ST_IS_THEME_CONTEXT (context));
208 g_return_if_fail (theme == NULL || ST_IS_THEME (theme));
209
210 if (context->theme != theme)
211 {
212 if (context->theme)
213 g_object_unref (context->theme);
214
215 context->theme = theme;
216
217 if (context->theme)
218 g_object_ref (context->theme);
219
220 st_theme_context_changed (context);
221 }
222 }
223
224 /**
225 * st_theme_context_get_theme:
226 * @context: a #StThemeContext
227 *
228 * Gets the default theme for the context. See st_theme_context_set_theme()
229 *
230 * Return value: (transfer none): the default theme for the context
231 */
232 StTheme *
233 st_theme_context_get_theme (StThemeContext *context)
234 {
235 g_return_val_if_fail (ST_IS_THEME_CONTEXT (context), NULL);
236
237 return context->theme;
238 }
239
240 /**
241 * st_theme_context_set_font:
242 * @context: a #StThemeContext
243 * @font: the default font for theme context
244 *
245 * Sets the default font for the theme context. This is the font that
246 * is inherited by the root node of the tree of theme nodes. If the
247 * font is not overriden, then this font will be used. If the font is
248 * partially modified (for example, with 'font-size: 110%', then that
249 * modification is based on this font.
250 */
251 void
252 st_theme_context_set_font (StThemeContext *context,
253 const PangoFontDescription *font)
254 {
255 g_return_if_fail (ST_IS_THEME_CONTEXT (context));
256 g_return_if_fail (font != NULL);
257
258 if (context->font == font ||
259 pango_font_description_equal (context->font, font))
260 return;
261
262 pango_font_description_free (context->font);
263 context->font = pango_font_description_copy (font);
264 st_theme_context_changed (context);
265 }
266
267 /**
268 * st_theme_context_get_font:
269 * @context: a #StThemeContext
270 *
271 * Gets the default font for the theme context. See st_theme_context_set_font().
272 *
273 * Return value: the default font for the theme context.
274 */
275 const PangoFontDescription *
276 st_theme_context_get_font (StThemeContext *context)
277 {
278 g_return_val_if_fail (ST_IS_THEME_CONTEXT (context), NULL);
279
280 return context->font;
281 }
282
283 /**
284 * st_theme_context_get_root_node:
285 * @context: a #StThemeContext
286 *
287 * Gets the root node of the tree of theme style nodes that associated with this
288 * context. For the node tree associated with a stage, this node represents
289 * styles applied to the stage itself.
290 *
291 * Return value: (transfer none): the root node of the context's style tree
292 */
293 StThemeNode *
294 st_theme_context_get_root_node (StThemeContext *context)
295 {
296 if (context->root_node == NULL)
297 context->root_node = st_theme_node_new (context, NULL, context->theme,
298 G_TYPE_NONE, NULL, NULL, NULL, NULL);
299
300 return context->root_node;
301 }