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 * If the application window has set the _HILDON_DO_NOT_DISTURB flag (using
40 * hildon_gtk_window_set_do_not_disturb() for example), the banner will not
41 * be showed. If you need to override this flag for important information,
42 * you can use the method hildon_banner_show_information_override_dnd().
43 * Please, take into account that this is only for important information.
46 * Two more kinds of banners are maintained for backward compatibility
47 * but are no longer recommended in Hildon 2.2. These are the animated
48 * banner (created with hildon_banner_show_animation()) and the
49 * progress banner (created with hildon_banner_show_progress()). See
50 * hildon_gtk_window_set_progress_indicator() for the preferred way of
51 * showing progress notifications in Hildon 2.2.
53 * Information banners dissapear automatically after a certain
54 * period. This is stored in the #HildonBanner:timeout property (in
55 * miliseconds), and can be changed using hildon_banner_set_timeout().
57 * Note that #HildonBanner<!-- -->s should only be used to display
58 * non-critical pieces of information.
66 #include <X11/Xatom.h>
69 #undef HILDON_DISABLE_DEPRECATED
71 #include "hildon-banner.h"
72 #include "hildon-banner-private.h"
73 #include "hildon-defines.h"
74 #include "hildon-gtk.h"
76 /* position relative to the screen */
78 #define HILDON_BANNER_WINDOW_X 0
80 #define HILDON_BANNER_WINDOW_Y HILDON_WINDOW_TITLEBAR_HEIGHT
84 #define HILDON_BANNER_PROGRESS_WIDTH 104
86 #define HILDON_BANNER_LABEL_MAX_TIMED \
87 (gdk_screen_width() - ((HILDON_MARGIN_TRIPLE) * 2))
89 #define HILDON_BANNER_LABEL_MAX_PROGRESS 375 /*265*/
93 #define HILDON_BANNER_DEFAULT_TIMEOUT 3000
97 #define HILDON_BANNER_DEFAULT_PROGRESS_ANIMATION "indicator_update"
99 /* animation related stuff */
101 #define HILDON_BANNER_ANIMATION_FRAMERATE ((float)1000/150)
103 #define HILDON_BANNER_ANIMATION_TMPL "indicator_update%d"
105 #define HILDON_BANNER_ANIMATION_NFRAMES 8
115 static GtkWidget* global_timed_banner = NULL;
118 hildon_banner_timed_quark (void);
121 hildon_banner_bind_style (HildonBanner *self,
125 hildon_banner_timeout (gpointer data);
128 hildon_banner_clear_timeout (HildonBanner *self);
131 hildon_banner_ensure_timeout (HildonBanner *self);
134 hildon_banner_set_property (GObject *object,
140 hildon_banner_get_property (GObject *object,
146 hildon_banner_destroy (GtkObject *object);
149 hildon_banner_real_get_instance (GObject *window,
153 hildon_banner_constructor (GType type,
154 guint n_construct_params,
155 GObjectConstructParam *construct_params);
158 hildon_banner_finalize (GObject *object);
161 hildon_banner_button_press_event (GtkWidget* widget,
162 GdkEventButton* event);
165 hildon_banner_map_event (GtkWidget *widget,
168 hildon_banner_reset_wrap_state (HildonBanner *banner);
171 force_to_wrap_truncated (HildonBanner *banner);
174 hildon_banner_check_position (GtkWidget *widget);
177 hildon_banner_realize (GtkWidget *widget);
180 hildon_banner_class_init (HildonBannerClass *klass);
183 hildon_banner_init (HildonBanner *self);
186 hildon_banner_ensure_child (HildonBanner *self,
187 GtkWidget *user_widget,
190 const gchar *first_property,
194 hildon_banner_get_instance_for_widget (GtkWidget *widget,
198 hildon_banner_set_override_flag (HildonBanner *banner);
201 hildon_banner_real_show_information (GtkWidget *widget,
203 gboolean override_dnd);
206 G_DEFINE_TYPE (HildonBanner, hildon_banner, GTK_TYPE_WINDOW)
209 hildon_banner_timed_quark (void)
211 static GQuark quark = 0;
213 if (G_UNLIKELY(quark == 0))
214 quark = g_quark_from_static_string ("hildon-banner-timed");
219 /* Set the widget and label name to make the correct rc-style attached into them */
221 hildon_banner_bind_style (HildonBanner *self,
222 const gchar *name_sufix)
224 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
229 name = g_strconcat ("HildonBannerLabel-", name_sufix, NULL);
230 gtk_widget_set_name (priv->label, name);
233 name = g_strconcat ("HildonBanner-", name_sufix, NULL);
234 gtk_widget_set_name (GTK_WIDGET (self), name);
238 /* In timeout function we automatically destroy timed banners */
240 simulate_close (GtkWidget* widget)
242 gboolean result = FALSE;
244 /* If the banner is currently visible (it normally should),
245 we simulate clicking the close button of the window.
246 This allows applications to reuse the banner by prevent
248 if (GTK_WIDGET_DRAWABLE (widget))
250 GdkEvent *event = gdk_event_new (GDK_DELETE);
251 event->any.window = g_object_ref (widget->window);
252 event->any.send_event = FALSE;
253 result = gtk_widget_event (widget, event);
254 gdk_event_free (event);
261 hildon_banner_timeout (gpointer data)
264 gboolean continue_timeout = FALSE;
266 GDK_THREADS_ENTER ();
268 g_assert (HILDON_IS_BANNER (data));
270 widget = GTK_WIDGET (data);
271 g_object_ref (widget);
273 continue_timeout = simulate_close (widget);
275 if (! continue_timeout) {
276 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (data);
277 priv->timeout_id = 0;
278 gtk_widget_destroy (widget);
281 g_object_unref (widget);
283 GDK_THREADS_LEAVE ();
285 return continue_timeout;
289 hildon_banner_clear_timeout (HildonBanner *self)
291 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
294 if (priv->timeout_id != 0) {
295 g_source_remove (priv->timeout_id);
296 priv->timeout_id = 0;
304 hildon_banner_ensure_timeout (HildonBanner *self)
306 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
309 if (priv->timeout_id == 0 && priv->is_timed && priv->timeout > 0)
310 priv->timeout_id = g_timeout_add (priv->timeout,
311 hildon_banner_timeout, self);
315 hildon_banner_set_property (GObject *object,
321 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
327 priv->timeout = g_value_get_uint (value);
331 priv->is_timed = g_value_get_boolean (value);
334 case PROP_PARENT_WINDOW:
335 window = g_value_get_object (value);
337 g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent);
340 gtk_window_set_transient_for (GTK_WINDOW (object), (GtkWindow *) window);
341 priv->parent = (GtkWindow *) window;
344 gtk_window_set_destroy_with_parent (GTK_WINDOW (object), TRUE);
345 g_object_add_weak_pointer(G_OBJECT (window), (gpointer) &priv->parent);
351 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
357 hildon_banner_get_property (GObject *object,
362 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
368 g_value_set_uint (value, priv->timeout);
372 g_value_set_boolean (value, priv->is_timed);
375 case PROP_PARENT_WINDOW:
376 g_value_set_object (value, gtk_window_get_transient_for (GTK_WINDOW (object)));
380 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
386 hildon_banner_destroy (GtkObject *object)
388 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
392 GObject *parent_window = (GObject *) priv->parent;
394 g_assert (HILDON_IS_BANNER (object));
395 self = HILDON_BANNER (object);
397 /* Drop possible global pointer. That can hold reference to us */
398 if ((gpointer) object == (gpointer) global_timed_banner) {
399 global_timed_banner = NULL;
400 g_object_unref (object);
403 /* Remove the data from parent window for timed banners. Those hold reference */
404 if (priv->is_timed && parent_window != NULL) {
405 g_object_set_qdata (parent_window, hildon_banner_timed_quark (), NULL);
408 if (!priv->is_timed && priv->parent) {
409 hildon_gtk_window_set_progress_indicator (priv->parent, 0);
412 (void) hildon_banner_clear_timeout (self);
414 if (GTK_OBJECT_CLASS (hildon_banner_parent_class)->destroy)
415 GTK_OBJECT_CLASS (hildon_banner_parent_class)->destroy (object);
418 /* Search a previous banner instance */
420 hildon_banner_real_get_instance (GObject *window,
424 /* If we have a parent window, the previous instance is stored there */
426 return g_object_get_qdata(window, hildon_banner_timed_quark ());
429 /* System notification instance is stored into global pointer */
430 return (GObject *) global_timed_banner;
433 /* Non-timed banners are normal (non-singleton) objects */
437 /* By overriding constructor we force timed banners to be
438 singletons for each window */
440 hildon_banner_constructor (GType type,
441 guint n_construct_params,
442 GObjectConstructParam *construct_params)
444 GObject *banner, *window = NULL;
445 gboolean timed = FALSE;
448 /* Search banner type information from parameters in order
449 to locate the possible previous banner instance. */
450 for (i = 0; i < n_construct_params; i++)
452 if (strcmp(construct_params[i].pspec->name, "parent-window") == 0)
453 window = g_value_get_object (construct_params[i].value);
454 else if (strcmp(construct_params[i].pspec->name, "is-timed") == 0)
455 timed = g_value_get_boolean (construct_params[i].value);
458 /* Try to get a previous instance if such exists */
459 banner = hildon_banner_real_get_instance (window, timed);
462 /* We have to create a new banner */
463 banner = G_OBJECT_CLASS (hildon_banner_parent_class)->constructor (type, n_construct_params, construct_params);
465 /* Store the newly created singleton instance either into parent
466 window data or into global variables. */
469 g_object_set_qdata_full (G_OBJECT (window), hildon_banner_timed_quark (),
470 g_object_ref (banner), g_object_unref);
472 g_assert (global_timed_banner == NULL);
473 global_timed_banner = g_object_ref (banner);
478 /* FIXME: This is a hack! We have to manually freeze
479 notifications. This is normally done by g_object_init, but we
480 are not going to call that. g_object_newv will otherwise give
481 a critical like this:
483 GLIB CRITICAL ** GLib-GObject - g_object_notify_queue_thaw:
484 assertion `nqueue->freeze_count > 0' failed */
486 g_object_freeze_notify (banner);
487 hildon_banner_reset_wrap_state (HILDON_BANNER (banner));
490 /* We restart possible timeouts for each new timed banner request */
491 if (timed && hildon_banner_clear_timeout (HILDON_BANNER (banner)))
492 hildon_banner_ensure_timeout (HILDON_BANNER(banner));
498 hildon_banner_finalize (GObject *object)
500 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
503 g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent);
506 G_OBJECT_CLASS (hildon_banner_parent_class)->finalize (object);
510 hildon_banner_button_press_event (GtkWidget* widget,
511 GdkEventButton* event)
513 gboolean result = simulate_close (widget);
516 /* signal emission not stopped - basically behave like
517 * gtk_main_do_event() for a delete event, but just hide the
518 * banner instead of destroying it, as it is already meant to
519 * be destroyed by hildon_banner_timeout() (if it's timed) or
520 * the application (if it's not). */
521 gtk_widget_hide (widget);
527 #if defined(MAEMO_GTK)
529 hildon_banner_map (GtkWidget *widget)
531 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->map) {
532 /* Make the banner temporary _before_ mapping it, to avoid closing
533 * other temporary windows */
534 gtk_window_set_is_temporary (GTK_WINDOW (widget), TRUE);
536 GTK_WIDGET_CLASS (hildon_banner_parent_class)->map (widget);
538 /* Make the banner non-temporary _after_ mapping it, to avoid
539 * being closed by other non-temporary windows */
540 gtk_window_set_is_temporary (GTK_WINDOW (widget), FALSE);
542 hildon_banner_check_position (widget);
547 /* We start the timer for timed notifications after the window appears on screen */
549 hildon_banner_map_event (GtkWidget *widget,
552 gboolean result = FALSE;
554 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->map_event)
555 result = GTK_WIDGET_CLASS (hildon_banner_parent_class)->map_event (widget, event);
557 hildon_banner_ensure_timeout (HILDON_BANNER(widget));
563 hildon_banner_reset_wrap_state (HildonBanner *banner)
566 HildonBannerPrivate *priv;
568 priv = HILDON_BANNER_GET_PRIVATE (banner);
571 layout = gtk_label_get_layout (GTK_LABEL (priv->label));
573 pango_layout_set_width (layout, -1);
574 priv->has_been_wrapped = FALSE;
575 priv->has_been_truncated = FALSE;
577 gtk_widget_set_size_request (priv->label, -1, -1);
578 gtk_widget_set_size_request (GTK_WIDGET (banner), -1, -1);
581 /* force to wrap truncated label by setting explicit size request
582 * see N#27000 and G#329646 */
584 force_to_wrap_truncated (HildonBanner *banner)
588 int width_text, width_max;
591 PangoRectangle logical;
592 GtkRequisition requisition;
593 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (banner);
595 g_return_if_fail (priv);
597 label = GTK_LABEL (priv->label);
599 layout = gtk_label_get_layout (label);
601 pango_layout_get_extents (layout, NULL, &logical);
602 width_text = PANGO_PIXELS (logical.width);
604 width_max = priv->is_timed ? HILDON_BANNER_LABEL_MAX_TIMED
605 : HILDON_BANNER_LABEL_MAX_PROGRESS;
607 /* If the width of the label is going to exceed the maximum allowed
608 * width, enforce the maximum allowed width now.
610 if (priv->has_been_wrapped
611 || width_text >= width_max
612 || pango_layout_is_wrapped (layout)) {
613 /* Force wrapping by setting the maximum size */
616 priv->has_been_wrapped = TRUE;
619 /* Make the label update its layout; and update our layout pointer
620 * because the layout will be cleared and refreshed.
622 gtk_widget_set_size_request (GTK_WIDGET (label), width, height);
623 gtk_widget_size_request (GTK_WIDGET (label), &requisition);
625 layout = gtk_label_get_layout (label);
627 /* If the layout has now been wrapped and exceeds 3 lines, we truncate
628 * the rest of the label according to spec.
630 if (priv->has_been_truncated
631 || (pango_layout_is_wrapped (layout)
632 && pango_layout_get_line_count (layout) > 3)) {
635 pango_layout_get_extents (layout, NULL, &logical);
636 lines = pango_layout_get_line_count (layout);
638 /* This calculation assumes that the same font is used
639 * throughout the banner -- this is usually the case on maemo
641 * FIXME: Pango >= 1.20 has pango_layout_set_height().
643 height = (PANGO_PIXELS (logical.height) * 3) / lines + 1;
644 priv->has_been_truncated = TRUE;
647 /* Set the new width/height if applicable */
648 gtk_widget_set_size_request (GTK_WIDGET (label), width, height);
653 hildon_banner_check_position (GtkWidget *widget)
658 gtk_widget_set_size_request (widget, gdk_screen_width (), -1);
660 force_to_wrap_truncated (HILDON_BANNER(widget)); /* see N#27000 and G#329646 */
662 gtk_widget_size_request (widget, &req);
669 x = HILDON_BANNER_WINDOW_X;
671 y = HILDON_BANNER_WINDOW_Y;
673 gtk_window_move (GTK_WINDOW (widget), x, y);
677 hildon_banner_realize (GtkWidget *widget)
681 guint32 portrait = 1;
682 const gchar *notification_type = "_HILDON_NOTIFICATION_TYPE_BANNER";
683 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (widget);
686 /* We let the parent to init widget->window before we need it */
687 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->realize)
688 GTK_WIDGET_CLASS (hildon_banner_parent_class)->realize (widget);
690 /* We use special hint to turn the banner into information notification. */
691 gdk_window_set_type_hint (widget->window, GDK_WINDOW_TYPE_HINT_NOTIFICATION);
692 gtk_window_set_transient_for (GTK_WINDOW (widget), (GtkWindow *) priv->parent);
694 hildon_banner_check_position (widget);
696 gdkwin = widget->window;
698 /* Set the _HILDON_NOTIFICATION_TYPE property so Matchbox places the window correctly */
699 atom = gdk_atom_intern ("_HILDON_NOTIFICATION_TYPE", FALSE);
700 gdk_property_change (gdkwin, atom, gdk_x11_xatom_to_atom (XA_STRING), 8, GDK_PROP_MODE_REPLACE,
701 (gpointer) notification_type, strlen (notification_type));
703 /* HildonBanner supports portrait mode */
704 atom = gdk_atom_intern ("_HILDON_PORTRAIT_MODE_SUPPORT", FALSE);
705 gdk_property_change (gdkwin, atom, gdk_x11_xatom_to_atom (XA_CARDINAL), 32,
706 GDK_PROP_MODE_REPLACE, (gpointer) &portrait, 1);
708 /* Manage override flag */
709 if ((priv->require_override_dnd)&&(!priv->overrides_dnd)) {
710 hildon_banner_set_override_flag (HILDON_BANNER (widget));
711 priv->overrides_dnd = TRUE;
716 hildon_banner_class_init (HildonBannerClass *klass)
718 GObjectClass *object_class;
719 GtkWidgetClass *widget_class;
721 object_class = G_OBJECT_CLASS (klass);
722 widget_class = GTK_WIDGET_CLASS (klass);
724 /* Append private structure to class. This is more elegant than
725 on g_new based approach */
726 g_type_class_add_private (klass, sizeof (HildonBannerPrivate));
728 /* Override virtual methods */
729 object_class->constructor = hildon_banner_constructor;
730 object_class->finalize = hildon_banner_finalize;
731 object_class->set_property = hildon_banner_set_property;
732 object_class->get_property = hildon_banner_get_property;
733 GTK_OBJECT_CLASS (klass)->destroy = hildon_banner_destroy;
734 widget_class->map_event = hildon_banner_map_event;
735 widget_class->realize = hildon_banner_realize;
736 widget_class->button_press_event = hildon_banner_button_press_event;
737 #if defined(MAEMO_GTK)
738 widget_class->map = hildon_banner_map;
741 /* Install properties.
742 We need construct properties for singleton purposes */
745 * HildonBanner:parent-window:
747 * The window for which the banner will be singleton.
750 g_object_class_install_property (object_class, PROP_PARENT_WINDOW,
751 g_param_spec_object ("parent-window",
753 "The window for which the banner will be singleton",
754 GTK_TYPE_WINDOW, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
757 * HildonBanner:is-timed:
759 * Whether the banner is timed and goes away automatically.
762 g_object_class_install_property (object_class, PROP_IS_TIMED,
763 g_param_spec_boolean ("is-timed",
765 "Whether or not the notification goes away automatically "
766 "after the specified time has passed",
767 FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
770 * HildonBanner:timeout:
772 * The time before making the banner banner go away. This needs
773 * to be adjusted before the banner is mapped to the screen.
776 g_object_class_install_property (object_class, PROP_TIMEOUT,
777 g_param_spec_uint ("timeout",
779 "The time before making the banner banner go away",
782 HILDON_BANNER_DEFAULT_TIMEOUT,
783 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
787 hildon_banner_init (HildonBanner *self)
789 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
793 priv->overrides_dnd = FALSE;
794 priv->require_override_dnd = FALSE;
796 /* Initialize the common layout inside banner */
797 priv->layout = gtk_hbox_new (FALSE, HILDON_MARGIN_DEFAULT);
799 priv->label = g_object_new (GTK_TYPE_LABEL, NULL);
800 gtk_label_set_line_wrap (GTK_LABEL (priv->label), TRUE);
801 gtk_label_set_line_wrap_mode (GTK_LABEL (priv->label), PANGO_WRAP_WORD_CHAR);
803 gtk_container_set_border_width (GTK_CONTAINER (priv->layout), HILDON_MARGIN_DEFAULT);
804 gtk_container_add (GTK_CONTAINER (self), priv->layout);
805 gtk_box_pack_start (GTK_BOX (priv->layout), priv->label, TRUE, TRUE, 0);
807 gtk_window_set_accept_focus (GTK_WINDOW (self), FALSE);
809 hildon_banner_reset_wrap_state (self);
811 gtk_widget_add_events (GTK_WIDGET (self), GDK_BUTTON_PRESS_MASK);
814 /* Makes sure that icon/progress item contains the desired type
815 of item. If possible, tries to avoid creating a new widget but
816 reuses the existing one */
818 hildon_banner_ensure_child (HildonBanner *self,
819 GtkWidget *user_widget,
822 const gchar *first_property,
827 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
831 widget = priv->main_item;
832 va_start (args, first_property);
834 /* Reuse existing widget if possible */
835 if (! user_widget && G_TYPE_CHECK_INSTANCE_TYPE (widget, type))
837 g_object_set_valist (G_OBJECT (widget), first_property, args);
841 /* We have to abandon old content widget */
843 gtk_container_remove (GTK_CONTAINER (priv->layout), widget);
845 /* Use user provided widget or create a new one */
846 priv->main_item = widget = user_widget ?
847 user_widget : GTK_WIDGET (g_object_new_valist(type, first_property, args));
848 gtk_box_pack_start (GTK_BOX (priv->layout), widget, TRUE, TRUE, 0);
851 /* We make sure that the widget exists in desired position. Different
852 banners place this child widget to different places */
853 gtk_box_reorder_child (GTK_BOX (priv->layout), widget, pos);
857 /* Creates a new banner instance or uses an existing one */
859 hildon_banner_get_instance_for_widget (GtkWidget *widget,
864 window = widget ? gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW) : NULL;
865 return g_object_new (HILDON_TYPE_BANNER, "parent-window", window, "is-timed", timed, NULL);
869 hildon_banner_create_animation (void)
872 GdkPixbufSimpleAnim *anim;
875 GError *error = NULL;
879 anim = gdk_pixbuf_simple_anim_new (HILDON_ICON_PIXEL_SIZE_STYLUS,
880 HILDON_ICON_PIXEL_SIZE_STYLUS,
881 HILDON_BANNER_ANIMATION_FRAMERATE);
882 gdk_pixbuf_simple_anim_set_loop (anim, TRUE);
883 theme = gtk_icon_theme_get_default ();
885 for (i = 1; i <= HILDON_BANNER_ANIMATION_NFRAMES; i++) {
886 icon_name = g_strdup_printf (HILDON_BANNER_ANIMATION_TMPL, i);
887 frame = gtk_icon_theme_load_icon (theme, icon_name, HILDON_ICON_PIXEL_SIZE_STYLUS,
891 g_warning ("Icon theme lookup for icon `%s' failed: %s",
892 icon_name, error->message);
893 g_error_free (error);
896 gdk_pixbuf_simple_anim_add_frame (anim, frame);
899 g_object_unref (frame);
903 image = gtk_image_new_from_animation (GDK_PIXBUF_ANIMATION (anim));
904 g_object_unref (anim);
910 * hildon_banner_show_information:
911 * @widget: the #GtkWidget that is the owner of the banner
912 * @icon_name: since Hildon 2.2 this parameter is not used anymore and
913 * any value that you pass will be ignored
914 * @text: Text to display
916 * This function creates and displays an information banner that
917 * automatically goes away after certain time period. For each window
918 * in your application there can only be one timed banner, so if you
919 * spawn a new banner before the earlier one has timed out, the
920 * previous one will be replaced.
922 * Returns: The newly created banner
926 hildon_banner_show_information (GtkWidget *widget,
927 const gchar *icon_name,
930 return hildon_banner_real_show_information (widget, text, FALSE);
934 * hildon_banner_show_information_override_dnd:
935 * @widget: the #GtkWidget that is the owner of the banner
936 * @icon_name: since Hildon 2.2 this parameter is not used anymore and
937 * any value that you pass will be ignored
938 * @text: Text to display
940 * Equivalent to hildon_banner_show_information() but it overrides the do not
941 * disturb flag, in the special cases that could be needed. It is required
942 * because this method calls internally gtk_widget_show before returns the banner,
943 * but the do not disturb flag is checked on the mapping of the widget
946 * Returns: The newly created banner
952 hildon_banner_show_information_override_dnd (GtkWidget *widget,
953 const gchar *icon_name,
956 return hildon_banner_real_show_information (widget, text, TRUE);
960 hildon_banner_set_override_flag (HildonBanner *banner)
964 gdk_property_change (GTK_WIDGET (banner)->window,
965 gdk_atom_intern_static_string ("_HILDON_DO_NOT_DISTURB_OVERRIDE"),
966 gdk_x11_xatom_to_atom (XA_INTEGER),
968 GDK_PROP_MODE_REPLACE,
969 (const guchar*) &state,
975 hildon_banner_real_show_information (GtkWidget *widget,
977 gboolean override_dnd)
979 HildonBanner *banner;
980 HildonBannerPrivate *priv = NULL;
982 g_return_val_if_fail (text != NULL, NULL);
985 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
986 priv = HILDON_BANNER_GET_PRIVATE (banner);
988 hildon_banner_set_text (banner, text);
989 hildon_banner_bind_style (banner, "information");
992 /* so on the realize it will set the property */
993 priv->require_override_dnd = TRUE;
996 /* Show the banner, since caller cannot do that */
997 gtk_widget_show_all (GTK_WIDGET (banner));
999 return GTK_WIDGET (banner);
1003 * hildon_banner_show_informationf:
1004 * @widget: the #GtkWidget that is the owner of the banner
1005 * @icon_name: since Hildon 2.2 this parameter is not used anymore and
1006 * any value that you pass will be ignored
1007 * @format: a printf-like format string
1008 * @Varargs: arguments for the format string
1010 * A helper function for #hildon_banner_show_information with
1011 * string formatting.
1013 * Returns: the newly created banner
1016 hildon_banner_show_informationf (GtkWidget *widget,
1017 const gchar *icon_name,
1018 const gchar *format,
1021 g_return_val_if_fail (format != NULL, NULL);
1027 va_start (args, format);
1028 message = g_strdup_vprintf (format, args);
1031 banner = hildon_banner_show_information (widget, icon_name, message);
1039 * hildon_banner_show_information_with_markup:
1040 * @widget: the #GtkWidget that wants to display banner
1041 * @icon_name: since Hildon 2.2 this parameter is not used anymore and
1042 * any value that you pass will be ignored
1043 * @markup: a markup string to display (see <link linkend="PangoMarkupFormat">Pango markup format</link>)
1045 * This function creates and displays an information banner that
1046 * automatically goes away after certain time period. For each window
1047 * in your application there can only be one timed banner, so if you
1048 * spawn a new banner before the earlier one has timed out, the
1049 * previous one will be replaced.
1051 * Returns: the newly created banner
1055 hildon_banner_show_information_with_markup (GtkWidget *widget,
1056 const gchar *icon_name,
1057 const gchar *markup)
1059 HildonBanner *banner;
1061 g_return_val_if_fail (icon_name == NULL || icon_name[0] != 0, NULL);
1062 g_return_val_if_fail (markup != NULL, NULL);
1064 /* Prepare banner */
1065 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
1067 hildon_banner_set_markup (banner, markup);
1068 hildon_banner_bind_style (banner, "information");
1070 /* Show the banner, since caller cannot do that */
1071 gtk_widget_show_all (GTK_WIDGET (banner));
1073 return (GtkWidget *) banner;
1077 * hildon_banner_show_animation:
1078 * @widget: the #GtkWidget that wants to display banner
1079 * @animation_name: since Hildon 2.2 this parameter is not used
1080 * anymore and any value that you pass will be
1082 * @text: the text to display.
1084 * Shows an animated progress notification. It's recommended not to try
1085 * to show more than one progress notification at a time, since
1086 * they will appear on top of each other. You can use progress
1087 * notifications with timed banners. In this case the banners are
1088 * located so that you can somehow see both.
1090 * Please note that banners are destroyed automatically once the
1091 * window they are attached to is closed. The pointer that you receive
1092 * with this function does not contain additional references, so it
1093 * can become invalid without warning (this is true for all toplevel
1094 * windows in gtk). To make sure that the banner does not disappear
1095 * automatically, you can separately ref the return value (this
1096 * doesn't prevent the banner from disappearing, just the object from
1097 * being finalized). In this case you have to call both
1098 * gtk_widget_destroy() followed by g_object_unref() (in this order).
1100 * Returns: a #HildonBanner widget. You must call gtk_widget_destroy()
1101 * once you are done with the banner.
1103 * Deprecated: Hildon 2.2: use
1104 * hildon_gtk_window_set_progress_indicator() instead.
1107 hildon_banner_show_animation (GtkWidget *widget,
1108 const gchar *animation_name,
1111 HildonBanner *banner;
1112 GtkWidget *image_widget;
1114 g_return_val_if_fail (text != NULL, NULL);
1116 image_widget = hildon_banner_create_animation ();
1118 /* Prepare banner */
1119 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
1120 hildon_banner_ensure_child (banner, image_widget, 0,
1121 GTK_TYPE_IMAGE, "yalign", 0.0, NULL);
1123 hildon_banner_set_text (banner, text);
1124 hildon_banner_bind_style (banner, "animation");
1127 gtk_widget_show_all (GTK_WIDGET (banner));
1129 return (GtkWidget *) banner;
1133 * hildon_banner_show_progress:
1134 * @widget: the #GtkWidget that wants to display banner
1135 * @bar: since Hildon 2.2 this parameter is not used anymore and
1136 * any value that you pass will be ignored
1137 * @text: text to display.
1139 * Shows progress notification. See #hildon_banner_show_animation
1140 * for more information.
1142 * Returns: a #HildonBanner widget. You must call #gtk_widget_destroy
1143 * once you are done with the banner.
1145 * Deprecated: Hildon 2.2: use hildon_gtk_window_set_progress_indicator() instead.
1148 hildon_banner_show_progress (GtkWidget *widget,
1149 GtkProgressBar *bar,
1152 HildonBanner *banner;
1153 HildonBannerPrivate *priv;
1155 g_return_val_if_fail (text != NULL, NULL);
1157 /* Prepare banner */
1158 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
1159 priv = HILDON_BANNER_GET_PRIVATE (banner);
1162 hildon_banner_set_text (banner, text);
1163 hildon_banner_bind_style (banner, "progress");
1166 hildon_gtk_window_set_progress_indicator (priv->parent, 1);
1168 /* Show the banner */
1169 gtk_widget_show_all (GTK_WIDGET (banner));
1171 return GTK_WIDGET (banner);
1175 * hildon_banner_set_text:
1176 * @self: a #HildonBanner widget
1177 * @text: a new text to display in banner
1179 * Sets the text that is displayed in the banner.
1183 hildon_banner_set_text (HildonBanner *self,
1187 HildonBannerPrivate *priv;
1188 const gchar *existing_text;
1190 g_return_if_fail (HILDON_IS_BANNER (self));
1192 priv = HILDON_BANNER_GET_PRIVATE (self);
1195 label = GTK_LABEL (priv->label);
1196 existing_text = gtk_label_get_text (label);
1198 if (existing_text != NULL &&
1200 strcmp (existing_text, text) != 0) {
1201 gtk_label_set_text (label, text);
1202 hildon_banner_reset_wrap_state (self);
1205 hildon_banner_check_position (GTK_WIDGET (self));
1209 * hildon_banner_set_markup:
1210 * @self: a #HildonBanner widget
1211 * @markup: a new text with Pango markup to display in the banner
1213 * Sets the text with markup that is displayed in the banner.
1217 hildon_banner_set_markup (HildonBanner *self,
1218 const gchar *markup)
1221 HildonBannerPrivate *priv;
1223 g_return_if_fail (HILDON_IS_BANNER (self));
1225 priv = HILDON_BANNER_GET_PRIVATE (self);
1228 label = GTK_LABEL (priv->label);
1229 gtk_label_set_markup (label, markup);
1231 hildon_banner_reset_wrap_state (self);
1233 hildon_banner_check_position (GTK_WIDGET(self));
1237 * hildon_banner_set_fraction:
1238 * @self: a #HildonBanner widget
1239 * @fraction: #gdouble
1241 * The fraction is the completion of progressbar,
1242 * the scale is from 0.0 to 1.0.
1243 * Sets the amount of fraction the progressbar has.
1245 * Note that this method only has effect if @self was created with
1246 * hildon_banner_show_progress()
1248 * Deprecated: This function does nothing. As of Hildon 2.2, hildon
1249 * banners don't have progress bars.
1252 hildon_banner_set_fraction (HildonBanner *self,
1258 * hildon_banner_set_timeout:
1259 * @self: a #HildonBanner widget
1260 * @timeout: timeout to set in miliseconds.
1262 * Sets the timeout on the banner. After the given amount of miliseconds
1263 * has elapsed the banner will go away. Note that settings this only makes
1264 * sense on the banners that are timed and that have not been yet displayed
1267 * Note that this method only has effect if @self is an information
1268 * banner (created using hildon_banner_show_information() and
1272 hildon_banner_set_timeout (HildonBanner *self,
1275 HildonBannerPrivate *priv;
1277 g_return_if_fail (HILDON_IS_BANNER (self));
1278 priv = HILDON_BANNER_GET_PRIVATE (self);
1281 priv->timeout = timeout;
1285 * hildon_banner_set_icon:
1286 * @self: a #HildonBanner widget
1287 * @icon_name: the name of icon to use. Can be %NULL for default icon
1289 * Sets the icon to be used in the banner.
1291 * Deprecated: This function does nothing. As of hildon 2.2, hildon
1292 * banners don't allow changing their icons.
1295 hildon_banner_set_icon (HildonBanner *self,
1296 const gchar *icon_name)
1301 * hildon_banner_set_icon_from_file:
1302 * @self: a #HildonBanner widget
1303 * @icon_file: the filename of icon to use. Can be %NULL for default icon
1305 * Sets the icon from its filename to be used in the banner.
1307 * Deprecated: This function does nothing. As of hildon 2.2, hildon
1308 * banners don't allow changing their icons.
1311 hildon_banner_set_icon_from_file (HildonBanner *self,
1312 const gchar *icon_file)