2006-09-21 Tommi Komulainen <tommi.komulainen@nokia.com>
[hildon] / hildon-widgets / hildon-defines.c
1 /*
2  * This file is part of hildon-libs
3  *
4  * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved.
5  *
6  * Contact: Michael Dominic Kostrzewa <michael.kostrzewa@nokia.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; version 2.1 of
11  * the License or any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  *
23  */
24
25 /**
26  * SECTION:hildon-defines
27  * @short_description: Not a widget, just a helper
28  *
29  */
30
31 #include <gtk/gtk.h>
32 #include "hildon-defines.h"
33
34 const  HildonIconSizes *hildoniconsizes = NULL;
35 static HildonIconSizes iis; /* hildon internal icon sizes */
36
37 /**
38  * hildon_icon_sizes_init:
39  * 
40  * Initializes the icon sizes. This is automatically
41  * called when the icon sizes have not been initialized
42  * and one is requested.
43  **/
44 void hildon_icon_sizes_init (void)
45 {
46   if (hildoniconsizes != NULL)
47     return;
48   
49   hildoniconsizes = &iis;
50   
51   iis.icon_size_list                       = gtk_icon_size_register ("hildon_icon_size_list",                64, 64);
52   iis.icon_size_small                      = gtk_icon_size_register ("*icon_size_small",                     26, 26);
53   iis.icon_size_toolbar                    = gtk_icon_size_register ("icon_size_toolbar",                    26, 26);
54   iis.icon_size_widg                       = gtk_icon_size_register ("icon_size_widg",                       26, 26);
55   iis.icon_size_widg_wizard                = gtk_icon_size_register ("icon_size_widg_wizard",                50, 50);
56   iis.icon_size_grid                       = gtk_icon_size_register ("icon_size_grid",                       64, 64);
57   iis.icon_size_big_note                   = gtk_icon_size_register ("icon_size_big_note",                   50, 50);
58   iis.icon_size_note                       = gtk_icon_size_register ("icon_size_note",                       26, 26);
59   iis.icon_size_statusbar                  = gtk_icon_size_register ("icon_size_statusbar",                  40, 40);
60   iis.icon_size_indi_video_player_pre_roll = gtk_icon_size_register ("icon_size_indi_video_player_pre_roll", 64, 64);
61   iis.icon_size_indi_key_pad_lock          = gtk_icon_size_register ("icon_size_indi_key_pad_lock",          50, 50);
62   iis.icon_size_indi_copy                  = gtk_icon_size_register ("icon_size_indi_copy",                  64, 64);
63   iis.icon_size_indi_delete                = gtk_icon_size_register ("icon_size_indi_delete",                64, 64);
64   iis.icon_size_indi_process               = gtk_icon_size_register ("icon_size_indi_process",               64, 64);
65   iis.icon_size_indi_progressball          = gtk_icon_size_register ("icon_size_indi_progressball",          64, 64);
66   iis.icon_size_indi_send                  = gtk_icon_size_register ("icon_size_indi_send",                  64, 64);
67   iis.icon_size_indi_offmode_charging      = gtk_icon_size_register ("icon_size_indi_offmode_charging",      50, 50);
68   iis.icon_size_indi_tap_and_hold          = gtk_icon_size_register ("icon_size_indi_tap_and_hold",          34, 34);
69   iis.icon_size_indi_send_receive          = gtk_icon_size_register ("icon_size_indi_send_receive",          64, 64);
70   iis.icon_size_indi_wlan_strength         = gtk_icon_size_register ("icon_size_indi_wlan_strength",         64, 64);
71
72   iis.image_size_indi_nokia_logo           = gtk_icon_size_register ("image_size_indi_nokia_logo",           64, 64);
73   iis.image_size_indi_startup_failed       = gtk_icon_size_register ("image_size_indi_startup_failed",       64, 64);
74   iis.image_size_indi_startup_nokia_logo   = gtk_icon_size_register ("image_size_indi_startup_nokia_logo",   64, 64);
75   iis.image_size_indi_nokia_hands          = gtk_icon_size_register ("image_size_indi_nokia_hands",          64, 64);
76 }
77
78 typedef struct _HildonLogicalData HildonLogicalData;
79
80 struct _HildonLogicalData
81 {
82   GtkRcFlags rcflags;
83   GtkStateType state;
84   gchar *logicalcolorstring;
85   gchar *logicalfontstring;
86 };
87
88
89 static void hildon_change_style_recursive_from_ld (GtkWidget *widget, GtkStyle *prev_style, HildonLogicalData *ld)
90 {
91   /* Change the style for child widgets */
92   if (GTK_IS_CONTAINER (widget)) {
93     GSList *iterator = gtk_container_get_children (GTK_CONTAINER (widget));
94     for (iterator; iterator; iterator = g_list_next (iterator))
95       hildon_change_style_recursive_from_ld (iterator->data, prev_style, ld);
96   }
97
98   /* gtk_widget_modify_*() emit "style_set" signals, so if we got here from
99      "style_set" signal, we need to block this function from being called
100      again or we get into inifinite loop.
101
102      FIXME: Compiling with gcc > 3.3 and -pedantic won't allow
103      conversion between function and object pointers. GLib API however
104      requires an object pointer for a function, so we have to work
105      around this.
106      See http://bugzilla.gnome.org/show_bug.cgi?id=310175
107   */
108   G_GNUC_EXTENSION
109   g_signal_handlers_block_matched (G_OBJECT (widget), G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC,
110                                    g_signal_lookup ("style_set", G_TYPE_FROM_INSTANCE (widget)),
111                                    0, NULL,
112                                    (gpointer) hildon_change_style_recursive_from_ld,
113                                    NULL);
114   
115   if (ld->logicalcolorstring != NULL)
116     {
117       /* Changing logical color */
118       GdkColor color;
119       gtk_widget_ensure_style (widget);
120       if (gtk_style_lookup_logical_color (widget->style, ld->logicalcolorstring, &color) == TRUE)
121         switch (ld->rcflags)
122           {
123             case GTK_RC_FG:
124               gtk_widget_modify_fg (widget, ld->state, &color);
125               break;
126             case GTK_RC_BG:
127               gtk_widget_modify_bg (widget, ld->state, &color);
128               break;
129             case GTK_RC_TEXT:
130               gtk_widget_modify_text (widget, ld->state, &color);
131               break;
132             case GTK_RC_BASE:
133               gtk_widget_modify_base (widget, ld->state, &color);
134               break;
135          } else 
136          {
137            g_warning ("Failed to lookup '%s' color!", ld->logicalcolorstring);
138          }
139     }
140
141   if (ld->logicalfontstring != NULL)
142     {
143       /* Changing logical font */
144       GtkStyle *fontstyle = gtk_rc_get_style_by_paths (gtk_settings_get_default (), ld->logicalfontstring, NULL, G_TYPE_NONE);
145       if (fontstyle != NULL)
146         {
147           PangoFontDescription *fontdesc = fontstyle->font_desc;
148           
149           if (fontdesc != NULL)
150             gtk_widget_modify_font (widget, fontdesc);
151         }
152     }
153    
154
155   /* FIXME: Compilation workaround for gcc > 3.3 + -pedantic again */
156   G_GNUC_EXTENSION
157   g_signal_handlers_unblock_matched (G_OBJECT (widget), G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC,
158                                    g_signal_lookup ("style_set", G_TYPE_FROM_INSTANCE (widget)),
159                                    0, NULL,
160                                    (gpointer) hildon_change_style_recursive_from_ld,
161                                    NULL);
162 }
163
164 static void hildon_logical_data_free (HildonLogicalData *ld)
165 {
166   g_return_if_fail (ld != NULL);
167   
168   if (ld->logicalcolorstring)
169     g_free(ld->logicalcolorstring);
170   
171   if (ld->logicalfontstring)
172     g_free(ld->logicalfontstring);
173   
174   g_free(ld);
175 }
176
177 /**
178  * hildon_gtk_widget_set_logical_font:
179  * @widget : A @GtkWidget to assign this logical font for.
180  * @logicalfontname : A gchar* with the logical font name to assign to the widget with an "osso-" -prefix.
181  * 
182  * This function assigns a defined logical font to the @widget and all its child widgets.
183  * It also connects to the "style_set" signal which will retrieve & assign the new font for the given logical name each time the theme is changed.
184  * The returned signal id can be used to disconnect the signal. 
185  * The previous signal (obtained by calling this function) is disconnected automatically and should not be used. 
186  * 
187  * Return value : The signal id that is triggered every time theme is changed. 0 if font set failed.
188  **/
189 gulong hildon_gtk_widget_set_logical_font (GtkWidget *widget, const gchar *logicalfontname)
190 {
191   HildonLogicalData *ld;
192   gulong signum = 0;
193    
194   g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
195   g_return_val_if_fail (logicalfontname != NULL, 0);
196    
197   ld = g_malloc (sizeof (HildonLogicalData));
198
199   ld->rcflags = 0;
200   ld->state = 0;
201   ld->logicalcolorstring = NULL;
202   ld->logicalfontstring = g_strdup(logicalfontname);
203
204   /* Disconnects the previously connected signals. That calls the closure notify
205    * and effectively disposes the allocated data (hildon_logical_data_free) */
206   g_signal_handlers_disconnect_matched (G_OBJECT (widget), G_SIGNAL_MATCH_FUNC, 
207                                         0, NULL, NULL, 
208                                         G_CALLBACK (hildon_change_style_recursive_from_ld), NULL);
209
210   /* Change the font now */
211   hildon_change_style_recursive_from_ld (widget, NULL, ld);
212
213   /* Connect to "style_set" so that the font gets changed whenever theme changes. */
214   signum = g_signal_connect_data (G_OBJECT (widget), "style_set",
215                                   G_CALLBACK (hildon_change_style_recursive_from_ld),
216                                   ld, (GClosureNotify) hildon_logical_data_free, 0);
217
218   return signum;
219 }
220
221 /**
222  * hildon_gtk_widget_set_logical_color:
223  * @widget : A @GtkWidget to assign this logical font for.
224  * @rcflags : @GtkRcFlags enumeration defining whether to assign to FG, BG, TEXT or BASE style.
225  * @state : @GtkStateType indicating to which state to assign the logical color
226  * @logicalcolorname : A gchar* with the logical font name to assign to the widget.
227  * 
228  * This function assigns a defined logical color to the @widget and all it's child widgets.
229  * It also connects to the "style_set" signal which will retrieve & assign the new color for the given logical name each time the theme is changed.
230  * The returned signal id can be used to disconnect the signal.
231  * The previous signal (obtained by calling this function) is disconnected automatically and should not be used. 
232  * 
233  * Example : If the style you want to modify is bg[NORMAL] then set rcflags to GTK_RC_BG and state to GTK_STATE_NORMAL.
234  * 
235  * Return value : The signal id that is triggered every time theme is changed. 0 if color set failed.
236  **/
237 gulong hildon_gtk_widget_set_logical_color (GtkWidget *widget, GtkRcFlags rcflags,
238                                     GtkStateType state, const gchar *logicalcolorname)
239 {
240   HildonLogicalData *ld;
241   gulong signum = 0;
242   
243   g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
244   g_return_val_if_fail (logicalcolorname != NULL, 0);
245  
246   ld = g_malloc (sizeof (HildonLogicalData));
247
248   ld->rcflags = rcflags;
249   ld->state = state;
250   ld->logicalcolorstring = g_strdup(logicalcolorname);
251   ld->logicalfontstring = NULL;
252
253   /* Disconnects the previously connected signals. That calls the closure notify
254    * and effectively disposes the allocated data (hildon_logical_data_free) */
255   g_signal_handlers_disconnect_matched (G_OBJECT (widget), G_SIGNAL_MATCH_FUNC, 
256                                         0, NULL, NULL, 
257                                         G_CALLBACK (hildon_change_style_recursive_from_ld), NULL);
258   
259   /* Change the colors now */
260   hildon_change_style_recursive_from_ld (widget, NULL, ld);
261
262   /* Connect to "style_set" so that the colors gets changed whenever theme */
263   signum = g_signal_connect_data (G_OBJECT (widget), "style_set",
264                                   G_CALLBACK (hildon_change_style_recursive_from_ld),
265                                   ld, (GClosureNotify) hildon_logical_data_free, 0);
266
267   return signum;
268 }