]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-theme-manager.c
Correct capitalisation. Fix bug #529439 (Baptiste Mille-Mathias).
[empathy.git] / libempathy-gtk / empathy-theme-manager.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2005-2007 Imendio AB
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public
16  * License along with this program; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #include "config.h"
22
23 #include <string.h>
24
25 #include <glib/gi18n.h>
26 #include <gtk/gtk.h>
27
28 #include <libempathy/empathy-utils.h>
29
30 #include "empathy-chat-view.h"
31 #include "empathy-conf.h"
32 #include "empathy-theme.h"
33 #include "empathy-theme-boxes.h"
34 #include "empathy-theme-irc.h"
35 #include "empathy-theme-manager.h"
36
37 #define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EMPATHY_TYPE_THEME_MANAGER, EmpathyThemeManagerPriv))
38
39 typedef struct {
40         gchar       *name;
41         guint        name_notify_id;
42
43         gboolean     show_avatars;
44         guint        show_avatars_notify_id;
45
46         EmpathyTheme *clean_theme;
47         EmpathyTheme *simple_theme;
48         EmpathyTheme *blue_theme;
49         EmpathyTheme *classic_theme;
50
51         GtkSettings  *settings;
52 } EmpathyThemeManagerPriv;
53
54 static void        theme_manager_finalize                 (GObject            *object);
55 static void        theme_manager_notify_name_cb           (EmpathyConf         *conf,
56                                                            const gchar        *key,
57                                                            gpointer            user_data);
58
59 static void        theme_manager_notify_show_avatars_cb   (EmpathyConf         *conf,
60                                                            const gchar        *key,
61                                                            gpointer            user_data);
62 static void        theme_manager_apply_theme              (EmpathyThemeManager *manager,
63                                                            EmpathyChatView     *view,
64                                                            const gchar        *name);
65
66 enum {
67         THEME_CHANGED,
68         LAST_SIGNAL
69 };
70
71 static guint signals[LAST_SIGNAL] = { 0 };
72
73 static const gchar *themes[] = {
74         "classic", N_("Classic"),
75         "simple", N_("Simple"),
76         "clean", N_("Clean"),
77         "blue", N_("Blue"),
78         NULL
79 };
80
81 G_DEFINE_TYPE (EmpathyThemeManager, empathy_theme_manager, G_TYPE_OBJECT);
82
83 static void
84 theme_manager_gdk_color_to_hex (GdkColor *gdk_color, gchar *str_color)
85 {
86         g_snprintf (str_color, 10, 
87                     "#%02x%02x%02x", 
88                     gdk_color->red >> 8,
89                     gdk_color->green >> 8,
90                     gdk_color->blue >> 8);
91 }
92  
93  static void
94 theme_manager_color_hash_notify_cb (EmpathyThemeManager *manager)
95 {
96         EmpathyThemeManagerPriv *priv;
97         GtkStyle                *style;
98         gchar                    color[10];
99
100         priv = GET_PRIV (manager);
101
102         style = gtk_widget_get_default_style ();
103
104         g_object_freeze_notify (G_OBJECT (priv->simple_theme));
105
106         theme_manager_gdk_color_to_hex (&style->base[GTK_STATE_SELECTED], color);
107         g_object_set (priv->simple_theme,
108                       "action-foreground", color,
109                       "link-foreground", color,
110                       NULL);
111  
112         theme_manager_gdk_color_to_hex (&style->bg[GTK_STATE_SELECTED], color);
113         g_object_set (priv->simple_theme,
114                       "header-background", color,
115                       NULL);
116
117         theme_manager_gdk_color_to_hex (&style->dark[GTK_STATE_SELECTED], color);
118         g_object_set (priv->simple_theme,
119                       "header-line-background", color,
120                       NULL);
121
122         theme_manager_gdk_color_to_hex (&style->fg[GTK_STATE_SELECTED], color);
123         g_object_set (priv->simple_theme,
124                       "header-foreground", color,
125                       NULL);
126
127         g_object_thaw_notify (G_OBJECT (priv->simple_theme));
128
129 #if 0
130
131 FIXME: Make that work, it should update color when theme changes but it
132        doesnt seems to work with all themes.
133   
134         g_object_get (priv->settings,
135                       "color-hash", &color_hash,
136                       NULL);
137
138         /*
139          * base_color: #ffffffffffff
140          * fg_color: #000000000000
141          * bg_color: #e6e6e7e7e8e8
142          * text_color: #000000000000
143          * selected_bg_color: #58589a9adbdb
144          * selected_fg_color: #ffffffffffff
145          */
146
147         color = g_hash_table_lookup (color_hash, "base_color");
148         if (color) {
149                 theme_manager_gdk_color_to_hex (color, color_str);
150                 g_object_set (priv->simple_theme,
151                               "action-foreground", color_str,
152                               "link-foreground", color_str,
153                               NULL);
154         }
155
156         color = g_hash_table_lookup (color_hash, "selected_bg_color");
157         if (color) {
158                 theme_manager_gdk_color_to_hex (color, color_str);
159                 g_object_set (priv->simple_theme,
160                               "header-background", color_str,
161                               NULL);
162         }
163
164         color = g_hash_table_lookup (color_hash, "bg_color");
165         if (color) {
166                 GdkColor tmp;
167
168                 tmp = *color;
169                 tmp.red /= 2;
170                 tmp.green /= 2;
171                 tmp.blue /= 2;
172                 theme_manager_gdk_color_to_hex (&tmp, color_str);
173                 g_object_set (priv->simple_theme,
174                               "header-line-background", color_str,
175                               NULL);
176         }
177
178         color = g_hash_table_lookup (color_hash, "selected_fg_color");
179         if (color) {
180                 theme_manager_gdk_color_to_hex (color, color_str);
181                 g_object_set (priv->simple_theme,
182                               "header-foreground", color_str,
183                               NULL);
184         }
185
186         g_hash_table_unref (color_hash);
187
188 #endif
189 }
190
191 static void
192 empathy_theme_manager_class_init (EmpathyThemeManagerClass *klass)
193 {
194         GObjectClass *object_class = G_OBJECT_CLASS (klass);
195
196         signals[THEME_CHANGED] =
197                 g_signal_new ("theme-changed",
198                               G_OBJECT_CLASS_TYPE (object_class),
199                               G_SIGNAL_RUN_LAST,
200                               0,
201                               NULL, NULL,
202                               g_cclosure_marshal_VOID__VOID,
203                               G_TYPE_NONE,
204                               0);
205
206         g_type_class_add_private (object_class, sizeof (EmpathyThemeManagerPriv));
207
208         object_class->finalize = theme_manager_finalize;
209 }
210
211 static void
212 empathy_theme_manager_init (EmpathyThemeManager *manager)
213 {
214         EmpathyThemeManagerPriv *priv;
215
216         priv = GET_PRIV (manager);
217
218         priv->name_notify_id =
219                 empathy_conf_notify_add (empathy_conf_get (),
220                                         EMPATHY_PREFS_CHAT_THEME,
221                                         theme_manager_notify_name_cb,
222                                         manager);
223
224         empathy_conf_get_string (empathy_conf_get (),
225                                 EMPATHY_PREFS_CHAT_THEME,
226                                 &priv->name);
227
228         /* Unused right now, but will be used soon. */
229         priv->show_avatars_notify_id =
230                 empathy_conf_notify_add (empathy_conf_get (),
231                                         EMPATHY_PREFS_UI_SHOW_AVATARS,
232                                         theme_manager_notify_show_avatars_cb,
233                                         manager);
234
235         empathy_conf_get_bool (empathy_conf_get (),
236                               EMPATHY_PREFS_UI_SHOW_AVATARS,
237                               &priv->show_avatars);
238
239         priv->settings = gtk_settings_get_default ();
240         g_signal_connect_swapped (priv->settings, "notify::color-hash",
241                                   G_CALLBACK (theme_manager_color_hash_notify_cb),
242                                   manager);
243
244         priv->simple_theme = g_object_new (EMPATHY_TYPE_THEME_BOXES, NULL);
245         theme_manager_color_hash_notify_cb (manager);
246
247         priv->clean_theme = g_object_new (EMPATHY_TYPE_THEME_BOXES,
248                                           "header-foreground", "black",
249                                           "header-background", "#efefdf",
250                                           "header_line_background", "#e3e3d3",
251                                           "action_foreground", "brown4",
252                                           "time_foreground", "darkgrey",
253                                           "event_foreground", "darkgrey",
254                                           "invite_foreground", "sienna",
255                                           "link_foreground","#49789e",
256                                           NULL);
257
258         priv->blue_theme = g_object_new (EMPATHY_TYPE_THEME_BOXES,
259                                          "header_foreground", "black",
260                                          "header_background", "#88a2b4",
261                                          "header_line_background", "#7f96a4",
262                                          "text_foreground", "black",
263                                          "text_background", "#adbdc8",
264                                          "highlight_foreground", "black",
265                                          "action_foreground", "brown4",
266                                          "time_foreground", "darkgrey",
267                                          "event_foreground", "#7f96a4",
268                                          "invite_foreground", "sienna",
269                                          "link_foreground", "#49789e",
270                                          NULL);
271
272         priv->classic_theme = g_object_new (EMPATHY_TYPE_THEME_IRC, NULL);
273 }
274
275 static void
276 theme_manager_finalize (GObject *object)
277 {
278         EmpathyThemeManagerPriv *priv;
279
280         priv = GET_PRIV (object);
281
282         empathy_conf_notify_remove (empathy_conf_get (), priv->name_notify_id);
283         empathy_conf_notify_remove (empathy_conf_get (), priv->show_avatars_notify_id);
284
285         g_free (priv->name);
286
287         g_object_unref (priv->clean_theme);
288         g_object_unref (priv->simple_theme);
289         g_object_unref (priv->blue_theme);
290         g_object_unref (priv->classic_theme);
291
292         G_OBJECT_CLASS (empathy_theme_manager_parent_class)->finalize (object);
293 }
294
295 static void
296 theme_manager_notify_name_cb (EmpathyConf  *conf,
297                               const gchar *key,
298                               gpointer     user_data)
299 {
300         EmpathyThemeManager     *manager;
301         EmpathyThemeManagerPriv *priv;
302         gchar                  *name;
303
304         manager = user_data;
305         priv = GET_PRIV (manager);
306
307         g_free (priv->name);
308
309         name = NULL;
310         if (!empathy_conf_get_string (conf, key, &name) ||
311             name == NULL || name[0] == 0) {
312                 priv->name = g_strdup ("classic");
313                 g_free (name);
314         } else {
315                 priv->name = name;
316         }
317
318         g_signal_emit (manager, signals[THEME_CHANGED], 0, NULL);
319 }
320
321 static void
322 theme_manager_notify_show_avatars_cb (EmpathyConf  *conf,
323                                       const gchar *key,
324                                       gpointer     user_data)
325 {
326         EmpathyThemeManager     *manager;
327         EmpathyThemeManagerPriv *priv;
328         gboolean                value;
329
330         manager = user_data;
331         priv = GET_PRIV (manager);
332
333         if (!empathy_conf_get_bool (conf, key, &value)) {
334                 priv->show_avatars = FALSE;
335         } else {
336                 priv->show_avatars = value;
337         }
338 }
339
340 static gboolean
341 theme_manager_ensure_theme_exists (const gchar *name)
342 {
343         gint i;
344
345         if (G_STR_EMPTY (name)) {
346                 return FALSE;
347         }
348
349         for (i = 0; themes[i]; i += 2) {
350                 if (strcmp (themes[i], name) == 0) {
351                         return TRUE;
352                 }
353         }
354
355         return FALSE;
356 }
357
358 static void
359 theme_manager_apply_theme (EmpathyThemeManager *manager,
360                            EmpathyChatView     *view,
361                            const gchar        *name)
362 {
363         EmpathyThemeManagerPriv *priv;
364         EmpathyTheme            *theme;
365
366         priv = GET_PRIV (manager);
367
368         /* Make sure all tags are present. Note: not useful now but when we have
369          * user defined theme it will be.
370          */
371         if (theme_manager_ensure_theme_exists (name)) {
372                 if (strcmp (name, "clean") == 0) {
373                         theme = priv->clean_theme;
374                 }
375                 else if (strcmp (name, "simple") == 0) {
376                         theme = priv->simple_theme;
377                 }
378                 else if (strcmp (name, "blue") == 0) {
379                         theme = priv->blue_theme;
380                 } else {
381                         theme = priv->classic_theme;
382                 }
383         } else {
384                 theme = priv->classic_theme;
385         }
386
387         empathy_chat_view_set_theme (view, theme);
388 }
389
390 EmpathyThemeManager *
391 empathy_theme_manager_get (void)
392 {
393         static EmpathyThemeManager *manager = NULL;
394
395         if (!manager) {
396                 manager = g_object_new (EMPATHY_TYPE_THEME_MANAGER, NULL);
397         }
398
399         return manager;
400 }
401
402 const gchar **
403 empathy_theme_manager_get_themes (void)
404 {
405         return themes;
406 }
407
408 void
409 empathy_theme_manager_apply (EmpathyThemeManager *manager,
410                             EmpathyChatView     *view,
411                             const gchar        *name)
412 {
413         EmpathyThemeManagerPriv *priv;
414
415         priv = GET_PRIV (manager);
416
417         theme_manager_apply_theme (manager, view, name);
418 }
419
420 void
421 empathy_theme_manager_apply_saved (EmpathyThemeManager *manager,
422                                   EmpathyChatView     *view)
423 {
424         EmpathyThemeManagerPriv *priv;
425
426         priv = GET_PRIV (manager);
427
428         theme_manager_apply_theme (manager, view, priv->name);
429 }
430