1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 2011 Red Hat, Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser 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.
8  *
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  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "config.h"
19 
20 #include "gtkcssiconthemevalueprivate.h"
21 
22 #include "gtkicontheme.h"
23 #include "gtksettingsprivate.h"
24 #include "gtkstyleproviderprivate.h"
25 
26 /*
27  * The idea behind this value (and the '-gtk-icon-theme' CSS property) is
28  * to track changes to the icon theme.
29  *
30  * We create a new instance of this value whenever the icon theme changes
31  * (via emitting the changed signal). So as long as the icon theme does
32  * not change, we will compute the same value. We can then compare values
33  * by pointer to see if the icon theme changed.
34  */
35 
36 struct _GtkCssValue {
37   GTK_CSS_VALUE_BASE
38   GtkIconTheme *icontheme;
39   guint changed_id;
40 };
41 
42 static void
gtk_css_value_icon_theme_disconnect_handler(GtkCssValue * value)43 gtk_css_value_icon_theme_disconnect_handler (GtkCssValue *value)
44 {
45   if (value->changed_id == 0)
46     return;
47 
48   g_object_set_data (G_OBJECT (value->icontheme), "-gtk-css-value", NULL);
49 
50   g_signal_handler_disconnect (value->icontheme, value->changed_id);
51   value->changed_id = 0;
52 }
53 
54 static void
gtk_css_value_icon_theme_changed_cb(GtkIconTheme * icontheme,GtkCssValue * value)55 gtk_css_value_icon_theme_changed_cb (GtkIconTheme *icontheme,
56                                      GtkCssValue  *value)
57 {
58   gtk_css_value_icon_theme_disconnect_handler (value);
59 }
60 
61 static void
gtk_css_value_icon_theme_free(GtkCssValue * value)62 gtk_css_value_icon_theme_free (GtkCssValue *value)
63 {
64   gtk_css_value_icon_theme_disconnect_handler (value);
65 
66   if (value->icontheme)
67     g_object_unref (value->icontheme);
68 
69   g_slice_free (GtkCssValue, value);
70 }
71 
72 static GtkCssValue *
gtk_css_value_icon_theme_compute(GtkCssValue * icon_theme,guint property_id,GtkStyleProviderPrivate * provider,GtkCssStyle * style,GtkCssStyle * parent_style)73 gtk_css_value_icon_theme_compute (GtkCssValue             *icon_theme,
74                                   guint                    property_id,
75                                   GtkStyleProviderPrivate *provider,
76                                   GtkCssStyle             *style,
77                                   GtkCssStyle             *parent_style)
78 {
79   GtkIconTheme *icontheme;
80 
81   if (icon_theme->icontheme)
82     icontheme = icon_theme->icontheme;
83   else
84     icontheme = gtk_icon_theme_get_for_screen (_gtk_settings_get_screen (_gtk_style_provider_private_get_settings (provider)));
85 
86   return gtk_css_icon_theme_value_new (icontheme);
87 }
88 
89 static gboolean
gtk_css_value_icon_theme_equal(const GtkCssValue * value1,const GtkCssValue * value2)90 gtk_css_value_icon_theme_equal (const GtkCssValue *value1,
91                                 const GtkCssValue *value2)
92 {
93   return FALSE;
94 }
95 
96 static GtkCssValue *
gtk_css_value_icon_theme_transition(GtkCssValue * start,GtkCssValue * end,guint property_id,double progress)97 gtk_css_value_icon_theme_transition (GtkCssValue *start,
98                                      GtkCssValue *end,
99                                      guint        property_id,
100                                      double       progress)
101 {
102   return NULL;
103 }
104 
105 static void
gtk_css_value_icon_theme_print(const GtkCssValue * icon_theme,GString * string)106 gtk_css_value_icon_theme_print (const GtkCssValue *icon_theme,
107                                 GString           *string)
108 {
109   g_string_append (string, "initial");
110 }
111 
112 static const GtkCssValueClass GTK_CSS_VALUE_ICON_THEME = {
113   gtk_css_value_icon_theme_free,
114   gtk_css_value_icon_theme_compute,
115   gtk_css_value_icon_theme_equal,
116   gtk_css_value_icon_theme_transition,
117   gtk_css_value_icon_theme_print
118 };
119 
120 static GtkCssValue default_icon_theme_value = { &GTK_CSS_VALUE_ICON_THEME, 1, NULL, 0 };
121 
122 GtkCssValue *
gtk_css_icon_theme_value_new(GtkIconTheme * icontheme)123 gtk_css_icon_theme_value_new (GtkIconTheme *icontheme)
124 {
125   GtkCssValue *result;
126 
127   if (icontheme == NULL)
128     return _gtk_css_value_ref (&default_icon_theme_value);
129 
130   result = g_object_get_data (G_OBJECT (icontheme), "-gtk-css-value");
131   if (result)
132     return _gtk_css_value_ref (result);
133 
134   result = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_ICON_THEME);
135   result->icontheme = g_object_ref (icontheme);
136 
137   g_object_set_data (G_OBJECT (icontheme), "-gtk-css-value", result);
138   result->changed_id = g_signal_connect (icontheme, "changed", G_CALLBACK (gtk_css_value_icon_theme_changed_cb), result);
139 
140   return result;
141 }
142 
143 GtkCssValue *
gtk_css_icon_theme_value_parse(GtkCssParser * parser)144 gtk_css_icon_theme_value_parse (GtkCssParser *parser)
145 {
146   GtkIconTheme *icontheme;
147   GtkCssValue *result;
148   char *s;
149 
150   s = _gtk_css_parser_read_string (parser);
151   if (s == NULL)
152     return NULL;
153 
154   icontheme = gtk_icon_theme_new ();
155   gtk_icon_theme_set_custom_theme (icontheme, s);
156 
157   result = gtk_css_icon_theme_value_new (icontheme);
158 
159   g_object_unref (icontheme);
160   g_free (s);
161 
162   return result;
163 }
164 
165 GtkIconTheme *
gtk_css_icon_theme_value_get_icon_theme(GtkCssValue * value)166 gtk_css_icon_theme_value_get_icon_theme (GtkCssValue *value)
167 {
168   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_ICON_THEME, NULL);
169 
170   return value->icontheme;
171 }
172