Big documentation fix mess continued.
[hildon] / src / hildon-helper.c
1 /*
2  * This file is a part of hildon
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.
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-helper
27  * @short_description: A collection of usefull utilities and functions.
28  *
29  * Hildon provides some helper functions that can be used for commonly 
30  * performed tasks and functionality blocks. This includes operations 
31  * on widget styles and probing functions for touch events.
32  *
33  */
34
35 #ifdef                                          HAVE_CONFIG_H
36 #include                                        <config.h>
37 #endif
38
39 #include                                        <gtk/gtk.h>
40 #include                                        "hildon-helper.h"
41
42 #define                                         HILDON_FINGER_PRESSURE_THRESHOLD 0.4
43
44 #define                                         HILDON_FINGER_BUTTON 8
45
46 #define                                         HILDON_FINGER_ALT_BUTTON 1
47
48 #define                                         HILDON_FINGER_ALT_MASK GDK_MOD4_MASK
49
50 #define                                         HILDON_FINGER_SIMULATE_BUTTON 2
51
52 struct                                          _HildonLogicalData
53 {
54     GtkRcFlags rcflags;
55     GtkStateType state;
56     gchar *logicalcolorstring;
57     gchar *logicalfontstring;
58 } typedef                                       HildonLogicalData;
59
60 static void 
61 hildon_change_style_recursive_from_ld           (GtkWidget *widget, 
62                                                  GtkStyle *prev_style, 
63                                                  HildonLogicalData *ld)
64 {
65     g_assert (GTK_IS_WIDGET (widget));
66
67     /* Change the style for child widgets */
68     if (GTK_IS_CONTAINER (widget)) {
69         GList *iterator = gtk_container_get_children (GTK_CONTAINER (widget));
70         for (iterator = iterator; iterator != NULL; iterator = g_list_next (iterator))
71             hildon_change_style_recursive_from_ld (GTK_WIDGET (iterator->data), prev_style, ld);
72     }
73
74     /* gtk_widget_modify_*() emit "style_set" signals, so if we got here from
75        "style_set" signal, we need to block this function from being called
76        again or we get into inifinite loop.
77
78     FIXME: Compiling with gcc > 3.3 and -pedantic won't allow
79     conversion between function and object pointers. GLib API however
80     requires an object pointer for a function, so we have to work
81     around this.
82     See http://bugzilla.gnome.org/show_bug.cgi?id=310175
83     */
84
85     G_GNUC_EXTENSION
86         g_signal_handlers_block_matched (G_OBJECT (widget), G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC,
87                 g_signal_lookup ("style_set", G_TYPE_FROM_INSTANCE (widget)),
88                 0, NULL,
89                 (gpointer) hildon_change_style_recursive_from_ld,
90                 NULL);
91
92     if (ld->logicalcolorstring != NULL)
93     {
94         /* Changing logical color */
95         GdkColor color;
96         gtk_widget_ensure_style (widget);
97         if (gtk_style_lookup_color (widget->style, ld->logicalcolorstring, &color) == TRUE)
98             switch (ld->rcflags)
99             {
100                 case GTK_RC_FG:
101                     gtk_widget_modify_fg (widget, ld->state, &color);
102                     break;
103
104                 case GTK_RC_BG:
105                     gtk_widget_modify_bg (widget, ld->state, &color);
106                     break;
107
108                 case GTK_RC_TEXT:
109                     gtk_widget_modify_text (widget, ld->state, &color);
110                     break;
111
112                 case GTK_RC_BASE:
113                     gtk_widget_modify_base (widget, ld->state, &color);
114                     break;
115
116             } else {
117                 g_warning ("Failed to lookup '%s' color!", ld->logicalcolorstring);
118             }
119     }
120
121     if (ld->logicalfontstring != NULL)
122     {
123         /* Changing logical font */
124         GtkStyle *fontstyle = gtk_rc_get_style_by_paths (gtk_settings_get_default (), ld->logicalfontstring, NULL, G_TYPE_NONE);
125         if (fontstyle != NULL)
126         {
127             PangoFontDescription *fontdesc = fontstyle->font_desc;
128
129             if (fontdesc != NULL)
130                 gtk_widget_modify_font (widget, fontdesc);
131         }
132     }
133
134     /* FIXME: Compilation workaround for gcc > 3.3 + -pedantic again */
135
136     G_GNUC_EXTENSION
137         g_signal_handlers_unblock_matched (G_OBJECT (widget), G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC,
138                 g_signal_lookup ("style_set", G_TYPE_FROM_INSTANCE (widget)),
139                 0, NULL,
140                 (gpointer) hildon_change_style_recursive_from_ld,
141                 NULL);
142 }
143
144 static void 
145 hildon_logical_data_free                        (HildonLogicalData *ld)
146 {
147     g_return_if_fail (ld != NULL);
148
149     if (ld->logicalcolorstring)
150         g_free (ld->logicalcolorstring);
151
152     if (ld->logicalfontstring)
153         g_free (ld->logicalfontstring);
154
155     g_free (ld);
156 }
157
158 /**
159  * hildon_helper_event_button_is_finger:
160  * @event: A @gtkeventbutton to check
161  *
162  * Checks if the given button event is a finger event.
163  * 
164  * return value : TRUE if the event is a finger event.
165  **/
166 gboolean 
167 hildon_helper_event_button_is_finger (GdkEventButton *event)
168 {
169     gdouble pressure;
170
171     if (gdk_event_get_axis ((GdkEvent*) event, GDK_AXIS_PRESSURE, &pressure) &&
172         pressure > HILDON_FINGER_PRESSURE_THRESHOLD)
173         return TRUE;
174
175     if (event->button == HILDON_FINGER_BUTTON)
176         return TRUE;
177
178     if (event->button == HILDON_FINGER_ALT_BUTTON &&
179         event->state & HILDON_FINGER_ALT_MASK)
180         return TRUE;
181
182     if (event->button == HILDON_FINGER_SIMULATE_BUTTON)
183         return TRUE;
184
185     return FALSE;
186 }
187
188 /**
189  * hildon_helper_set_logical_font:
190  * @widget : a @gtkwidget to assign this logical font for.
191  * @logicalfontname : a gchar* with the logical font name to assign to the widget.
192  * 
193  * This function assigns a defined logical font to the @widget and all its child widgets.
194  * it also connects to the "style_set" signal which will retrieve & assign the new font 
195  * for the given logical name each time the theme is changed.
196  * The returned signal id can be used to disconnect the signal. 
197  * When calling multiple times the previous signal (obtained by calling this function) is disconnected 
198  * automatically and should not be used. 
199  * 
200  * return value : the signal id that is triggered every time theme is changed. 0 if font set failed.
201  **/
202 gulong
203 hildon_helper_set_logical_font                  (GtkWidget *widget, 
204                                                  const gchar *logicalfontname)
205 {
206     HildonLogicalData *ld;
207     gulong signum = 0;
208
209     g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
210     g_return_val_if_fail (logicalfontname != NULL, 0);
211
212     ld = g_malloc (sizeof (HildonLogicalData));
213
214     ld->rcflags = 0;
215     ld->state = 0;
216     ld->logicalcolorstring = NULL;
217     ld->logicalfontstring = g_strdup(logicalfontname);
218
219     /* Disconnects the previously connected signals. That calls the closure notify
220      * and effectively disposes the allocated data (hildon_logical_data_free) */
221     g_signal_handlers_disconnect_matched (G_OBJECT (widget), G_SIGNAL_MATCH_FUNC, 
222             0, 0, NULL, 
223             G_CALLBACK (hildon_change_style_recursive_from_ld), NULL);
224
225     /* Change the font now */
226     hildon_change_style_recursive_from_ld (widget, NULL, ld);
227
228     /* Connect to "style_set" so that the font gets changed whenever theme changes. */
229     signum = g_signal_connect_data (G_OBJECT (widget), "style_set",
230             G_CALLBACK (hildon_change_style_recursive_from_ld),
231             ld, (GClosureNotify) hildon_logical_data_free, 0);
232
233     return signum;
234 }
235
236 /**
237  * hildon_helper_set_logical_color:
238  * @widget : A @GtkWidget to assign this logical font for.
239  * @rcflags : @GtkRcFlags enumeration defining whether to assign to FG, BG, TEXT or BASE style.
240  * @state : @GtkStateType indicating to which state to assign the logical color
241  * @logicalcolorname : A gchar* with the logical font name to assign to the widget.
242  * 
243  * This function assigns a defined logical color to the @widget and all it's child widgets.
244  * It also connects to the "style_set" signal which will retrieve & assign the new color 
245  * for the given logical name each time the theme is changed.
246  * The returned signal id can be used to disconnect the signal.
247  * When calling multiple times the previous signal (obtained by calling this function) is disconnected 
248  * automatically and should not be used. 
249  * 
250  * Example : If the style you want to modify is bg[NORMAL] then set rcflags to GTK_RC_BG and state to GTK_STATE_NORMAL.
251  * 
252  * Return value : The signal id that is triggered every time theme is changed. 0 if color set failed.
253  **/
254 gulong 
255 hildon_helper_set_logical_color                 (GtkWidget *widget, 
256                                                  GtkRcFlags rcflags,
257                                                  GtkStateType state, 
258                                                  const gchar *logicalcolorname)
259 {
260     HildonLogicalData *ld;
261     gulong signum = 0;
262
263     g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
264     g_return_val_if_fail (logicalcolorname != NULL, 0);
265
266     ld = g_malloc (sizeof (HildonLogicalData));
267
268     ld->rcflags = rcflags;
269     ld->state = state;
270     ld->logicalcolorstring = g_strdup (logicalcolorname);
271     ld->logicalfontstring = NULL;
272
273     /* Disconnects the previously connected signals. That calls the closure notify
274      * and effectively disposes the allocated data (hildon_logical_data_free) */
275     g_signal_handlers_disconnect_matched (G_OBJECT (widget), G_SIGNAL_MATCH_FUNC, 
276             0, 0, NULL, 
277             G_CALLBACK (hildon_change_style_recursive_from_ld), NULL);
278
279     /* Change the colors now */
280     hildon_change_style_recursive_from_ld (widget, NULL, ld);
281
282     /* Connect to "style_set" so that the colors gets changed whenever theme */
283     signum = g_signal_connect_data (G_OBJECT (widget), "style_set",
284             G_CALLBACK (hildon_change_style_recursive_from_ld),
285             ld, (GClosureNotify) hildon_logical_data_free, 0);
286
287     return signum;
288 }
289
290