2 * This file is a part of hildon
4 * Copyright (C) 2005, 2006, 2007 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
11 * the License, or (at your option) any later version.
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-banner
27 * @short_description: A widget used to display timed notifications.
29 * #HildonBanner can be used to display a short, timed notification
30 * or information to the user. It can communicate that a
31 * task has been finished or the application state has changed.
32 * Banners should be used only to display non-critical pieces of
41 #include "hildon-banner.h"
42 #include <gtk/gtkhbox.h>
43 #include <gtk/gtkimage.h>
44 #include <gtk/gtkicontheme.h>
47 #include <X11/Xatom.h>
48 #include "hildon-defines.h"
49 #include "hildon-banner-private.h"
51 /* position relative to the screen */
53 #define HILDON_BANNER_WINDOW_X 30
55 #define HILDON_BANNER_WINDOW_Y 73
57 #define HILDON_BANNER_WINDOW_FULLSCREEN_Y 20
61 #define HILDON_BANNER_PROGRESS_WIDTH 104
63 #define HILDON_BANNER_LABEL_MAX_TIMED 375
65 #define HILDON_BANNER_LABEL_MAX_PROGRESS 375 /*265*/
69 #define HILDON_BANNER_DEFAULT_TIMEOUT 3000
73 #define HILDON_BANNER_DEFAULT_ICON "qgn_note_infoprint"
75 #define HILDON_BANNER_DEFAULT_PROGRESS_ANIMATION "qgn_indi_pball_a"
85 static GtkWidget* global_timed_banner = NULL;
88 get_current_app_window (void);
91 check_fullscreen_state (Window window);
94 hildon_banner_timed_quark (void);
97 hildon_banner_bind_label_style (HildonBanner *self,
101 hildon_banner_timeout (gpointer data);
104 hildon_banner_clear_timeout (HildonBanner *self);
107 hildon_banner_ensure_timeout (HildonBanner *self);
110 hildon_banner_set_property (GObject *object,
116 hildon_banner_get_property (GObject *object,
122 hildon_banner_destroy (GtkObject *object);
125 hildon_banner_real_get_instance (GObject *window,
129 hildon_banner_constructor (GType type,
130 guint n_construct_params,
131 GObjectConstructParam *construct_params);
134 hildon_banner_finalize (GObject *object);
137 hildon_banner_map_event (GtkWidget *widget,
141 force_to_wrap_truncated (HildonBanner *banner);
144 hildon_banner_check_position (GtkWidget *widget);
147 hildon_banner_realize (GtkWidget *widget);
150 hildon_banner_class_init (HildonBannerClass *klass);
153 hildon_banner_init (HildonBanner *self);
156 hildon_banner_ensure_child (HildonBanner *self,
157 GtkWidget *user_widget,
160 const gchar *first_property,
164 hildon_banner_get_instance_for_widget (GtkWidget *widget,
167 static GtkWindowClass* parent_class = NULL;
170 * hildon_banner_get_type:
172 * Initializes and returns the type of a hildon banner.
174 * @Returns: GType of #HildonBanner
177 hildon_banner_get_type (void)
179 static GType banner_type = 0;
183 static const GTypeInfo banner_info = {
184 sizeof (HildonBannerClass),
185 NULL, /* base_init */
186 NULL, /* base_finalize */
187 (GClassInitFunc) hildon_banner_class_init,
188 NULL, /* class_finalize */
189 NULL, /* class_data */
190 sizeof (HildonBanner),
192 (GInstanceInitFunc) hildon_banner_init,
194 banner_type = g_type_register_static (GTK_TYPE_WINDOW,
195 "HildonBanner", &banner_info, 0 );
200 /* copy/paste from old infoprint implementation: Use matchbox
201 properties to find the topmost application window */
203 get_current_app_window (void)
210 Atom atom_current_app_window = gdk_x11_get_xatom_by_name ("_MB_CURRENT_APP_WINDOW");
212 Window win_result = None;
213 guchar *data_return = NULL;
215 status = XGetWindowProperty (GDK_DISPLAY(), GDK_ROOT_WINDOW (),
216 atom_current_app_window, 0L, 16L,
217 0, XA_WINDOW, &realType, &format,
221 if (status == Success && realType == XA_WINDOW && format == 32 && n == 1 && data_return != NULL)
223 win_result = ((Window*) data_return)[0];
232 /* Checks if a window is in fullscreen state or not. This
233 information is needed when banners are positioned on screen.
234 copy/paste from old infoprint implementation. */
236 check_fullscreen_state (Window window)
240 int format, status, i;
241 guchar *data_return = NULL;
244 Atom atom_window_state = gdk_x11_get_xatom_by_name ("_NET_WM_STATE");
245 Atom atom_fullscreen = gdk_x11_get_xatom_by_name ("_NET_WM_STATE_FULLSCREEN");
250 /* in some cases XGetWindowProperty seems to generate BadWindow,
251 so at the moment this function does not always work perfectly */
252 gdk_error_trap_push ();
253 status = XGetWindowProperty (GDK_DISPLAY (), window,
254 atom_window_state, 0L, 1000000L,
255 0, XA_ATOM, &realType, &format,
256 &n, &extra, &data_return);
260 if (gdk_error_trap_pop ())
263 if (status == Success && realType == XA_ATOM && format == 32 && n > 0)
265 for (i=0; i < n; i++)
266 if (((Atom*)data_return)[i] && ((Atom*)data_return)[i] == atom_fullscreen)
268 if (data_return) XFree (data_return);
280 hildon_banner_timed_quark (void)
282 static GQuark quark = 0;
284 if (G_UNLIKELY(quark == 0))
285 quark = g_quark_from_static_string ("hildon-banner-timed");
290 /* Set the label name to make the correct rc-style attached into it */
292 hildon_banner_bind_label_style (HildonBanner *self,
295 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
298 GtkWidget *label = priv->label;
300 /* Too bad that we cannot really reset the widget name */
301 gtk_widget_set_name (label, name ? name : g_type_name (GTK_WIDGET_TYPE (label)));
304 /* In timeout function we automatically destroy timed banners */
306 hildon_banner_timeout (gpointer data)
310 gboolean continue_timeout = FALSE;
312 GDK_THREADS_ENTER ();
314 g_assert (HILDON_IS_BANNER (data));
316 widget = GTK_WIDGET (data);
317 g_object_ref (widget);
319 /* If the banner is currently visible (it normally should),
320 we simulate clicking the close button of the window.
321 This allows applications to reuse the banner by prevent
323 if (GTK_WIDGET_DRAWABLE (widget))
325 event = gdk_event_new (GDK_DELETE);
326 event->any.window = g_object_ref (widget->window);
327 event->any.send_event = FALSE;
328 continue_timeout = gtk_widget_event (widget, event);
329 gdk_event_free (event);
332 if (! continue_timeout)
333 gtk_widget_destroy (widget);
335 g_object_unref (widget);
337 GDK_THREADS_LEAVE ();
339 return continue_timeout;
343 hildon_banner_clear_timeout (HildonBanner *self)
345 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
348 if (priv->timeout_id != 0) {
349 g_source_remove (priv->timeout_id);
350 priv->timeout_id = 0;
358 hildon_banner_ensure_timeout (HildonBanner *self)
360 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
363 if (priv->timeout_id == 0 && priv->is_timed && priv->timeout > 0)
364 priv->timeout_id = g_timeout_add (priv->timeout,
365 hildon_banner_timeout, self);
369 hildon_banner_set_property (GObject *object,
376 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
382 priv->timeout = g_value_get_uint (value);
386 priv->is_timed = g_value_get_boolean (value);
388 /* Timed and progress notifications have different
389 pixel size values for text.
390 We force to use requisition size for timed banners
391 in order to avoid resize problems when reusing the
392 window (see bug #24339) */
393 geom.max_width = priv->is_timed ? -1
394 : HILDON_BANNER_LABEL_MAX_PROGRESS;
395 geom.max_height = -1;
396 gtk_window_set_geometry_hints (GTK_WINDOW (object),
397 priv->label, &geom, GDK_HINT_MAX_SIZE);
400 case PROP_PARENT_WINDOW:
401 window = g_value_get_object (value);
403 g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent);
406 gtk_window_set_transient_for (GTK_WINDOW (object), (GtkWindow *) window);
407 priv->parent = (GtkWindow *) window;
410 gtk_window_set_destroy_with_parent (GTK_WINDOW (object), TRUE);
411 g_object_add_weak_pointer(G_OBJECT (window), (gpointer) &priv->parent);
417 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
423 hildon_banner_get_property (GObject *object,
428 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
434 g_value_set_uint (value, priv->timeout);
438 g_value_set_boolean (value, priv->is_timed);
441 case PROP_PARENT_WINDOW:
442 g_value_set_object (value, gtk_window_get_transient_for (GTK_WINDOW (object)));
446 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
452 hildon_banner_destroy (GtkObject *object)
454 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
458 GObject *parent_window = (GObject *) priv->parent;
460 g_assert (HILDON_IS_BANNER (object));
461 self = HILDON_BANNER (object);
463 /* Drop possible global pointer. That can hold reference to us */
464 if ((gpointer) object == (gpointer) global_timed_banner) {
465 global_timed_banner = NULL;
466 g_object_unref (object);
469 /* Remove the data from parent window for timed banners. Those hold reference */
470 if (priv->is_timed && parent_window != NULL) {
471 g_object_set_qdata (parent_window, hildon_banner_timed_quark (), NULL);
474 (void) hildon_banner_clear_timeout (self);
476 if (GTK_OBJECT_CLASS (parent_class)->destroy)
477 GTK_OBJECT_CLASS (parent_class)->destroy (object);
480 /* Search a previous banner instance */
482 hildon_banner_real_get_instance (GObject *window,
486 /* If we have a parent window, the previous instance is stored there */
488 return g_object_get_qdata(window, hildon_banner_timed_quark ());
491 /* System notification instance is stored into global pointer */
492 return (GObject *) global_timed_banner;
495 /* Non-timed banners are normal (non-singleton) objects */
499 /* By overriding constructor we force timed banners to be
500 singletons for each window */
502 hildon_banner_constructor (GType type,
503 guint n_construct_params,
504 GObjectConstructParam *construct_params)
506 GObject *banner, *window = NULL;
507 gboolean timed = FALSE;
510 /* Search banner type information from parameters in order
511 to locate the possible previous banner instance. */
512 for (i = 0; i < n_construct_params; i++)
514 if (strcmp(construct_params[i].pspec->name, "parent-window") == 0)
515 window = g_value_get_object (construct_params[i].value);
516 else if (strcmp(construct_params[i].pspec->name, "is-timed") == 0)
517 timed = g_value_get_boolean (construct_params[i].value);
520 /* Try to get a previous instance if such exists */
521 banner = hildon_banner_real_get_instance (window, timed);
524 /* We have to create a new banner */
525 banner = G_OBJECT_CLASS (parent_class)->constructor (type, n_construct_params, construct_params);
527 /* Store the newly created singleton instance either into parent
528 window data or into global variables. */
531 g_object_set_qdata_full (G_OBJECT (window), hildon_banner_timed_quark (),
532 g_object_ref (banner), g_object_unref);
534 g_assert (global_timed_banner == NULL);
535 global_timed_banner = g_object_ref (banner);
540 /* FIXME: This is a hack! We have to manually freeze
541 notifications. This is normally done by g_object_init, but we
542 are not going to call that. g_object_newv will otherwise give
543 a critical like this:
545 GLIB CRITICAL ** GLib-GObject - g_object_notify_queue_thaw:
546 assertion `nqueue->freeze_count > 0' failed */
548 g_object_freeze_notify (banner);
551 /* We restart possible timeouts for each new timed banner request */
552 if (timed && hildon_banner_clear_timeout (HILDON_BANNER (banner)))
553 hildon_banner_ensure_timeout (HILDON_BANNER(banner));
559 hildon_banner_finalize (GObject *object)
561 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
564 g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent);
567 G_OBJECT_CLASS (parent_class)->finalize (object);
570 /* We start the timer for timed notifications after the window appears on screen */
572 hildon_banner_map_event (GtkWidget *widget,
575 gboolean result = FALSE;
577 if (GTK_WIDGET_CLASS (parent_class)->map_event)
578 result = GTK_WIDGET_CLASS (parent_class)->map_event (widget, event);
580 hildon_banner_ensure_timeout (HILDON_BANNER(widget));
586 /* force to wrap truncated label by setting explicit size request
587 * see N#27000 and G#329646 */
589 force_to_wrap_truncated (HildonBanner *banner)
593 int width_text, width_max;
595 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (banner);
598 label = GTK_LABEL (priv->label);
600 layout = gtk_label_get_layout (label);
601 width_text = PANGO_PIXELS(pango_layout_get_width (layout));
602 /* = width to which the lines of the PangoLayout should be wrapped */
604 width_max = priv->is_timed ? HILDON_BANNER_LABEL_MAX_TIMED
605 : HILDON_BANNER_LABEL_MAX_PROGRESS;
607 if (width_text >= width_max) {
608 /* explicitly request maximum size to force wrapping */
609 PangoRectangle logical;
611 pango_layout_set_width (layout, width_max * PANGO_SCALE);
612 pango_layout_get_extents (layout, NULL, &logical);
614 width = PANGO_PIXELS (logical.width);
617 /* use fixed width when wrapping or natural one otherwise */
618 gtk_widget_set_size_request (GTK_WIDGET (label), width, -1);
623 hildon_banner_check_position (GtkWidget *widget)
628 force_to_wrap_truncated (HILDON_BANNER(widget)); /* see N#27000 and G#329646 */
630 gtk_widget_size_request (widget, &req);
637 x = gdk_screen_width() - HILDON_BANNER_WINDOW_X - req.width;
638 y = check_fullscreen_state (get_current_app_window ()) ?
639 HILDON_BANNER_WINDOW_FULLSCREEN_Y : HILDON_BANNER_WINDOW_Y;
641 gtk_window_move (GTK_WINDOW (widget), x, y);
645 hildon_banner_realize (GtkWidget *widget)
647 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (widget);
650 /* We let the parent to init widget->window before we need it */
651 if (GTK_WIDGET_CLASS (parent_class)->realize)
652 GTK_WIDGET_CLASS (parent_class)->realize (widget);
654 /* We use special hint to turn the banner into information notification. */
655 gdk_window_set_type_hint (widget->window, GDK_WINDOW_TYPE_HINT_NOTIFICATION);
656 gtk_window_set_transient_for (GTK_WINDOW (widget), (GtkWindow *) priv->parent);
658 hildon_banner_check_position (widget);
662 hildon_banner_class_init (HildonBannerClass *klass)
664 GObjectClass *object_class;
665 GtkWidgetClass *widget_class;
667 object_class = G_OBJECT_CLASS (klass);
668 widget_class = GTK_WIDGET_CLASS (klass);
669 parent_class = g_type_class_peek_parent (klass);
671 /* Append private structure to class. This is more elegant than
672 on g_new based approach */
673 g_type_class_add_private (klass, sizeof (HildonBannerPrivate));
675 /* Override virtual methods */
676 object_class->constructor = hildon_banner_constructor;
677 object_class->finalize = hildon_banner_finalize;
678 object_class->set_property = hildon_banner_set_property;
679 object_class->get_property = hildon_banner_get_property;
680 GTK_OBJECT_CLASS (klass)->destroy = hildon_banner_destroy;
681 widget_class->map_event = hildon_banner_map_event;
682 widget_class->realize = hildon_banner_realize;
684 /* Install properties.
685 We need construct properties for singleton purposes */
688 * HildonBanner:parent-window:
690 * The window for which the banner will be singleton.
693 g_object_class_install_property (object_class, PROP_PARENT_WINDOW,
694 g_param_spec_object ("parent-window",
696 "The window for which the banner will be singleton",
697 GTK_TYPE_WINDOW, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
700 * HildonBanner:is-timed:
702 * Whether the banner is timed and goes away automatically.
705 g_object_class_install_property (object_class, PROP_IS_TIMED,
706 g_param_spec_boolean ("is-timed",
708 "Whether or not the notification goes away automatically "
709 "after the specified time has passed",
710 FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
713 * HildonBanner:timeout:
715 * The time before making the banner banner go away. This needs
716 * to be adjusted before the banner is mapped to the screen.
719 g_object_class_install_property (object_class, PROP_TIMEOUT,
720 g_param_spec_uint ("timeout",
722 "The time before making the banner banner go away",
725 HILDON_BANNER_DEFAULT_TIMEOUT,
726 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
730 hildon_banner_init (HildonBanner *self)
732 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
737 /* Initialize the common layout inside banner */
738 priv->layout = gtk_hbox_new (FALSE, HILDON_MARGIN_DEFAULT);
740 priv->label = g_object_new (GTK_TYPE_LABEL, NULL);
741 gtk_label_set_line_wrap (GTK_LABEL (priv->label), TRUE);
743 gtk_container_set_border_width (GTK_CONTAINER (priv->layout), HILDON_MARGIN_DEFAULT);
744 gtk_container_add (GTK_CONTAINER (self), priv->layout);
745 gtk_box_pack_start (GTK_BOX (priv->layout), priv->label, TRUE, TRUE, 0);
747 gtk_window_set_accept_focus (GTK_WINDOW (self), FALSE);
750 /* Makes sure that icon/progress item contains the desired type
751 of item. If possible, tries to avoid creating a new widget but
752 reuses the existing one */
754 hildon_banner_ensure_child (HildonBanner *self,
755 GtkWidget *user_widget,
758 const gchar *first_property,
763 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
767 widget = priv->main_item;
768 va_start (args, first_property);
770 /* Reuse existing widget if possible */
771 if (! user_widget && G_TYPE_CHECK_INSTANCE_TYPE (widget, type))
773 g_object_set_valist (G_OBJECT (widget), first_property, args);
777 /* We have to abandon old content widget */
779 gtk_container_remove (GTK_CONTAINER (priv->layout), widget);
781 /* Use user provided widget or create a new one */
782 priv->main_item = widget = user_widget ?
783 user_widget : GTK_WIDGET (g_object_new_valist(type, first_property, args));
784 gtk_box_pack_start (GTK_BOX (priv->layout), widget, TRUE, TRUE, 0);
787 /* We make sure that the widget exists in desired position. Different
788 banners place this child widget to different places */
789 gtk_box_reorder_child (GTK_BOX (priv->layout), widget, pos);
793 /* Creates a new banner instance or uses an existing one */
795 hildon_banner_get_instance_for_widget (GtkWidget *widget,
800 window = widget ? gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW) : NULL;
801 return g_object_new (HILDON_TYPE_BANNER, "parent-window", window, "is-timed", timed, NULL);
805 * hildon_banner_show_information:
806 * @widget: the #GtkWidget that is the owner of the banner
807 * @icon_name: the name of icon to use. Can be %NULL for default icon
808 * @text: Text to display
810 * This function creates and displays an information banner that
811 * automatically goes away after certain time period. For each window
812 * in your application there can only be one timed banner, so if you
813 * spawn a new banner before the earlier one has timed out, the
814 * previous one will be replaced.
816 * Returns: The newly created banner
820 hildon_banner_show_information (GtkWidget *widget,
821 const gchar *icon_name,
824 HildonBanner *banner;
826 g_return_val_if_fail (icon_name == NULL || icon_name[0] != 0, NULL);
827 g_return_val_if_fail (text != NULL, NULL);
830 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
831 hildon_banner_ensure_child (banner, NULL, 0, GTK_TYPE_IMAGE,
832 "pixel-size", HILDON_ICON_PIXEL_SIZE_NOTE,
833 "icon-name", icon_name ? icon_name : HILDON_BANNER_DEFAULT_ICON,
837 hildon_banner_set_text (banner, text);
838 hildon_banner_bind_label_style (banner, NULL);
840 /* Show the banner, since caller cannot do that */
841 gtk_widget_show_all (GTK_WIDGET (banner));
843 return (GtkWidget *) banner;
847 * hildon_banner_show_informationf:
848 * @widget: the #GtkWidget that is the owner of the banner
849 * @icon_name: the name of icon to use. Can be %NULL for default icon
850 * @format: a printf-like format string
851 * @Varargs: arguments for the format string
853 * A helper function for #hildon_banner_show_information with
856 * Returns: the newly created banner
859 hildon_banner_show_informationf (GtkWidget *widget,
860 const gchar *icon_name,
864 g_return_val_if_fail (format != NULL, NULL);
870 va_start (args, format);
871 message = g_strdup_vprintf (format, args);
874 banner = hildon_banner_show_information (widget, icon_name, message);
882 * hildon_banner_show_information_with_markup:
883 * @widget: the #GtkWidget that wants to display banner
884 * @icon_name: the name of icon to use. Can be %NULL for default icon.
885 * @markup: a markup string to display (see <link linkend="PangoMarkupFormat">Pango markup format</link>)
887 * This function creates and displays an information banner that
888 * automatically goes away after certain time period. For each window
889 * in your application there can only be one timed banner, so if you
890 * spawn a new banner before the earlier one has timed out, the
891 * previous one will be replaced.
893 * Returns: the newly created banner
897 hildon_banner_show_information_with_markup (GtkWidget *widget,
898 const gchar *icon_name,
901 HildonBanner *banner;
903 g_return_val_if_fail (icon_name == NULL || icon_name[0] != 0, NULL);
904 g_return_val_if_fail (markup != NULL, NULL);
907 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
909 hildon_banner_ensure_child (banner, NULL, 0, GTK_TYPE_IMAGE,
910 "pixel-size", HILDON_ICON_PIXEL_SIZE_NOTE,
911 "icon-name", icon_name ? icon_name : HILDON_BANNER_DEFAULT_ICON,
915 hildon_banner_set_markup (banner, markup);
916 hildon_banner_bind_label_style (banner, NULL);
918 /* Show the banner, since caller cannot do that */
919 gtk_widget_show_all (GTK_WIDGET (banner));
921 return (GtkWidget *) banner;
925 * hildon_banner_show_animation:
926 * @widget: the #GtkWidget that wants to display banner
927 * @animation_name: The progress animation to use. You usually can just
928 * pass %NULL for the default animation.
929 * @text: the text to display.
931 * Shows an animated progress notification. It's recommended not to try
932 * to show more than one progress notification at a time, since
933 * they will appear on top of each other. You can use progress
934 * notifications with timed banners. In this case the banners are
935 * located so that you can somehow see both.
937 * Please note that banners are destroyed automatically once the
938 * window they are attached to is closed. The pointer that you
939 * receive with this function do not contain additional references,
940 * so it can become invalid without warning (this is true for
941 * all toplevel windows in gtk). To make sure that the banner do not disapear
942 * automatically, you can separately ref the return value (this
943 * doesn't prevent the banner from disappearing, but the object it just
944 * not finalized). In this case you have to call both #gtk_widget_destroy
945 * followed by #g_object_unref (in this order).
947 * Returns: a #HildonBanner widget. You must call #gtk_widget_destroy
948 * once you are done with the banner.
952 hildon_banner_show_animation (GtkWidget *widget,
953 const gchar *animation_name,
956 HildonBanner *banner;
959 GtkWidget *image_widget;
960 const gchar *filename;
962 g_return_val_if_fail (animation_name == NULL || animation_name[0] != 0, NULL);
963 g_return_val_if_fail (text != NULL, NULL);
965 /* Find out which animation to use */
966 theme = gtk_icon_theme_get_default ();
967 info = gtk_icon_theme_lookup_icon (theme, animation_name ? /* FIXME: consider using: gtk_icon_theme_load_icon() */
968 animation_name : HILDON_BANNER_DEFAULT_PROGRESS_ANIMATION,
969 HILDON_ICON_SIZE_NOTE, 0);
971 /* Try to load animation. One could try to optimize this
972 to avoid loading the default animation during each call */
974 filename = gtk_icon_info_get_filename (info);
975 image_widget = gtk_image_new_from_file (filename);
976 gtk_icon_info_free (info);
978 g_warning ("Icon theme lookup for icon failed!");
983 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
984 hildon_banner_ensure_child (banner, image_widget, 0,
985 GTK_TYPE_IMAGE, "yalign", 0.0, NULL);
987 hildon_banner_set_text (banner, text);
988 hildon_banner_bind_label_style (banner, NULL);
991 gtk_widget_show_all (GTK_WIDGET (banner));
993 return (GtkWidget *) banner;
997 * hildon_banner_show_progress:
998 * @widget: the #GtkWidget that wants to display banner
999 * @bar: Progressbar to use. You usually can just pass %NULL, unless
1000 * you want somehow customized progress bar.
1001 * @text: text to display.
1003 * Shows progress notification. See #hildon_banner_show_animation
1004 * for more information.
1006 * Returns: a #HildonBanner widget. You must call #gtk_widget_destroy
1007 * once you are done with the banner.
1011 hildon_banner_show_progress (GtkWidget *widget,
1012 GtkProgressBar *bar,
1015 HildonBanner *banner;
1016 HildonBannerPrivate *priv;
1018 g_return_val_if_fail (bar == NULL || GTK_IS_PROGRESS_BAR (bar), NULL);
1019 g_return_val_if_fail (text != NULL, NULL);
1022 /* Prepare banner */
1023 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
1024 priv = HILDON_BANNER_GET_PRIVATE (banner);
1026 hildon_banner_ensure_child (banner, (GtkWidget *) bar, -1, GTK_TYPE_PROGRESS_BAR, NULL);
1028 gtk_widget_set_size_request (priv->main_item,
1029 HILDON_BANNER_PROGRESS_WIDTH, -1);
1031 hildon_banner_set_text (banner, text);
1032 hildon_banner_bind_label_style (banner, NULL);
1034 /* Show the banner */
1035 gtk_widget_show_all (GTK_WIDGET (banner));
1037 return GTK_WIDGET (banner);
1041 * hildon_banner_set_text:
1042 * @self: a #HildonBanner widget
1043 * @text: a new text to display in banner
1045 * Sets the text that is displayed in the banner.
1049 hildon_banner_set_text (HildonBanner *self,
1053 HildonBannerPrivate *priv;
1054 const gchar *existing_text;
1056 g_return_if_fail (HILDON_IS_BANNER (self));
1058 priv = HILDON_BANNER_GET_PRIVATE (self);
1061 label = GTK_LABEL (priv->label);
1062 existing_text = gtk_label_get_text (label);
1064 if (existing_text != NULL &&
1066 strcmp (existing_text, text) != 0)
1067 gtk_label_set_text (label, text);
1069 hildon_banner_check_position (GTK_WIDGET (self));
1073 * hildon_banner_set_markup:
1074 * @self: a #HildonBanner widget
1075 * @markup: a new text with Pango markup to display in the banner
1077 * Sets the text with markup that is displayed in the banner.
1081 hildon_banner_set_markup (HildonBanner *self,
1082 const gchar *markup)
1085 HildonBannerPrivate *priv;
1087 g_return_if_fail (HILDON_IS_BANNER (self));
1089 priv = HILDON_BANNER_GET_PRIVATE (self);
1092 label = GTK_LABEL (priv->label);
1093 gtk_label_set_markup (label, markup);
1095 hildon_banner_check_position (GTK_WIDGET(self));
1099 * hildon_banner_set_fraction:
1100 * @self: a #HildonBanner widget
1101 * @fraction: #gdouble
1103 * The fraction is the completion of progressbar,
1104 * the scale is from 0.0 to 1.0.
1105 * Sets the amount of fraction the progressbar has.
1109 hildon_banner_set_fraction (HildonBanner *self,
1112 HildonBannerPrivate *priv;
1114 g_return_if_fail (HILDON_IS_BANNER (self));
1115 priv = HILDON_BANNER_GET_PRIVATE (self);
1118 g_return_if_fail (GTK_IS_PROGRESS_BAR (priv->main_item));
1119 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (priv->main_item), fraction);
1123 * hildon_banner_set_timeout:
1124 * @self: a #HildonBanner widget
1125 * @timeout: timeout to set in miliseconds.
1127 * Sets the timeout on the banner. After the given amount of miliseconds
1128 * has elapsed the banner will go away. Note that settings this only makes
1129 * sense on the banners that are timed and that have not been yet displayed
1134 hildon_banner_set_timeout (HildonBanner *self,
1137 HildonBannerPrivate *priv;
1139 g_return_if_fail (HILDON_IS_BANNER (self));
1140 priv = HILDON_BANNER_GET_PRIVATE (self);
1143 priv->timeout = timeout;
1147 * hildon_banner_set_icon:
1148 * @self: a #HildonBanner widget
1149 * @icon_name: the name of icon to use. Can be %NULL for default icon
1151 * Sets the icon to be used in the banner.
1155 hildon_banner_set_icon (HildonBanner *self,
1156 const gchar *icon_name)
1158 HildonBannerPrivate *priv;
1160 g_return_if_fail (HILDON_IS_BANNER (self));
1161 priv = HILDON_BANNER_GET_PRIVATE (self);
1164 hildon_banner_ensure_child (self, NULL, 0, GTK_TYPE_IMAGE,
1165 "pixel-size", HILDON_ICON_PIXEL_SIZE_NOTE,
1166 "icon-name", icon_name ? icon_name : HILDON_BANNER_DEFAULT_ICON,
1172 * hildon_banner_set_icon_from_file:
1173 * @self: a #HildonBanner widget
1174 * @icon_file: the filename of icon to use. Can be %NULL for default icon
1176 * Sets the icon from its filename to be used in the banner.
1180 hildon_banner_set_icon_from_file (HildonBanner *self,
1181 const gchar *icon_file)
1183 HildonBannerPrivate *priv;
1185 g_return_if_fail (HILDON_IS_BANNER (self));
1186 priv = HILDON_BANNER_GET_PRIVATE (self);
1189 if (icon_file != NULL) {
1190 hildon_banner_ensure_child (self, NULL, 0, GTK_TYPE_IMAGE,
1191 "pixel-size", HILDON_ICON_PIXEL_SIZE_NOTE,
1196 hildon_banner_ensure_child (self, NULL, 0, GTK_TYPE_IMAGE,
1197 "pixel-size", HILDON_ICON_PIXEL_SIZE_NOTE,
1198 "icon-name", HILDON_BANNER_DEFAULT_ICON,