2 * This file is a part of hildon
4 * Copyright (C) 2005, 2006, 2007 Nokia Corporation, all rights reserved.
6 * Contact: Rodrigo Novo <rodrigo.novo@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 is a small, pop-up window that can be used to display
30 * a short, timed notification or information to the user. It can
31 * communicate that a task has been finished or that the application
34 * Hildon provides convenient funtions to create and show banners. To
35 * create and show information banners you can use
36 * hildon_banner_show_information(), hildon_banner_show_informationf()
37 * or hildon_banner_show_information_with_markup().
39 * Two more kinds of banners are maintained for backward compatibility
40 * but are no longer recommended in Hildon 2.2. These are the animated
41 * banner (created with hildon_banner_show_animation()) and the
42 * progress banner (created with hildon_banner_show_progress()). See
43 * hildon_gtk_window_set_progress_indicator() for the preferred way of
44 * showing progress notifications in Hildon 2.2.
46 * Information banners dissapear automatically after a certain
47 * period. This is stored in the #HildonBanner:timeout property (in
48 * miliseconds), and can be changed using hildon_banner_set_timeout().
50 * Note that #HildonBanner<!-- -->s should only be used to display
51 * non-critical pieces of information.
59 #include <X11/Xatom.h>
63 #undef HILDON_DISABLE_DEPRECATED
65 #include "hildon-banner.h"
66 #include "hildon-banner-private.h"
67 #include "hildon-defines.h"
69 /* position relative to the screen */
71 #define HILDON_BANNER_WINDOW_X 0
73 #define HILDON_BANNER_WINDOW_Y 73
75 #define HILDON_BANNER_WINDOW_FULLSCREEN_Y 20
79 #define HILDON_BANNER_PROGRESS_WIDTH 104
81 #define HILDON_BANNER_LABEL_MAX_TIMED \
82 (800 - ((HILDON_MARGIN_TRIPLE) * 2))
84 #define HILDON_BANNER_LABEL_MAX_PROGRESS 375 /*265*/
88 #define HILDON_BANNER_DEFAULT_TIMEOUT 3000
92 #define HILDON_BANNER_DEFAULT_PROGRESS_ANIMATION "indicator_update"
94 /* animation related stuff */
96 #define HILDON_BANNER_ANIMATION_FRAMERATE ((float)1000/150)
98 #define HILDON_BANNER_ANIMATION_TMPL "indicator_update%d"
100 #define HILDON_BANNER_ANIMATION_NFRAMES 8
110 static GtkWidget* global_timed_banner = NULL;
113 get_current_app_window (void);
116 check_fullscreen_state (Window window);
119 hildon_banner_timed_quark (void);
122 hildon_banner_bind_style (HildonBanner *self,
126 hildon_banner_timeout (gpointer data);
129 hildon_banner_clear_timeout (HildonBanner *self);
132 hildon_banner_ensure_timeout (HildonBanner *self);
135 hildon_banner_set_property (GObject *object,
141 hildon_banner_get_property (GObject *object,
147 hildon_banner_destroy (GtkObject *object);
150 hildon_banner_real_get_instance (GObject *window,
154 hildon_banner_constructor (GType type,
155 guint n_construct_params,
156 GObjectConstructParam *construct_params);
159 hildon_banner_finalize (GObject *object);
162 hildon_banner_button_press_event (GtkWidget* widget,
163 GdkEventButton* event);
166 hildon_banner_map_event (GtkWidget *widget,
169 hildon_banner_reset_wrap_state (HildonBanner *banner);
172 force_to_wrap_truncated (HildonBanner *banner);
175 hildon_banner_check_position (GtkWidget *widget);
178 hildon_banner_realize (GtkWidget *widget);
181 hildon_banner_class_init (HildonBannerClass *klass);
184 hildon_banner_init (HildonBanner *self);
187 hildon_banner_ensure_child (HildonBanner *self,
188 GtkWidget *user_widget,
191 const gchar *first_property,
195 hildon_banner_get_instance_for_widget (GtkWidget *widget,
198 G_DEFINE_TYPE (HildonBanner, hildon_banner, GTK_TYPE_WINDOW)
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 widget and label name to make the correct rc-style attached into them */
292 hildon_banner_bind_style (HildonBanner *self,
293 const gchar *name_sufix)
295 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
300 name = g_strconcat ("HildonBannerLabel-", name_sufix, NULL);
301 gtk_widget_set_name (priv->label, name);
304 name = g_strconcat ("HildonBanner-", name_sufix, NULL);
305 gtk_widget_set_name (GTK_WIDGET (self), name);
309 /* In timeout function we automatically destroy timed banners */
311 simulate_close (GtkWidget* widget)
313 gboolean result = FALSE;
315 /* If the banner is currently visible (it normally should),
316 we simulate clicking the close button of the window.
317 This allows applications to reuse the banner by prevent
319 if (GTK_WIDGET_DRAWABLE (widget))
321 GdkEvent *event = gdk_event_new (GDK_DELETE);
322 event->any.window = g_object_ref (widget->window);
323 event->any.send_event = FALSE;
324 result = gtk_widget_event (widget, event);
325 gdk_event_free (event);
332 hildon_banner_timeout (gpointer data)
335 gboolean continue_timeout = FALSE;
337 GDK_THREADS_ENTER ();
339 g_assert (HILDON_IS_BANNER (data));
341 widget = GTK_WIDGET (data);
342 g_object_ref (widget);
344 continue_timeout = simulate_close (widget);
346 if (! continue_timeout) {
347 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (data);
348 priv->timeout_id = 0;
349 gtk_widget_destroy (widget);
352 g_object_unref (widget);
354 GDK_THREADS_LEAVE ();
356 return continue_timeout;
360 hildon_banner_clear_timeout (HildonBanner *self)
362 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
365 if (priv->timeout_id != 0) {
366 g_source_remove (priv->timeout_id);
367 priv->timeout_id = 0;
375 hildon_banner_ensure_timeout (HildonBanner *self)
377 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
380 if (priv->timeout_id == 0 && priv->is_timed && priv->timeout > 0)
381 priv->timeout_id = g_timeout_add (priv->timeout,
382 hildon_banner_timeout, self);
386 hildon_banner_set_property (GObject *object,
392 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
398 priv->timeout = g_value_get_uint (value);
402 priv->is_timed = g_value_get_boolean (value);
405 case PROP_PARENT_WINDOW:
406 window = g_value_get_object (value);
408 g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent);
411 gtk_window_set_transient_for (GTK_WINDOW (object), (GtkWindow *) window);
412 priv->parent = (GtkWindow *) window;
415 gtk_window_set_destroy_with_parent (GTK_WINDOW (object), TRUE);
416 g_object_add_weak_pointer(G_OBJECT (window), (gpointer) &priv->parent);
422 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
428 hildon_banner_get_property (GObject *object,
433 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
439 g_value_set_uint (value, priv->timeout);
443 g_value_set_boolean (value, priv->is_timed);
446 case PROP_PARENT_WINDOW:
447 g_value_set_object (value, gtk_window_get_transient_for (GTK_WINDOW (object)));
451 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
457 hildon_banner_destroy (GtkObject *object)
459 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
463 GObject *parent_window = (GObject *) priv->parent;
465 g_assert (HILDON_IS_BANNER (object));
466 self = HILDON_BANNER (object);
468 /* Drop possible global pointer. That can hold reference to us */
469 if ((gpointer) object == (gpointer) global_timed_banner) {
470 global_timed_banner = NULL;
471 g_object_unref (object);
474 /* Remove the data from parent window for timed banners. Those hold reference */
475 if (priv->is_timed && parent_window != NULL) {
476 g_object_set_qdata (parent_window, hildon_banner_timed_quark (), NULL);
479 (void) hildon_banner_clear_timeout (self);
481 if (GTK_OBJECT_CLASS (hildon_banner_parent_class)->destroy)
482 GTK_OBJECT_CLASS (hildon_banner_parent_class)->destroy (object);
485 /* Search a previous banner instance */
487 hildon_banner_real_get_instance (GObject *window,
491 /* If we have a parent window, the previous instance is stored there */
493 return g_object_get_qdata(window, hildon_banner_timed_quark ());
496 /* System notification instance is stored into global pointer */
497 return (GObject *) global_timed_banner;
500 /* Non-timed banners are normal (non-singleton) objects */
504 /* By overriding constructor we force timed banners to be
505 singletons for each window */
507 hildon_banner_constructor (GType type,
508 guint n_construct_params,
509 GObjectConstructParam *construct_params)
511 GObject *banner, *window = NULL;
512 gboolean timed = FALSE;
515 /* Search banner type information from parameters in order
516 to locate the possible previous banner instance. */
517 for (i = 0; i < n_construct_params; i++)
519 if (strcmp(construct_params[i].pspec->name, "parent-window") == 0)
520 window = g_value_get_object (construct_params[i].value);
521 else if (strcmp(construct_params[i].pspec->name, "is-timed") == 0)
522 timed = g_value_get_boolean (construct_params[i].value);
525 /* Try to get a previous instance if such exists */
526 banner = hildon_banner_real_get_instance (window, timed);
529 /* We have to create a new banner */
530 banner = G_OBJECT_CLASS (hildon_banner_parent_class)->constructor (type, n_construct_params, construct_params);
532 /* Store the newly created singleton instance either into parent
533 window data or into global variables. */
536 g_object_set_qdata_full (G_OBJECT (window), hildon_banner_timed_quark (),
537 g_object_ref (banner), g_object_unref);
539 g_assert (global_timed_banner == NULL);
540 global_timed_banner = g_object_ref (banner);
545 /* FIXME: This is a hack! We have to manually freeze
546 notifications. This is normally done by g_object_init, but we
547 are not going to call that. g_object_newv will otherwise give
548 a critical like this:
550 GLIB CRITICAL ** GLib-GObject - g_object_notify_queue_thaw:
551 assertion `nqueue->freeze_count > 0' failed */
553 g_object_freeze_notify (banner);
554 hildon_banner_reset_wrap_state (HILDON_BANNER (banner));
557 /* We restart possible timeouts for each new timed banner request */
558 if (timed && hildon_banner_clear_timeout (HILDON_BANNER (banner)))
559 hildon_banner_ensure_timeout (HILDON_BANNER(banner));
565 hildon_banner_finalize (GObject *object)
567 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
570 g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent);
573 G_OBJECT_CLASS (hildon_banner_parent_class)->finalize (object);
577 hildon_banner_button_press_event (GtkWidget* widget,
578 GdkEventButton* event)
580 gboolean result = simulate_close (widget);
583 /* signal emission not stopped - basically behave like
584 * gtk_main_do_event() for a delete event, but just hide the
585 * banner instead of destroying it, as it is already meant to
586 * be destroyed by hildon_banner_timeout() (if it's timed) or
587 * the application (if it's not). */
588 gtk_widget_hide (widget);
594 #if defined(MAEMO_GTK)
596 hildon_banner_map (GtkWidget *widget)
598 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->map) {
599 /* Make the banner temporary _before_ mapping it, to avoid closing
600 * other temporary windows */
601 gtk_window_set_is_temporary (GTK_WINDOW (widget), TRUE);
603 GTK_WIDGET_CLASS (hildon_banner_parent_class)->map (widget);
605 /* Make the banner non-temporary _after_ mapping it, to avoid
606 * being closed by other non-temporary windows */
607 gtk_window_set_is_temporary (GTK_WINDOW (widget), FALSE);
612 /* We start the timer for timed notifications after the window appears on screen */
614 hildon_banner_map_event (GtkWidget *widget,
617 gboolean result = FALSE;
619 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->map_event)
620 result = GTK_WIDGET_CLASS (hildon_banner_parent_class)->map_event (widget, event);
622 hildon_banner_ensure_timeout (HILDON_BANNER(widget));
628 hildon_banner_reset_wrap_state (HildonBanner *banner)
631 HildonBannerPrivate *priv;
633 priv = HILDON_BANNER_GET_PRIVATE (banner);
636 layout = gtk_label_get_layout (GTK_LABEL (priv->label));
638 pango_layout_set_width (layout, -1);
639 priv->has_been_wrapped = FALSE;
640 priv->has_been_truncated = FALSE;
642 gtk_widget_set_size_request (priv->label, -1, -1);
643 gtk_widget_set_size_request (GTK_WIDGET (banner), -1, -1);
646 /* force to wrap truncated label by setting explicit size request
647 * see N#27000 and G#329646 */
649 force_to_wrap_truncated (HildonBanner *banner)
653 int width_text, width_max;
656 PangoRectangle logical;
657 GtkRequisition requisition;
658 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (banner);
660 g_return_if_fail (priv);
662 label = GTK_LABEL (priv->label);
664 layout = gtk_label_get_layout (label);
666 pango_layout_get_extents (layout, NULL, &logical);
667 width_text = PANGO_PIXELS (logical.width);
669 width_max = priv->is_timed ? HILDON_BANNER_LABEL_MAX_TIMED
670 : HILDON_BANNER_LABEL_MAX_PROGRESS;
672 /* If the width of the label is going to exceed the maximum allowed
673 * width, enforce the maximum allowed width now.
675 if (priv->has_been_wrapped
676 || width_text >= width_max
677 || pango_layout_is_wrapped (layout)) {
678 /* Force wrapping by setting the maximum size */
681 priv->has_been_wrapped = TRUE;
684 /* Make the label update its layout; and update our layout pointer
685 * because the layout will be cleared and refreshed.
687 gtk_widget_set_size_request (GTK_WIDGET (label), width, height);
688 gtk_widget_size_request (GTK_WIDGET (label), &requisition);
690 layout = gtk_label_get_layout (label);
692 /* If the layout has now been wrapped and exceeds 3 lines, we truncate
693 * the rest of the label according to spec.
695 if (priv->has_been_truncated
696 || (pango_layout_is_wrapped (layout)
697 && pango_layout_get_line_count (layout) > 3)) {
700 pango_layout_get_extents (layout, NULL, &logical);
701 lines = pango_layout_get_line_count (layout);
703 /* This calculation assumes that the same font is used
704 * throughout the banner -- this is usually the case on maemo
706 * FIXME: Pango >= 1.20 has pango_layout_set_height().
708 height = (PANGO_PIXELS (logical.height) * 3) / lines + 1;
709 priv->has_been_truncated = TRUE;
712 /* Set the new width/height if applicable */
713 gtk_widget_set_size_request (GTK_WIDGET (label), width, height);
718 hildon_banner_check_position (GtkWidget *widget)
723 gtk_widget_set_size_request (widget, gdk_screen_width (), -1);
725 force_to_wrap_truncated (HILDON_BANNER(widget)); /* see N#27000 and G#329646 */
727 gtk_widget_size_request (widget, &req);
734 x = HILDON_BANNER_WINDOW_X;
736 y = check_fullscreen_state (get_current_app_window ()) ?
737 HILDON_BANNER_WINDOW_FULLSCREEN_Y : HILDON_BANNER_WINDOW_Y;
739 gtk_window_move (GTK_WINDOW (widget), x, y);
743 hildon_banner_realize (GtkWidget *widget)
747 const gchar *notification_type = "_HILDON_NOTIFICATION_TYPE_BANNER";
748 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (widget);
751 /* We let the parent to init widget->window before we need it */
752 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->realize)
753 GTK_WIDGET_CLASS (hildon_banner_parent_class)->realize (widget);
755 /* We use special hint to turn the banner into information notification. */
756 gdk_window_set_type_hint (widget->window, GDK_WINDOW_TYPE_HINT_NOTIFICATION);
757 gtk_window_set_transient_for (GTK_WINDOW (widget), (GtkWindow *) priv->parent);
759 hildon_banner_check_position (widget);
761 /* Set the _HILDON_NOTIFICATION_TYPE property so Matchbox places the window correctly */
762 display = gdk_drawable_get_display (widget->window);
763 atom = gdk_x11_get_xatom_by_name_for_display (display, "_HILDON_NOTIFICATION_TYPE");
764 XChangeProperty (GDK_WINDOW_XDISPLAY (widget->window), GDK_WINDOW_XID (widget->window),
765 atom, XA_STRING, 8, PropModeReplace, (guchar *) notification_type,
766 strlen (notification_type));
770 hildon_banner_class_init (HildonBannerClass *klass)
772 GObjectClass *object_class;
773 GtkWidgetClass *widget_class;
775 object_class = G_OBJECT_CLASS (klass);
776 widget_class = GTK_WIDGET_CLASS (klass);
778 /* Append private structure to class. This is more elegant than
779 on g_new based approach */
780 g_type_class_add_private (klass, sizeof (HildonBannerPrivate));
782 /* Override virtual methods */
783 object_class->constructor = hildon_banner_constructor;
784 object_class->finalize = hildon_banner_finalize;
785 object_class->set_property = hildon_banner_set_property;
786 object_class->get_property = hildon_banner_get_property;
787 GTK_OBJECT_CLASS (klass)->destroy = hildon_banner_destroy;
788 widget_class->map_event = hildon_banner_map_event;
789 widget_class->realize = hildon_banner_realize;
790 widget_class->button_press_event = hildon_banner_button_press_event;
791 #if defined(MAEMO_GTK)
792 widget_class->map = hildon_banner_map;
795 /* Install properties.
796 We need construct properties for singleton purposes */
799 * HildonBanner:parent-window:
801 * The window for which the banner will be singleton.
804 g_object_class_install_property (object_class, PROP_PARENT_WINDOW,
805 g_param_spec_object ("parent-window",
807 "The window for which the banner will be singleton",
808 GTK_TYPE_WINDOW, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
811 * HildonBanner:is-timed:
813 * Whether the banner is timed and goes away automatically.
816 g_object_class_install_property (object_class, PROP_IS_TIMED,
817 g_param_spec_boolean ("is-timed",
819 "Whether or not the notification goes away automatically "
820 "after the specified time has passed",
821 FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
824 * HildonBanner:timeout:
826 * The time before making the banner banner go away. This needs
827 * to be adjusted before the banner is mapped to the screen.
830 g_object_class_install_property (object_class, PROP_TIMEOUT,
831 g_param_spec_uint ("timeout",
833 "The time before making the banner banner go away",
836 HILDON_BANNER_DEFAULT_TIMEOUT,
837 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
841 hildon_banner_init (HildonBanner *self)
843 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
848 /* Initialize the common layout inside banner */
849 priv->layout = gtk_hbox_new (FALSE, HILDON_MARGIN_DEFAULT);
851 priv->label = g_object_new (GTK_TYPE_LABEL, NULL);
852 gtk_label_set_line_wrap (GTK_LABEL (priv->label), TRUE);
853 gtk_label_set_line_wrap_mode (GTK_LABEL (priv->label), PANGO_WRAP_WORD_CHAR);
855 gtk_container_set_border_width (GTK_CONTAINER (priv->layout), HILDON_MARGIN_DEFAULT);
856 gtk_container_add (GTK_CONTAINER (self), priv->layout);
857 gtk_box_pack_start (GTK_BOX (priv->layout), priv->label, TRUE, TRUE, 0);
859 gtk_window_set_accept_focus (GTK_WINDOW (self), FALSE);
861 hildon_banner_reset_wrap_state (self);
863 gtk_widget_add_events (GTK_WIDGET (self), GDK_BUTTON_PRESS_MASK);
866 /* Makes sure that icon/progress item contains the desired type
867 of item. If possible, tries to avoid creating a new widget but
868 reuses the existing one */
870 hildon_banner_ensure_child (HildonBanner *self,
871 GtkWidget *user_widget,
874 const gchar *first_property,
879 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
883 widget = priv->main_item;
884 va_start (args, first_property);
886 /* Reuse existing widget if possible */
887 if (! user_widget && G_TYPE_CHECK_INSTANCE_TYPE (widget, type))
889 g_object_set_valist (G_OBJECT (widget), first_property, args);
893 /* We have to abandon old content widget */
895 gtk_container_remove (GTK_CONTAINER (priv->layout), widget);
897 /* Use user provided widget or create a new one */
898 priv->main_item = widget = user_widget ?
899 user_widget : GTK_WIDGET (g_object_new_valist(type, first_property, args));
900 gtk_box_pack_start (GTK_BOX (priv->layout), widget, TRUE, TRUE, 0);
903 /* We make sure that the widget exists in desired position. Different
904 banners place this child widget to different places */
905 gtk_box_reorder_child (GTK_BOX (priv->layout), widget, pos);
909 /* Creates a new banner instance or uses an existing one */
911 hildon_banner_get_instance_for_widget (GtkWidget *widget,
916 window = widget ? gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW) : NULL;
917 return g_object_new (HILDON_TYPE_BANNER, "parent-window", window, "is-timed", timed, NULL);
921 hildon_banner_create_animation (void)
924 GdkPixbufSimpleAnim *anim;
927 GError *error = NULL;
931 anim = gdk_pixbuf_simple_anim_new (HILDON_ICON_PIXEL_SIZE_FINGER,
932 HILDON_ICON_PIXEL_SIZE_FINGER,
933 HILDON_BANNER_ANIMATION_FRAMERATE);
934 gdk_pixbuf_simple_anim_set_loop (anim, TRUE);
935 theme = gtk_icon_theme_get_default ();
937 for (i = 1; i <= HILDON_BANNER_ANIMATION_NFRAMES; i++) {
938 icon_name = g_strdup_printf (HILDON_BANNER_ANIMATION_TMPL, i);
939 frame = gtk_icon_theme_load_icon (theme, icon_name, HILDON_ICON_PIXEL_SIZE_FINGER,
943 g_warning ("Icon theme lookup for icon `%s' failed: %s",
944 icon_name, error->message);
945 g_error_free (error);
948 gdk_pixbuf_simple_anim_add_frame (anim, frame);
951 g_object_unref (frame);
955 image = gtk_image_new_from_animation (GDK_PIXBUF_ANIMATION (anim));
956 g_object_unref (anim);
962 * hildon_banner_show_information:
963 * @widget: the #GtkWidget that is the owner of the banner
964 * @icon_name: since Hildon 2.2 this parameter is not used anymore and
965 * any value that you pass will be ignored
966 * @text: Text to display
968 * This function creates and displays an information banner that
969 * automatically goes away after certain time period. For each window
970 * in your application there can only be one timed banner, so if you
971 * spawn a new banner before the earlier one has timed out, the
972 * previous one will be replaced.
974 * Returns: The newly created banner
978 hildon_banner_show_information (GtkWidget *widget,
979 const gchar *icon_name,
982 HildonBanner *banner;
984 g_return_val_if_fail (text != NULL, NULL);
987 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
989 hildon_banner_set_text (banner, text);
990 hildon_banner_bind_style (banner, "information");
992 /* Show the banner, since caller cannot do that */
993 gtk_widget_show_all (GTK_WIDGET (banner));
995 return (GtkWidget *) banner;
999 * hildon_banner_show_informationf:
1000 * @widget: the #GtkWidget that is the owner of the banner
1001 * @icon_name: since Hildon 2.2 this parameter is not used anymore and
1002 * any value that you pass will be ignored
1003 * @format: a printf-like format string
1004 * @Varargs: arguments for the format string
1006 * A helper function for #hildon_banner_show_information with
1007 * string formatting.
1009 * Returns: the newly created banner
1012 hildon_banner_show_informationf (GtkWidget *widget,
1013 const gchar *icon_name,
1014 const gchar *format,
1017 g_return_val_if_fail (format != NULL, NULL);
1023 va_start (args, format);
1024 message = g_strdup_vprintf (format, args);
1027 banner = hildon_banner_show_information (widget, icon_name, message);
1035 * hildon_banner_show_information_with_markup:
1036 * @widget: the #GtkWidget that wants to display banner
1037 * @icon_name: since Hildon 2.2 this parameter is not used anymore and
1038 * any value that you pass will be ignored
1039 * @markup: a markup string to display (see <link linkend="PangoMarkupFormat">Pango markup format</link>)
1041 * This function creates and displays an information banner that
1042 * automatically goes away after certain time period. For each window
1043 * in your application there can only be one timed banner, so if you
1044 * spawn a new banner before the earlier one has timed out, the
1045 * previous one will be replaced.
1047 * Returns: the newly created banner
1051 hildon_banner_show_information_with_markup (GtkWidget *widget,
1052 const gchar *icon_name,
1053 const gchar *markup)
1055 HildonBanner *banner;
1057 g_return_val_if_fail (icon_name == NULL || icon_name[0] != 0, NULL);
1058 g_return_val_if_fail (markup != NULL, NULL);
1060 /* Prepare banner */
1061 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
1063 hildon_banner_set_markup (banner, markup);
1064 hildon_banner_bind_style (banner, "information");
1066 /* Show the banner, since caller cannot do that */
1067 gtk_widget_show_all (GTK_WIDGET (banner));
1069 return (GtkWidget *) banner;
1073 * hildon_banner_show_animation:
1074 * @widget: the #GtkWidget that wants to display banner
1075 * @animation_name: since Hildon 2.2 this parameter is not used
1076 * anymore and any value that you pass will be
1078 * @text: the text to display.
1080 * Shows an animated progress notification. It's recommended not to try
1081 * to show more than one progress notification at a time, since
1082 * they will appear on top of each other. You can use progress
1083 * notifications with timed banners. In this case the banners are
1084 * located so that you can somehow see both.
1086 * Please note that banners are destroyed automatically once the
1087 * window they are attached to is closed. The pointer that you receive
1088 * with this function does not contain additional references, so it
1089 * can become invalid without warning (this is true for all toplevel
1090 * windows in gtk). To make sure that the banner does not disappear
1091 * automatically, you can separately ref the return value (this
1092 * doesn't prevent the banner from disappearing, just the object from
1093 * being finalized). In this case you have to call both
1094 * gtk_widget_destroy() followed by g_object_unref() (in this order).
1096 * Returns: a #HildonBanner widget. You must call gtk_widget_destroy()
1097 * once you are done with the banner.
1099 * Deprecated: Hildon 2.2: use
1100 * hildon_gtk_window_set_progress_indicator() instead.
1103 hildon_banner_show_animation (GtkWidget *widget,
1104 const gchar *animation_name,
1107 HildonBanner *banner;
1108 GtkWidget *image_widget;
1110 g_return_val_if_fail (text != NULL, NULL);
1112 image_widget = hildon_banner_create_animation ();
1114 /* Prepare banner */
1115 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
1116 hildon_banner_ensure_child (banner, image_widget, 0,
1117 GTK_TYPE_IMAGE, "yalign", 0.0, NULL);
1119 hildon_banner_set_text (banner, text);
1120 hildon_banner_bind_style (banner, "animation");
1123 gtk_widget_show_all (GTK_WIDGET (banner));
1125 return (GtkWidget *) banner;
1129 * hildon_banner_show_progress:
1130 * @widget: the #GtkWidget that wants to display banner
1131 * @bar: Progressbar to use. You usually can just pass %NULL, unless
1132 * you want somehow customized progress bar.
1133 * @text: text to display.
1135 * Shows progress notification. See #hildon_banner_show_animation
1136 * for more information.
1138 * Returns: a #HildonBanner widget. You must call #gtk_widget_destroy
1139 * once you are done with the banner.
1141 * Deprecated: Hildon 2.2: use hildon_gtk_window_set_progress_indicator() instead.
1144 hildon_banner_show_progress (GtkWidget *widget,
1145 GtkProgressBar *bar,
1148 HildonBanner *banner;
1149 HildonBannerPrivate *priv;
1151 g_return_val_if_fail (bar == NULL || GTK_IS_PROGRESS_BAR (bar), NULL);
1152 g_return_val_if_fail (text != NULL, NULL);
1155 /* Prepare banner */
1156 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
1157 priv = HILDON_BANNER_GET_PRIVATE (banner);
1159 hildon_banner_ensure_child (banner, (GtkWidget *) bar, -1, GTK_TYPE_PROGRESS_BAR, NULL);
1161 gtk_widget_set_size_request (priv->main_item,
1162 HILDON_BANNER_PROGRESS_WIDTH, -1);
1164 hildon_banner_set_text (banner, text);
1165 hildon_banner_bind_style (banner, "progress");
1167 /* Show the banner */
1168 gtk_widget_show_all (GTK_WIDGET (banner));
1170 return GTK_WIDGET (banner);
1174 * hildon_banner_set_text:
1175 * @self: a #HildonBanner widget
1176 * @text: a new text to display in banner
1178 * Sets the text that is displayed in the banner.
1182 hildon_banner_set_text (HildonBanner *self,
1186 HildonBannerPrivate *priv;
1187 const gchar *existing_text;
1189 g_return_if_fail (HILDON_IS_BANNER (self));
1191 priv = HILDON_BANNER_GET_PRIVATE (self);
1194 label = GTK_LABEL (priv->label);
1195 existing_text = gtk_label_get_text (label);
1197 if (existing_text != NULL &&
1199 strcmp (existing_text, text) != 0) {
1200 gtk_label_set_text (label, text);
1201 hildon_banner_reset_wrap_state (self);
1204 hildon_banner_check_position (GTK_WIDGET (self));
1208 * hildon_banner_set_markup:
1209 * @self: a #HildonBanner widget
1210 * @markup: a new text with Pango markup to display in the banner
1212 * Sets the text with markup that is displayed in the banner.
1216 hildon_banner_set_markup (HildonBanner *self,
1217 const gchar *markup)
1220 HildonBannerPrivate *priv;
1222 g_return_if_fail (HILDON_IS_BANNER (self));
1224 priv = HILDON_BANNER_GET_PRIVATE (self);
1227 label = GTK_LABEL (priv->label);
1228 gtk_label_set_markup (label, markup);
1230 hildon_banner_reset_wrap_state (self);
1232 hildon_banner_check_position (GTK_WIDGET(self));
1236 * hildon_banner_set_fraction:
1237 * @self: a #HildonBanner widget
1238 * @fraction: #gdouble
1240 * The fraction is the completion of progressbar,
1241 * the scale is from 0.0 to 1.0.
1242 * Sets the amount of fraction the progressbar has.
1244 * Note that this method only has effect if @self was created with
1245 * hildon_banner_show_progress()
1249 hildon_banner_set_fraction (HildonBanner *self,
1252 HildonBannerPrivate *priv;
1254 g_return_if_fail (HILDON_IS_BANNER (self));
1255 priv = HILDON_BANNER_GET_PRIVATE (self);
1258 g_return_if_fail (GTK_IS_PROGRESS_BAR (priv->main_item));
1259 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (priv->main_item), fraction);
1263 * hildon_banner_set_timeout:
1264 * @self: a #HildonBanner widget
1265 * @timeout: timeout to set in miliseconds.
1267 * Sets the timeout on the banner. After the given amount of miliseconds
1268 * has elapsed the banner will go away. Note that settings this only makes
1269 * sense on the banners that are timed and that have not been yet displayed
1272 * Note that this method only has effect if @self is an information
1273 * banner (created using hildon_banner_show_information() and
1277 hildon_banner_set_timeout (HildonBanner *self,
1280 HildonBannerPrivate *priv;
1282 g_return_if_fail (HILDON_IS_BANNER (self));
1283 priv = HILDON_BANNER_GET_PRIVATE (self);
1286 priv->timeout = timeout;
1290 * hildon_banner_set_icon:
1291 * @self: a #HildonBanner widget
1292 * @icon_name: the name of icon to use. Can be %NULL for default icon
1294 * Sets the icon to be used in the banner.
1296 * Deprecated: This function does nothing. As of hildon 2.2, hildon
1297 * banners don't allow changing their icons.
1300 hildon_banner_set_icon (HildonBanner *self,
1301 const gchar *icon_name)
1306 * hildon_banner_set_icon_from_file:
1307 * @self: a #HildonBanner widget
1308 * @icon_file: the filename of icon to use. Can be %NULL for default icon
1310 * Sets the icon from its filename to be used in the banner.
1312 * Deprecated: This function does nothing. As of hildon 2.2, hildon
1313 * banners don't allow changing their icons.
1316 hildon_banner_set_icon_from_file (HildonBanner *self,
1317 const gchar *icon_file)