2 * This file is a part of hildon
4 * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved.
6 * Contact: Michael Dominic Kostrzewa <michael.kostrzewa@nokia.com>
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
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.
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
26 * SECTION:hildon-helper
27 * @short_description: A collection of usefull utilities and functions.
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.
40 #include "hildon-helper.h"
41 #include "hildon-banner.h"
43 #define HILDON_FINGER_PRESSURE_THRESHOLD 0.4
45 #define HILDON_FINGER_BUTTON 8
47 #define HILDON_FINGER_ALT_BUTTON 1
49 #define HILDON_FINGER_ALT_MASK GDK_MOD4_MASK
51 #define HILDON_FINGER_SIMULATE_BUTTON 2
53 struct _HildonLogicalData
57 gchar *logicalcolorstring;
58 gchar *logicalfontstring;
59 } typedef HildonLogicalData;
62 hildon_change_style_recursive_from_ld (GtkWidget *widget,
64 HildonLogicalData *ld)
66 g_assert (GTK_IS_WIDGET (widget));
68 /* Change the style for child widgets */
69 if (GTK_IS_CONTAINER (widget)) {
70 GList *iterator = gtk_container_get_children (GTK_CONTAINER (widget));
71 for (iterator = iterator; iterator != NULL; iterator = g_list_next (iterator))
72 hildon_change_style_recursive_from_ld (GTK_WIDGET (iterator->data), prev_style, ld);
75 /* gtk_widget_modify_*() emit "style_set" signals, so if we got here from
76 "style_set" signal, we need to block this function from being called
77 again or we get into inifinite loop.
79 FIXME: Compiling with gcc > 3.3 and -pedantic won't allow
80 conversion between function and object pointers. GLib API however
81 requires an object pointer for a function, so we have to work
83 See http://bugzilla.gnome.org/show_bug.cgi?id=310175
87 g_signal_handlers_block_matched (G_OBJECT (widget), G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC,
88 g_signal_lookup ("style_set", G_TYPE_FROM_INSTANCE (widget)),
90 (gpointer) hildon_change_style_recursive_from_ld,
93 if (ld->logicalcolorstring != NULL)
95 /* Changing logical color */
97 gtk_widget_ensure_style (widget);
98 if (gtk_style_lookup_color (widget->style, ld->logicalcolorstring, &color) == TRUE)
102 gtk_widget_modify_fg (widget, ld->state, &color);
106 gtk_widget_modify_bg (widget, ld->state, &color);
110 gtk_widget_modify_text (widget, ld->state, &color);
114 gtk_widget_modify_base (widget, ld->state, &color);
118 g_warning ("Failed to lookup '%s' color!", ld->logicalcolorstring);
122 if (ld->logicalfontstring != NULL)
124 /* Changing logical font */
125 GtkStyle *fontstyle = gtk_rc_get_style_by_paths (gtk_settings_get_default (), ld->logicalfontstring, NULL, G_TYPE_NONE);
126 if (fontstyle != NULL)
128 PangoFontDescription *fontdesc = fontstyle->font_desc;
130 if (fontdesc != NULL)
131 gtk_widget_modify_font (widget, fontdesc);
135 /* FIXME: Compilation workaround for gcc > 3.3 + -pedantic again */
138 g_signal_handlers_unblock_matched (G_OBJECT (widget), G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC,
139 g_signal_lookup ("style_set", G_TYPE_FROM_INSTANCE (widget)),
141 (gpointer) hildon_change_style_recursive_from_ld,
146 hildon_logical_data_free (HildonLogicalData *ld)
148 g_return_if_fail (ld != NULL);
150 if (ld->logicalcolorstring)
151 g_free (ld->logicalcolorstring);
153 if (ld->logicalfontstring)
154 g_free (ld->logicalfontstring);
160 * hildon_helper_event_button_is_finger:
161 * @event: A @gtkeventbutton to check
163 * Checks if the given button event is a finger event.
165 * return value : TRUE if the event is a finger event.
168 hildon_helper_event_button_is_finger (GdkEventButton *event)
172 if (gdk_event_get_axis ((GdkEvent*) event, GDK_AXIS_PRESSURE, &pressure) &&
173 pressure > HILDON_FINGER_PRESSURE_THRESHOLD)
176 if (event->button == HILDON_FINGER_BUTTON)
179 if (event->button == HILDON_FINGER_ALT_BUTTON &&
180 event->state & HILDON_FINGER_ALT_MASK)
183 if (event->button == HILDON_FINGER_SIMULATE_BUTTON)
190 * hildon_helper_set_logical_font:
191 * @widget : a @gtkwidget to assign this logical font for.
192 * @logicalfontname : a gchar* with the logical font name to assign to the widget.
194 * This function assigns a defined logical font to the @widget and all its child widgets.
195 * it also connects to the "style_set" signal which will retrieve & assign the new font
196 * for the given logical name each time the theme is changed.
197 * The returned signal id can be used to disconnect the signal.
198 * When calling multiple times the previous signal (obtained by calling this function) is disconnected
199 * automatically and should not be used.
201 * return value : the signal id that is triggered every time theme is changed. 0 if font set failed.
204 hildon_helper_set_logical_font (GtkWidget *widget,
205 const gchar *logicalfontname)
207 HildonLogicalData *ld;
210 g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
211 g_return_val_if_fail (logicalfontname != NULL, 0);
213 ld = g_malloc (sizeof (HildonLogicalData));
217 ld->logicalcolorstring = NULL;
218 ld->logicalfontstring = g_strdup(logicalfontname);
220 /* Disconnects the previously connected signals. That calls the closure notify
221 * and effectively disposes the allocated data (hildon_logical_data_free) */
222 g_signal_handlers_disconnect_matched (G_OBJECT (widget), G_SIGNAL_MATCH_FUNC,
224 G_CALLBACK (hildon_change_style_recursive_from_ld), NULL);
226 /* Change the font now */
227 hildon_change_style_recursive_from_ld (widget, NULL, ld);
229 /* Connect to "style_set" so that the font gets changed whenever theme changes. */
230 signum = g_signal_connect_data (G_OBJECT (widget), "style_set",
231 G_CALLBACK (hildon_change_style_recursive_from_ld),
232 ld, (GClosureNotify) hildon_logical_data_free, 0);
238 hildon_helper_insensitive_message_quark (void)
240 static GQuark quark = 0;
242 if (G_UNLIKELY (quark == 0))
243 quark = g_quark_from_static_string ("hildon-insensitive-message");
250 show_insensitive_message (GtkWidget *widget, gpointer user_data)
252 gchar *message = NULL;
254 g_assert (GTK_IS_WIDGET (widget));
256 message = (gchar*) g_object_get_qdata (G_OBJECT (widget),
257 hildon_helper_insensitive_message_quark ());
260 hildon_banner_show_information (widget, NULL, message);
265 * hildon_helper_set_insensitive_message
266 * @widget : A @GtkWidget to assign a banner to
267 * @message: A message to display to the user
269 * This function assigns an insensitive message to a @widget. When the @widget is
270 * in an insensitive state and the user activates it, the @message will be displayed
271 * using a standard @HildonBanner.
276 hildon_helper_set_insensitive_message (GtkWidget *widget,
277 const gchar *message)
279 g_return_if_fail (GTK_IS_WIDGET (widget));
280 g_return_if_fail (message != NULL);
282 gpointer stored_message;
284 /* Clean up any previous instance of the insensitive message */
285 g_signal_handlers_disconnect_matched (G_OBJECT (widget), G_SIGNAL_MATCH_FUNC,
287 G_CALLBACK (show_insensitive_message), NULL);
289 stored_message = g_object_get_qdata (G_OBJECT (widget), hildon_helper_insensitive_message_quark ());
291 g_free (stored_message);
293 /* We need to dup the string because the pointer might not be valid when the
294 insensitive-press signal callback is executed */
295 g_object_set_qdata_full (G_OBJECT (widget), hildon_helper_insensitive_message_quark (),
296 (gpointer)g_strdup (message),
299 if (message != NULL) {
300 g_signal_connect (G_OBJECT (widget), "insensitive-press",
301 G_CALLBACK (show_insensitive_message), NULL);
306 * hildon_helper_set_insensitive_messagef
307 * @widget : A @GtkWidget to assign a banner to
308 * @format : a printf-like format string
309 * @varargs : arguments for the format string
311 * A version of hildon_helper_set_insensitive_message with string formatting.
316 hildon_helper_set_insensitive_messagef (GtkWidget *widget,
320 g_return_if_fail (GTK_IS_WIDGET (widget));
325 va_start (args, format);
326 message = g_strdup_vprintf (format, args);
329 hildon_helper_set_insensitive_message (widget, message);
335 * hildon_helper_set_logical_color:
336 * @widget : A @GtkWidget to assign this logical font for.
337 * @rcflags : @GtkRcFlags enumeration defining whether to assign to FG, BG, TEXT or BASE style.
338 * @state : @GtkStateType indicating to which state to assign the logical color
339 * @logicalcolorname : A gchar* with the logical font name to assign to the widget.
341 * This function assigns a defined logical color to the @widget and all it's child widgets.
342 * It also connects to the "style_set" signal which will retrieve & assign the new color
343 * for the given logical name each time the theme is changed.
344 * The returned signal id can be used to disconnect the signal.
345 * When calling multiple times the previous signal (obtained by calling this function) is disconnected
346 * automatically and should not be used.
348 * Example : If the style you want to modify is bg[NORMAL] then set rcflags to GTK_RC_BG and state to GTK_STATE_NORMAL.
350 * Return value : The signal id that is triggered every time theme is changed. 0 if color set failed.
353 hildon_helper_set_logical_color (GtkWidget *widget,
356 const gchar *logicalcolorname)
358 HildonLogicalData *ld;
361 g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
362 g_return_val_if_fail (logicalcolorname != NULL, 0);
364 ld = g_malloc (sizeof (HildonLogicalData));
366 ld->rcflags = rcflags;
368 ld->logicalcolorstring = g_strdup (logicalcolorname);
369 ld->logicalfontstring = NULL;
371 /* Disconnects the previously connected signals. That calls the closure notify
372 * and effectively disposes the allocated data (hildon_logical_data_free) */
373 g_signal_handlers_disconnect_matched (G_OBJECT (widget), G_SIGNAL_MATCH_FUNC,
375 G_CALLBACK (hildon_change_style_recursive_from_ld), NULL);
377 /* Change the colors now */
378 hildon_change_style_recursive_from_ld (widget, NULL, ld);
380 /* Connect to "style_set" so that the colors gets changed whenever theme */
381 signum = g_signal_connect_data (G_OBJECT (widget), "style_set",
382 G_CALLBACK (hildon_change_style_recursive_from_ld),
383 ld, (GClosureNotify) hildon_logical_data_free, 0);