X-Git-Url: https://vcs.maemo.org/git/?a=blobdiff_plain;f=src%2Fhildon-helper.c;h=cd3026dd62e379dbbe41115c56c52e07d1898ed8;hb=e3a8bb2cb36fb7ee162c1e57333b7a77a8c15e70;hp=22c5af8230268e10088d52d254a7ec32aaa7e51c;hpb=e7c0ffbe7d6773b72e7989842a7df9d2cd18c55c;p=hildon diff --git a/src/hildon-helper.c b/src/hildon-helper.c index 22c5af8..cd3026d 100644 --- a/src/hildon-helper.c +++ b/src/hildon-helper.c @@ -3,7 +3,7 @@ * * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. * - * Contact: Michael Dominic Kostrzewa + * Contact: Rodrigo Novo * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -24,19 +24,19 @@ /** * SECTION:hildon-helper - * @short_description: A collection of usefull utilities and functions. + * @short_description: A collection of useful utilities and functions. * - * Hildon provides some helper functions that can be used for commonly - * performed tasks and functionality blocks. This includes operations + * Hildon provides some helper functions that can be used for commonly + * performed tasks and functionality blocks. This includes operations * on widget styles and probing functions for touch events. - * */ +#undef HILDON_DISABLE_DEPRECATED + #ifdef HAVE_CONFIG_H #include #endif -#include #include "hildon-helper.h" #include "hildon-banner.h" @@ -50,26 +50,145 @@ #define HILDON_FINGER_SIMULATE_BUTTON 2 -struct _HildonLogicalData +struct _HildonLogicalElement { - GtkRcFlags rcflags; + gboolean is_color; /* If FALSE, it's a logical font def */ + GtkRcFlags rc_flags; GtkStateType state; - gchar *logicalcolorstring; - gchar *logicalfontstring; -} typedef HildonLogicalData; + gchar *logical_color_name; + gchar *logical_font_name; +} typedef HildonLogicalElement; + +static void +hildon_logical_element_list_free (GSList *list) +{ + GSList *iterator = list; + + while (iterator) { + HildonLogicalElement *element = (HildonLogicalElement *) iterator->data; + + g_free (element->logical_color_name); + g_free (element->logical_font_name); + g_slice_free (HildonLogicalElement, element); + + iterator = iterator->next; + } + + /* Free the list itself */ + g_slist_free (list); +} + +static GQuark +hildon_helper_logical_data_quark (void) +{ + static GQuark quark = 0; + + if (G_UNLIKELY (quark == 0)) + quark = g_quark_from_static_string ("hildon-logical-data"); + + return quark; +} + +static HildonLogicalElement* +attach_blank_element (GtkWidget *widget, + GSList **style_list) +{ + gboolean first = (*style_list == NULL) ? TRUE : FALSE; + + HildonLogicalElement *element = g_slice_new (HildonLogicalElement); + + element->is_color = FALSE; + element->rc_flags = 0; + element->state = 0; + element->logical_color_name = NULL; + element->logical_font_name = NULL; + + *style_list = g_slist_append (*style_list, element); + + if (first) + g_object_set_qdata_full (G_OBJECT (widget), hildon_helper_logical_data_quark (), *style_list, (GDestroyNotify) hildon_logical_element_list_free); + + return element; +} + +static GSList* +attach_new_font_element (GtkWidget *widget, + const gchar *font_name) +{ + GSList *style_list = g_object_get_qdata (G_OBJECT (widget), hildon_helper_logical_data_quark ()); + HildonLogicalElement *element = NULL; + + /* Try to find an element that already sets a font */ + GSList *iterator = style_list; + while (iterator) { + element = (HildonLogicalElement *) iterator->data; + + if (element->is_color == FALSE) { + /* Reusing ... */ + g_free (element->logical_font_name); + element->logical_font_name = g_strdup (font_name); + return style_list; + } + + iterator = iterator->next; + } + + /* It was not found so we need to create a new one and attach it */ + element = attach_blank_element (widget, &style_list); + element->is_color = FALSE; + element->logical_font_name = g_strdup (font_name); + return style_list; +} + +static GSList* +attach_new_color_element (GtkWidget *widget, + GtkRcFlags flags, + GtkStateType state, + const gchar *color_name) +{ + GSList *style_list = g_object_get_qdata (G_OBJECT (widget), hildon_helper_logical_data_quark ()); + HildonLogicalElement *element = NULL; + + /* Try to find an element that has same flags and state */ + GSList *iterator = style_list; + while (iterator) { + element = (HildonLogicalElement *) iterator->data; + + if (element->rc_flags == flags && + element->state == state && + element->is_color == TRUE) { + /* Reusing ... */ + g_free (element->logical_color_name); + element->logical_color_name = g_strdup (color_name); + return style_list; + } + + iterator = iterator->next; + } + + /* It was not found so we need to create a new one and attach it */ + element = attach_blank_element (widget, &style_list); + element->is_color = TRUE; + element->state = state; + element->rc_flags = flags; + element->logical_color_name = g_strdup (color_name); + return style_list; +} static void -hildon_change_style_recursive_from_ld (GtkWidget *widget, +hildon_change_style_recursive_from_list (GtkWidget *widget, GtkStyle *prev_style, - HildonLogicalData *ld) + GSList *list) { g_assert (GTK_IS_WIDGET (widget)); /* Change the style for child widgets */ if (GTK_IS_CONTAINER (widget)) { - GList *iterator = gtk_container_get_children (GTK_CONTAINER (widget)); - for (iterator = iterator; iterator != NULL; iterator = g_list_next (iterator)) - hildon_change_style_recursive_from_ld (GTK_WIDGET (iterator->data), prev_style, ld); + GList *iterator, *children; + children = gtk_container_get_children (GTK_CONTAINER (widget)); + for (iterator = children; iterator != NULL; iterator = g_list_next (iterator)) + hildon_change_style_recursive_from_list (GTK_WIDGET (iterator->data), prev_style, list); + g_list_free (children); } /* gtk_widget_modify_*() emit "style_set" signals, so if we got here from @@ -87,50 +206,57 @@ hildon_change_style_recursive_from_ld (GtkWidget *widget, g_signal_handlers_block_matched (G_OBJECT (widget), G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC, g_signal_lookup ("style_set", G_TYPE_FROM_INSTANCE (widget)), 0, NULL, - (gpointer) hildon_change_style_recursive_from_ld, + (gpointer) hildon_change_style_recursive_from_list, NULL); - if (ld->logicalcolorstring != NULL) - { - /* Changing logical color */ - GdkColor color; - gtk_widget_ensure_style (widget); - if (gtk_style_lookup_color (widget->style, ld->logicalcolorstring, &color) == TRUE) - switch (ld->rcflags) - { - case GTK_RC_FG: - gtk_widget_modify_fg (widget, ld->state, &color); - break; - - case GTK_RC_BG: - gtk_widget_modify_bg (widget, ld->state, &color); - break; - - case GTK_RC_TEXT: - gtk_widget_modify_text (widget, ld->state, &color); - break; - - case GTK_RC_BASE: - gtk_widget_modify_base (widget, ld->state, &color); - break; - - } else { - g_warning ("Failed to lookup '%s' color!", ld->logicalcolorstring); - } - } - - if (ld->logicalfontstring != NULL) - { - /* Changing logical font */ - GtkStyle *fontstyle = gtk_rc_get_style_by_paths (gtk_settings_get_default (), ld->logicalfontstring, NULL, G_TYPE_NONE); - if (fontstyle != NULL) - { - PangoFontDescription *fontdesc = fontstyle->font_desc; + /* We iterate over all list elements and apply each style + * specification. */ - if (fontdesc != NULL) - gtk_widget_modify_font (widget, fontdesc); + GSList *iterator = list; + while (iterator) { + + HildonLogicalElement *element = (HildonLogicalElement *) iterator->data; + + if (element->is_color == TRUE) { + + /* Changing logical color */ + GdkColor color; + gtk_widget_ensure_style (widget); + if (gtk_style_lookup_color (widget->style, element->logical_color_name, &color) == TRUE) { + + switch (element->rc_flags) + { + case GTK_RC_FG: + gtk_widget_modify_fg (widget, element->state, &color); + break; + + case GTK_RC_BG: + gtk_widget_modify_bg (widget, element->state, &color); + break; + + case GTK_RC_TEXT: + gtk_widget_modify_text (widget, element->state, &color); + break; + + case GTK_RC_BASE: + gtk_widget_modify_base (widget, element->state, &color); + break; + } + } + } else { + + /* Changing logical font */ + GtkStyle *font_style = gtk_rc_get_style_by_paths (gtk_settings_get_default (), element->logical_font_name, NULL, G_TYPE_NONE); + if (font_style != NULL) { + PangoFontDescription *font_desc = font_style->font_desc; + + if (font_desc != NULL) + gtk_widget_modify_font (widget, font_desc); + } } - } + + iterator = iterator->next; + } /* FIXME: Compilation workaround for gcc > 3.3 + -pedantic again */ @@ -138,34 +264,20 @@ hildon_change_style_recursive_from_ld (GtkWidget *widget, g_signal_handlers_unblock_matched (G_OBJECT (widget), G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC, g_signal_lookup ("style_set", G_TYPE_FROM_INSTANCE (widget)), 0, NULL, - (gpointer) hildon_change_style_recursive_from_ld, + (gpointer) hildon_change_style_recursive_from_list, NULL); } -static void -hildon_logical_data_free (HildonLogicalData *ld) -{ - g_return_if_fail (ld != NULL); - - if (ld->logicalcolorstring) - g_free (ld->logicalcolorstring); - - if (ld->logicalfontstring) - g_free (ld->logicalfontstring); - - g_free (ld); -} - /** * hildon_helper_event_button_is_finger: - * @event: A @gtkeventbutton to check + * @event: A #GtkEventButton to check * * Checks if the given button event is a finger event. - * - * return value : TRUE if the event is a finger event. + * + * Return value: TRUE if the event is a finger event. **/ gboolean -hildon_helper_event_button_is_finger (GdkEventButton *event) +hildon_helper_event_button_is_finger (GdkEventButton *event) { gdouble pressure; @@ -188,48 +300,43 @@ hildon_helper_event_button_is_finger (GdkEventButton *event) /** * hildon_helper_set_logical_font: - * @widget : a @gtkwidget to assign this logical font for. - * @logicalfontname : a gchar* with the logical font name to assign to the widget. - * + * @widget: a #GtkWidget to assign this logical font for. + * @logicalfontname: a gchar* with the logical font name to assign to the widget. + * * This function assigns a defined logical font to the @widget and all its child widgets. - * 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. - * The returned signal id can be used to disconnect the signal. - * When calling multiple times the previous signal (obtained by calling this function) is disconnected - * automatically and should not be used. - * - * return value : the signal id that is triggered every time theme is changed. 0 if font set failed. + * 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 + * The returned signal id can be used to disconnect the signal. + * When calling multiple times the previous signal (obtained by calling this function) is disconnected + * automatically and should not be used. + * + * Return value: the signal id that is triggered every time theme is changed. 0 if font set failed. **/ gulong hildon_helper_set_logical_font (GtkWidget *widget, const gchar *logicalfontname) { - HildonLogicalData *ld; gulong signum = 0; + GSList *list; g_return_val_if_fail (GTK_IS_WIDGET (widget), 0); g_return_val_if_fail (logicalfontname != NULL, 0); - ld = g_malloc (sizeof (HildonLogicalData)); - - ld->rcflags = 0; - ld->state = 0; - ld->logicalcolorstring = NULL; - ld->logicalfontstring = g_strdup(logicalfontname); + list = attach_new_font_element (widget, logicalfontname); /* Disconnects the previously connected signals. That calls the closure notify * and effectively disposes the allocated data (hildon_logical_data_free) */ g_signal_handlers_disconnect_matched (G_OBJECT (widget), G_SIGNAL_MATCH_FUNC, - 0, 0, NULL, - G_CALLBACK (hildon_change_style_recursive_from_ld), NULL); + 0, 0, NULL, + G_CALLBACK (hildon_change_style_recursive_from_list), NULL); /* Change the font now */ - hildon_change_style_recursive_from_ld (widget, NULL, ld); + hildon_change_style_recursive_from_list (widget, NULL, list); /* Connect to "style_set" so that the font gets changed whenever theme changes. */ signum = g_signal_connect_data (G_OBJECT (widget), "style_set", - G_CALLBACK (hildon_change_style_recursive_from_ld), - ld, (GClosureNotify) hildon_logical_data_free, 0); + G_CALLBACK (hildon_change_style_recursive_from_list), + list, NULL, 0); return signum; } @@ -262,16 +369,16 @@ show_insensitive_message (GtkWidget *widget, /** - * hildon_helper_set_insensitive_message - * @widget : A @GtkWidget to assign a banner to + * hildon_helper_set_insensitive_message: + * @widget: A #GtkWidget to assign a banner to * @message: A message to display to the user * - * This function assigns an insensitive message to a @widget. When the @widget is + * This function assigns an insensitive message to a @widget. When the @widget is * in an insensitive state and the user activates it, the @message will be displayed - * using a standard @HildonBanner. + * using a standard #HildonBanner. * + * Deprecated: As of hildon 2.2, it is strongly discouraged to use insensitive messages. **/ - void hildon_helper_set_insensitive_message (GtkWidget *widget, const gchar *message) @@ -296,15 +403,15 @@ hildon_helper_set_insensitive_message (GtkWidget *widget, } /** - * hildon_helper_set_insensitive_messagef - * @widget : A @GtkWidget to assign a banner to - * @format : a printf-like format string - * @varargs : arguments for the format string + * hildon_helper_set_insensitive_messagef: + * @widget: A #GtkWidget to assign a banner to + * @format: a printf-like format string + * @Varargs: arguments for the format string * * A version of hildon_helper_set_insensitive_message with string formatting. * + * Deprecated: As of hildon 2.2, it is strongly discouraged to use insensitive messages. **/ - void hildon_helper_set_insensitive_messagef (GtkWidget *widget, const gchar *format, @@ -326,10 +433,10 @@ hildon_helper_set_insensitive_messagef (GtkWidget *widget, /** * hildon_helper_set_logical_color: - * @widget : A @GtkWidget to assign this logical font for. - * @rcflags : @GtkRcFlags enumeration defining whether to assign to FG, BG, TEXT or BASE style. - * @state : @GtkStateType indicating to which state to assign the logical color - * @logicalcolorname : A gchar* with the logical font name to assign to the widget. + * @widget: A #GtkWidget to assign this logical font for. + * @rcflags: #GtkRcFlags enumeration defining whether to assign to FG, BG, TEXT or BASE style. + * @state: #GtkStateType indicating to which state to assign the logical color + * @logicalcolorname: A gchar* with the logical font name to assign to the widget. * * This function assigns a defined logical color to the @widget and all it's child widgets. * It also connects to the "style_set" signal which will retrieve & assign the new color @@ -340,7 +447,7 @@ hildon_helper_set_insensitive_messagef (GtkWidget *widget, * * Example : If the style you want to modify is bg[NORMAL] then set rcflags to GTK_RC_BG and state to GTK_STATE_NORMAL. * - * Return value : The signal id that is triggered every time theme is changed. 0 if color set failed. + * Return value: The signal id that is triggered every time theme is changed. 0 if color set failed. **/ gulong hildon_helper_set_logical_color (GtkWidget *widget, @@ -348,48 +455,41 @@ hildon_helper_set_logical_color (GtkWidget *widget, GtkStateType state, const gchar *logicalcolorname) { - HildonLogicalData *ld; gulong signum = 0; + GSList *list = NULL; g_return_val_if_fail (GTK_IS_WIDGET (widget), 0); g_return_val_if_fail (logicalcolorname != NULL, 0); + + list = attach_new_color_element (widget, rcflags, state, logicalcolorname); - ld = g_malloc (sizeof (HildonLogicalData)); - - ld->rcflags = rcflags; - ld->state = state; - ld->logicalcolorstring = g_strdup (logicalcolorname); - ld->logicalfontstring = NULL; - - /* Disconnects the previously connected signals. That calls the closure notify - * and effectively disposes the allocated data (hildon_logical_data_free) */ + /* Disconnects the previously connected signals. */ g_signal_handlers_disconnect_matched (G_OBJECT (widget), G_SIGNAL_MATCH_FUNC, - 0, 0, NULL, - G_CALLBACK (hildon_change_style_recursive_from_ld), NULL); + 0, 0, NULL, + G_CALLBACK (hildon_change_style_recursive_from_list), NULL); /* Change the colors now */ - hildon_change_style_recursive_from_ld (widget, NULL, ld); + hildon_change_style_recursive_from_list (widget, NULL, list); /* Connect to "style_set" so that the colors gets changed whenever theme */ signum = g_signal_connect_data (G_OBJECT (widget), "style_set", - G_CALLBACK (hildon_change_style_recursive_from_ld), - ld, (GClosureNotify) hildon_logical_data_free, 0); + G_CALLBACK (hildon_change_style_recursive_from_list), + list, NULL, 0); return signum; } /** - * - * hildon_helper_set_thumb_scrollbar - * @win: A @GtkScrolledWindow to use as target + * hildon_helper_set_thumb_scrollbar: + * @win: A #GtkScrolledWindow to use as target * @thumb: TRUE to enable the thumb scrollbar, FALSE to disable * * This function enables a thumb scrollbar on a given scrolled window. It'll convert the - * existing normal scrollbar into a larger, finger-usable scrollbar that works without a stylus. - * As fingerable list rows are fairly high, consider using the whole available vertical space - * of your application for the content in order to have as many rows as possible - * visible on the screen at once. + * existing normal scrollbar into a larger, finger-usable scrollbar that works without a stylus. + * As fingerable list rows are fairly high, consider using the whole available vertical space + * of your application for the content in order to have as many rows as possible + * visible on the screen at once. * * Finger-Sized scrollbar should always be used together with finger-sized content. **/