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 shown. 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 are automatically destroyed 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.
61 * <title>Using the HildonBanner widget</title>
63 * void show_info_banner (GtkWidget *parent)
67 * banner = hildon_banner_show_information (widget, NULL, "Information banner");
68 * hildon_banner_set_timeout (HILDON_BANNER (banner), 9000);
81 #include <X11/Xatom.h>
84 #undef HILDON_DISABLE_DEPRECATED
86 #include "hildon-banner.h"
87 #include "hildon-private.h"
88 #include "hildon-defines.h"
89 #include "hildon-gtk.h"
93 #define HILDON_BANNER_LABEL_MAX_TIMED \
94 (gdk_screen_width() - ((HILDON_MARGIN_TRIPLE) * 2))
96 #define HILDON_BANNER_LABEL_MAX_PROGRESS 375 /*265*/
100 #define HILDON_BANNER_DEFAULT_TIMEOUT 3000
104 #define HILDON_BANNER_DEFAULT_PROGRESS_ANIMATION "indicator_update"
106 /* animation related stuff */
108 #define HILDON_BANNER_ANIMATION_FRAMERATE ((float)1000/150)
110 #define HILDON_BANNER_ANIMATION_TMPL "indicator_update%d"
112 #define HILDON_BANNER_ANIMATION_NFRAMES 8
122 static GtkWidget* global_timed_banner = NULL;
125 hildon_banner_timed_quark (void);
128 hildon_banner_bind_style (HildonBanner *self);
131 hildon_banner_timeout (gpointer data);
134 hildon_banner_clear_timeout (HildonBanner *self);
137 hildon_banner_ensure_timeout (HildonBanner *self);
140 hildon_banner_set_property (GObject *object,
146 hildon_banner_get_property (GObject *object,
152 hildon_banner_destroy (GtkObject *object);
155 hildon_banner_real_get_instance (GObject *window,
159 hildon_banner_constructor (GType type,
160 guint n_construct_params,
161 GObjectConstructParam *construct_params);
164 hildon_banner_finalize (GObject *object);
167 hildon_banner_button_press_event (GtkWidget* widget,
168 GdkEventButton* event);
171 hildon_banner_map_event (GtkWidget *widget,
175 force_to_wrap_truncated (HildonBanner *banner);
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,
199 hildon_banner_set_override_flag (HildonBanner *banner);
202 hildon_banner_real_show_information (GtkWidget *widget,
204 gboolean override_dnd);
206 G_DEFINE_TYPE (HildonBanner, hildon_banner, GTK_TYPE_WINDOW)
208 typedef struct _HildonBannerPrivate HildonBannerPrivate;
210 #define HILDON_BANNER_GET_PRIVATE(obj) \
211 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
212 HILDON_TYPE_BANNER, HildonBannerPrivate));
214 struct _HildonBannerPrivate
216 GtkWidget *main_item;
217 GtkWidget *alignment;
221 const gchar *name_suffix;
225 guint require_override_dnd : 1;
226 guint overrides_dnd : 1;
230 hildon_banner_timed_quark (void)
232 static GQuark quark = 0;
234 if (G_UNLIKELY(quark == 0))
235 quark = g_quark_from_static_string ("hildon-banner-timed");
240 /* Set the widget and label name to make the correct rc-style attached into them */
242 hildon_banner_bind_style (HildonBanner *self)
244 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
245 GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (self));
246 gboolean portrait = gdk_screen_get_width (screen) < gdk_screen_get_height (screen);
247 const gchar *portrait_suffix = portrait ? "-portrait" : NULL;
252 name = g_strconcat ("HildonBannerLabel-", priv->name_suffix, NULL);
253 gtk_widget_set_name (priv->label, name);
256 name = g_strconcat ("HildonBanner-", priv->name_suffix, portrait_suffix, NULL);
257 gtk_widget_set_name (GTK_WIDGET (self), name);
261 /* In timeout function we automatically destroy timed banners */
263 simulate_close (GtkWidget* widget)
265 gboolean result = FALSE;
267 /* If the banner is currently visible (it normally should),
268 we simulate clicking the close button of the window.
269 This allows applications to reuse the banner by prevent
271 if (GTK_WIDGET_DRAWABLE (widget))
273 GdkEvent *event = gdk_event_new (GDK_DELETE);
274 event->any.window = g_object_ref (widget->window);
275 event->any.send_event = FALSE;
276 result = gtk_widget_event (widget, event);
277 gdk_event_free (event);
284 hildon_banner_size_request (GtkWidget *self,
287 GTK_WIDGET_CLASS (hildon_banner_parent_class)->size_request (self, req);
288 req->width = gdk_screen_get_width (gtk_widget_get_screen (self));
292 hildon_banner_timeout (gpointer data)
295 gboolean continue_timeout = FALSE;
297 g_assert (HILDON_IS_BANNER (data));
299 widget = GTK_WIDGET (data);
300 g_object_ref (widget);
302 continue_timeout = simulate_close (widget);
304 if (! continue_timeout) {
305 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (data);
306 priv->timeout_id = 0;
307 gtk_widget_destroy (widget);
310 g_object_unref (widget);
312 return continue_timeout;
316 hildon_banner_clear_timeout (HildonBanner *self)
318 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
321 if (priv->timeout_id != 0) {
322 g_source_remove (priv->timeout_id);
323 priv->timeout_id = 0;
331 hildon_banner_ensure_timeout (HildonBanner *self)
333 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
336 if (priv->timeout_id == 0 && priv->is_timed && priv->timeout > 0)
337 priv->timeout_id = gdk_threads_add_timeout (priv->timeout,
338 hildon_banner_timeout, self);
342 hildon_banner_set_property (GObject *object,
348 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
354 priv->timeout = g_value_get_uint (value);
358 priv->is_timed = g_value_get_boolean (value);
361 case PROP_PARENT_WINDOW:
362 window = g_value_get_object (value);
364 g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent);
367 gtk_window_set_transient_for (GTK_WINDOW (object), (GtkWindow *) window);
368 priv->parent = (GtkWindow *) window;
371 gtk_window_set_destroy_with_parent (GTK_WINDOW (object), TRUE);
372 g_object_add_weak_pointer(G_OBJECT (window), (gpointer) &priv->parent);
378 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
384 hildon_banner_get_property (GObject *object,
389 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
395 g_value_set_uint (value, priv->timeout);
399 g_value_set_boolean (value, priv->is_timed);
402 case PROP_PARENT_WINDOW:
403 g_value_set_object (value, gtk_window_get_transient_for (GTK_WINDOW (object)));
407 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
413 hildon_banner_destroy (GtkObject *object)
415 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
419 GObject *parent_window = (GObject *) priv->parent;
421 g_assert (HILDON_IS_BANNER (object));
422 self = HILDON_BANNER (object);
424 /* Drop possible global pointer. That can hold reference to us */
425 if ((gpointer) object == (gpointer) global_timed_banner) {
426 global_timed_banner = NULL;
427 g_object_unref (object);
430 /* Remove the data from parent window for timed banners. Those hold reference */
431 if (priv->is_timed && parent_window != NULL) {
432 g_object_set_qdata (parent_window, hildon_banner_timed_quark (), NULL);
435 if (!priv->is_timed && priv->parent) {
436 hildon_gtk_window_set_progress_indicator (priv->parent, 0);
439 (void) hildon_banner_clear_timeout (self);
441 if (GTK_OBJECT_CLASS (hildon_banner_parent_class)->destroy)
442 GTK_OBJECT_CLASS (hildon_banner_parent_class)->destroy (object);
445 /* Search a previous banner instance */
447 hildon_banner_real_get_instance (GObject *window,
451 /* If we have a parent window, the previous instance is stored there */
453 return g_object_get_qdata(window, hildon_banner_timed_quark ());
456 /* System notification instance is stored into global pointer */
457 return (GObject *) global_timed_banner;
460 /* Non-timed banners are normal (non-singleton) objects */
464 /* By overriding constructor we force timed banners to be
465 singletons for each window */
467 hildon_banner_constructor (GType type,
468 guint n_construct_params,
469 GObjectConstructParam *construct_params)
471 GObject *banner, *window = NULL;
472 gboolean timed = FALSE;
475 /* Search banner type information from parameters in order
476 to locate the possible previous banner instance. */
477 for (i = 0; i < n_construct_params; i++)
479 if (strcmp(construct_params[i].pspec->name, "parent-window") == 0)
480 window = g_value_get_object (construct_params[i].value);
481 else if (strcmp(construct_params[i].pspec->name, "is-timed") == 0)
482 timed = g_value_get_boolean (construct_params[i].value);
485 /* Try to get a previous instance if such exists */
486 banner = hildon_banner_real_get_instance (window, timed);
489 /* We have to create a new banner */
490 banner = G_OBJECT_CLASS (hildon_banner_parent_class)->constructor (type, n_construct_params, construct_params);
492 /* Store the newly created singleton instance either into parent
493 window data or into global variables. */
496 g_object_set_qdata_full (G_OBJECT (window), hildon_banner_timed_quark (),
497 g_object_ref (banner), g_object_unref);
499 g_assert (global_timed_banner == NULL);
500 global_timed_banner = g_object_ref (banner);
505 /* FIXME: This is a hack! We have to manually freeze
506 notifications. This is normally done by g_object_init, but we
507 are not going to call that. g_object_newv will otherwise give
508 a critical like this:
510 GLIB CRITICAL ** GLib-GObject - g_object_notify_queue_thaw:
511 assertion `nqueue->freeze_count > 0' failed */
513 g_object_freeze_notify (banner);
516 /* We restart possible timeouts for each new timed banner request */
517 if (timed && hildon_banner_clear_timeout (HILDON_BANNER (banner)))
518 hildon_banner_ensure_timeout (HILDON_BANNER(banner));
524 hildon_banner_finalize (GObject *object)
526 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
529 g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent);
532 G_OBJECT_CLASS (hildon_banner_parent_class)->finalize (object);
536 hildon_banner_button_press_event (GtkWidget* widget,
537 GdkEventButton* event)
539 gboolean result = simulate_close (widget);
542 /* signal emission not stopped - basically behave like
543 * gtk_main_do_event() for a delete event, but just hide the
544 * banner instead of destroying it, as it is already meant to
545 * be destroyed by hildon_banner_timeout() (if it's timed) or
546 * the application (if it's not). */
547 gtk_widget_hide (widget);
553 #if defined(MAEMO_GTK)
555 hildon_banner_map (GtkWidget *widget)
557 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->map) {
558 /* Make the banner temporary _before_ mapping it, to avoid closing
559 * other temporary windows */
560 gtk_window_set_is_temporary (GTK_WINDOW (widget), TRUE);
562 GTK_WIDGET_CLASS (hildon_banner_parent_class)->map (widget);
564 /* Make the banner non-temporary _after_ mapping it, to avoid
565 * being closed by other non-temporary windows */
566 gtk_window_set_is_temporary (GTK_WINDOW (widget), FALSE);
568 gtk_window_move (GTK_WINDOW (widget), 0, HILDON_WINDOW_TITLEBAR_HEIGHT);
573 /* We start the timer for timed notifications after the window appears on screen */
575 hildon_banner_map_event (GtkWidget *widget,
578 gboolean result = FALSE;
580 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->map_event)
581 result = GTK_WIDGET_CLASS (hildon_banner_parent_class)->map_event (widget, event);
583 hildon_banner_ensure_timeout (HILDON_BANNER(widget));
589 banner_do_set_text (HildonBanner *banner,
593 HildonBannerPrivate *priv;
596 priv = HILDON_BANNER_GET_PRIVATE (banner);
599 gtk_label_set_markup (GTK_LABEL (priv->label), text);
601 gtk_label_set_text (GTK_LABEL (priv->label), text);
603 gtk_widget_set_size_request (priv->label, -1, -1);
604 gtk_widget_size_request (priv->label, &req);
606 force_to_wrap_truncated (banner);
609 /* force to wrap truncated label by setting explicit size request
610 * see N#27000 and G#329646 */
612 force_to_wrap_truncated (HildonBanner *banner)
619 PangoRectangle logical;
620 GtkRequisition requisition;
621 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (banner);
623 g_return_if_fail (priv);
625 label = GTK_LABEL (priv->label);
627 layout = gtk_label_get_layout (label);
629 pango_layout_get_extents (layout, NULL, &logical);
630 width = PANGO_PIXELS (logical.width);
632 width_max = priv->is_timed ? HILDON_BANNER_LABEL_MAX_TIMED
633 : HILDON_BANNER_LABEL_MAX_PROGRESS;
635 /* If the width of the label is going to exceed the maximum allowed
636 * width, enforce the maximum allowed width now.
638 if (width >= width_max || pango_layout_is_wrapped (layout)) {
642 /* Make the label update its layout; and update our layout pointer
643 * because the layout will be cleared and refreshed.
645 gtk_widget_set_size_request (GTK_WIDGET (label), width, height);
646 gtk_widget_size_request (GTK_WIDGET (label), &requisition);
648 layout = gtk_label_get_layout (label);
650 /* If the layout has now been wrapped and exceeds 3 lines, we truncate
651 * the rest of the label according to spec.
653 if (pango_layout_is_wrapped (layout) && pango_layout_get_line_count (layout) > 3) {
656 pango_layout_get_extents (layout, NULL, &logical);
657 lines = pango_layout_get_line_count (layout);
659 /* This calculation assumes that the same font is used
660 * throughout the banner -- this is usually the case on maemo
662 * FIXME: Pango >= 1.20 has pango_layout_set_height().
664 height = (PANGO_PIXELS (logical.height) * 3) / lines + 1;
667 /* Set the new width/height if applicable */
668 gtk_widget_set_size_request (GTK_WIDGET (label), width, height);
672 screen_size_changed (GdkScreen *screen,
676 hildon_banner_bind_style (HILDON_BANNER (banner));
677 gtk_window_reshow_with_initial_size (banner);
678 force_to_wrap_truncated (HILDON_BANNER (banner));
682 hildon_banner_realize (GtkWidget *widget)
687 guint32 portrait = 1;
688 const gchar *notification_type = "_HILDON_NOTIFICATION_TYPE_BANNER";
689 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (widget);
692 /* We let the parent to init widget->window before we need it */
693 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->realize)
694 GTK_WIDGET_CLASS (hildon_banner_parent_class)->realize (widget);
696 /* We use special hint to turn the banner into information notification. */
697 gdk_window_set_type_hint (widget->window, GDK_WINDOW_TYPE_HINT_NOTIFICATION);
698 gtk_window_set_transient_for (GTK_WINDOW (widget), (GtkWindow *) priv->parent);
700 gdkwin = widget->window;
702 /* Set the _HILDON_NOTIFICATION_TYPE property so Matchbox places the window correctly */
703 atom = gdk_atom_intern ("_HILDON_NOTIFICATION_TYPE", FALSE);
704 gdk_property_change (gdkwin, atom, gdk_x11_xatom_to_atom (XA_STRING), 8, GDK_PROP_MODE_REPLACE,
705 (gpointer) notification_type, strlen (notification_type));
707 /* HildonBanner supports portrait mode */
708 atom = gdk_atom_intern ("_HILDON_PORTRAIT_MODE_SUPPORT", FALSE);
709 gdk_property_change (gdkwin, atom, gdk_x11_xatom_to_atom (XA_CARDINAL), 32,
710 GDK_PROP_MODE_REPLACE, (gpointer) &portrait, 1);
712 /* Manage override flag */
713 if ((priv->require_override_dnd)&&(!priv->overrides_dnd)) {
714 hildon_banner_set_override_flag (HILDON_BANNER (widget));
715 priv->overrides_dnd = TRUE;
718 screen = gtk_widget_get_screen (widget);
719 g_signal_connect (screen, "size-changed", G_CALLBACK (screen_size_changed), widget);
723 hildon_banner_unrealize (GtkWidget *widget)
725 GdkScreen *screen = gtk_widget_get_screen (widget);
726 g_signal_handlers_disconnect_by_func (screen, G_CALLBACK (screen_size_changed), widget);
728 GTK_WIDGET_CLASS (hildon_banner_parent_class)->unrealize (widget);
732 hildon_banner_class_init (HildonBannerClass *klass)
734 GObjectClass *object_class;
735 GtkWidgetClass *widget_class;
737 object_class = G_OBJECT_CLASS (klass);
738 widget_class = GTK_WIDGET_CLASS (klass);
740 /* Append private structure to class. This is more elegant than
741 on g_new based approach */
742 g_type_class_add_private (klass, sizeof (HildonBannerPrivate));
744 /* Override virtual methods */
745 object_class->constructor = hildon_banner_constructor;
746 object_class->finalize = hildon_banner_finalize;
747 object_class->set_property = hildon_banner_set_property;
748 object_class->get_property = hildon_banner_get_property;
749 GTK_OBJECT_CLASS (klass)->destroy = hildon_banner_destroy;
750 widget_class->size_request = hildon_banner_size_request;
751 widget_class->map_event = hildon_banner_map_event;
752 widget_class->realize = hildon_banner_realize;
753 widget_class->unrealize = hildon_banner_unrealize;
754 widget_class->button_press_event = hildon_banner_button_press_event;
755 #if defined(MAEMO_GTK)
756 widget_class->map = hildon_banner_map;
759 /* Install properties.
760 We need construct properties for singleton purposes */
763 * HildonBanner:parent-window:
765 * The window for which the banner will be singleton.
768 g_object_class_install_property (object_class, PROP_PARENT_WINDOW,
769 g_param_spec_object ("parent-window",
771 "The window for which the banner will be singleton",
772 GTK_TYPE_WINDOW, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
775 * HildonBanner:is-timed:
777 * Whether the banner is timed and goes away automatically.
780 g_object_class_install_property (object_class, PROP_IS_TIMED,
781 g_param_spec_boolean ("is-timed",
783 "Whether or not the notification goes away automatically "
784 "after the specified time has passed",
785 FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
788 * HildonBanner:timeout:
790 * The time before destroying the banner. This needs
791 * to be adjusted before the banner is mapped to the screen.
794 g_object_class_install_property (object_class, PROP_TIMEOUT,
795 g_param_spec_uint ("timeout",
797 "The time before making the banner banner go away",
800 HILDON_BANNER_DEFAULT_TIMEOUT,
801 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
805 hildon_banner_init (HildonBanner *self)
807 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
811 priv->overrides_dnd = FALSE;
812 priv->require_override_dnd = FALSE;
813 priv->name_suffix = NULL;
815 /* Initialize the common layout inside banner */
816 priv->alignment = gtk_alignment_new (0.5, 0.5, 0, 0);
817 priv->layout = gtk_hbox_new (FALSE, HILDON_MARGIN_DEFAULT);
819 priv->label = g_object_new (GTK_TYPE_LABEL, NULL);
820 gtk_label_set_line_wrap (GTK_LABEL (priv->label), TRUE);
821 gtk_label_set_line_wrap_mode (GTK_LABEL (priv->label), PANGO_WRAP_WORD_CHAR);
822 gtk_label_set_justify (GTK_LABEL (priv->label), GTK_JUSTIFY_CENTER);
824 gtk_container_set_border_width (GTK_CONTAINER (priv->layout), HILDON_MARGIN_DEFAULT);
825 gtk_container_add (GTK_CONTAINER (self), priv->alignment);
826 gtk_container_add (GTK_CONTAINER (priv->alignment), priv->layout);
827 gtk_box_pack_start (GTK_BOX (priv->layout), priv->label, FALSE, FALSE, 0);
829 gtk_window_set_accept_focus (GTK_WINDOW (self), FALSE);
831 gtk_widget_add_events (GTK_WIDGET (self), GDK_BUTTON_PRESS_MASK);
834 /* Makes sure that icon/progress item contains the desired type
835 of item. If possible, tries to avoid creating a new widget but
836 reuses the existing one */
838 hildon_banner_ensure_child (HildonBanner *self,
839 GtkWidget *user_widget,
842 const gchar *first_property,
847 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
851 widget = priv->main_item;
852 va_start (args, first_property);
854 /* Reuse existing widget if possible */
855 if (! user_widget && G_TYPE_CHECK_INSTANCE_TYPE (widget, type))
857 g_object_set_valist (G_OBJECT (widget), first_property, args);
861 /* We have to abandon old content widget */
863 gtk_container_remove (GTK_CONTAINER (priv->layout), widget);
865 /* Use user provided widget or create a new one */
866 priv->main_item = widget = user_widget ?
867 user_widget : GTK_WIDGET (g_object_new_valist(type, first_property, args));
868 gtk_box_pack_start (GTK_BOX (priv->layout), widget, FALSE, FALSE, 0);
871 /* We make sure that the widget exists in desired position. Different
872 banners place this child widget to different places */
873 gtk_box_reorder_child (GTK_BOX (priv->layout), widget, pos);
877 /* Creates a new banner instance or uses an existing one */
879 hildon_banner_get_instance_for_widget (GtkWidget *widget,
884 window = widget ? gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW) : NULL;
885 return g_object_new (HILDON_TYPE_BANNER, "parent-window", window, "is-timed", timed, NULL);
889 * hildon_banner_show_information:
890 * @widget: the #GtkWidget that is the owner of the banner
891 * @icon_name: since Hildon 2.2 this parameter is not used anymore and
892 * any value that you pass will be ignored
893 * @text: Text to display
895 * This function creates and displays an information banner that is
896 * automatically destroyed after a certain time period (see
897 * hildon_banner_set_timeout()). For each window in your application
898 * there can only be one timed banner, so if you spawn a new banner
899 * before the earlier one has timed out, the previous one will be
902 * Returns: The newly created banner
906 hildon_banner_show_information (GtkWidget *widget,
907 const gchar *icon_name,
910 return hildon_banner_real_show_information (widget, text, FALSE);
914 * hildon_banner_show_information_override_dnd:
915 * @widget: the #GtkWidget that is the owner of the banner
916 * @text: Text to display
918 * Equivalent to hildon_banner_show_information(), but overriding the
919 * "do not disturb" flag.
921 * Returns: The newly created banner
927 hildon_banner_show_information_override_dnd (GtkWidget *widget,
930 return hildon_banner_real_show_information (widget, text, TRUE);
934 hildon_banner_set_override_flag (HildonBanner *banner)
938 gdk_property_change (GTK_WIDGET (banner)->window,
939 gdk_atom_intern_static_string ("_HILDON_DO_NOT_DISTURB_OVERRIDE"),
940 gdk_x11_xatom_to_atom (XA_INTEGER),
942 GDK_PROP_MODE_REPLACE,
943 (const guchar*) &state,
948 reshow_banner (HildonBanner *banner)
950 if (GTK_WIDGET_VISIBLE (banner)) {
951 gint width = gdk_screen_get_width (gtk_widget_get_screen (GTK_WIDGET (banner)));
952 gtk_window_resize (GTK_WINDOW (banner), width, 1);
954 force_to_wrap_truncated (banner);
955 gtk_widget_show_all (GTK_WIDGET (banner));
959 hildon_banner_real_show_information (GtkWidget *widget,
961 gboolean override_dnd)
963 HildonBanner *banner;
964 HildonBannerPrivate *priv = NULL;
966 g_return_val_if_fail (text != NULL, NULL);
969 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
970 priv = HILDON_BANNER_GET_PRIVATE (banner);
972 priv->name_suffix = "information";
973 banner_do_set_text (banner, text, FALSE);
974 hildon_banner_bind_style (banner);
977 /* so on the realize it will set the property */
978 priv->require_override_dnd = TRUE;
981 /* Show the banner, since caller cannot do that */
982 reshow_banner (banner);
984 return GTK_WIDGET (banner);
988 * hildon_banner_show_informationf:
989 * @widget: the #GtkWidget that is the owner of the banner
990 * @icon_name: since Hildon 2.2 this parameter is not used anymore and
991 * any value that you pass will be ignored
992 * @format: a printf-like format string
993 * @Varargs: arguments for the format string
995 * A helper function for hildon_banner_show_information() with
998 * Returns: the newly created banner
1001 hildon_banner_show_informationf (GtkWidget *widget,
1002 const gchar *icon_name,
1003 const gchar *format,
1006 g_return_val_if_fail (format != NULL, NULL);
1012 va_start (args, format);
1013 message = g_strdup_vprintf (format, args);
1016 banner = hildon_banner_show_information (widget, icon_name, message);
1024 * hildon_banner_show_information_with_markup:
1025 * @widget: the #GtkWidget that wants to display banner
1026 * @icon_name: since Hildon 2.2 this parameter is not used anymore and
1027 * any value that you pass will be ignored
1028 * @markup: a markup string to display (see <link linkend="PangoMarkupFormat">Pango markup format</link>)
1030 * This function creates and displays an information banner that is
1031 * automatically destroyed after certain time period (see
1032 * hildon_banner_set_timeout()). For each window in your application
1033 * there can only be one timed banner, so if you spawn a new banner
1034 * before the earlier one has timed out, the previous one will be
1037 * Returns: the newly created banner
1041 hildon_banner_show_information_with_markup (GtkWidget *widget,
1042 const gchar *icon_name,
1043 const gchar *markup)
1045 HildonBanner *banner;
1046 HildonBannerPrivate *priv;
1048 g_return_val_if_fail (icon_name == NULL || icon_name[0] != 0, NULL);
1049 g_return_val_if_fail (markup != NULL, NULL);
1051 /* Prepare banner */
1052 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
1053 priv = HILDON_BANNER_GET_PRIVATE (banner);
1055 priv->name_suffix = "information";
1056 banner_do_set_text (banner, markup, TRUE);
1057 hildon_banner_bind_style (banner);
1059 /* Show the banner, since caller cannot do that */
1060 reshow_banner (banner);
1062 return (GtkWidget *) banner;
1066 * hildon_banner_show_animation:
1067 * @widget: the #GtkWidget that wants to display banner
1068 * @animation_name: since Hildon 2.2 this parameter is not used
1069 * anymore and any value that you pass will be
1071 * @text: the text to display.
1073 * Shows an animated progress notification. It's recommended not to try
1074 * to show more than one progress notification at a time, since
1075 * they will appear on top of each other. You can use progress
1076 * notifications with timed banners. In this case the banners are
1077 * located so that you can somehow see both.
1079 * Unlike information banners (created with
1080 * hildon_banner_show_information()), animation banners are not
1081 * destroyed automatically using a timeout. You have to destroy them
1084 * Please note also that these banners are destroyed automatically if the
1085 * window they are attached to is closed. The pointer that you receive
1086 * with this function does not contain additional references, so it
1087 * can become invalid without warning (this is true for all toplevel
1088 * windows in gtk). To make sure that the banner does not disappear
1089 * automatically, you can separately ref the return value (this
1090 * doesn't prevent the banner from disappearing, just the object from
1091 * being finalized). In this case you have to call
1092 * gtk_widget_destroy() followed by g_object_unref().
1094 * Returns: a #HildonBanner widget. You must call gtk_widget_destroy()
1095 * once you are done with the banner.
1097 * Deprecated: Hildon 2.2: use
1098 * hildon_gtk_window_set_progress_indicator() instead.
1101 hildon_banner_show_animation (GtkWidget *widget,
1102 const gchar *animation_name,
1105 HildonBanner *banner;
1106 GtkWidget *image_widget;
1107 HildonBannerPrivate *priv;
1109 g_return_val_if_fail (text != NULL, NULL);
1111 image_widget = hildon_private_create_animation (
1112 HILDON_BANNER_ANIMATION_FRAMERATE,
1113 HILDON_BANNER_ANIMATION_TMPL,
1114 HILDON_BANNER_ANIMATION_NFRAMES);
1116 /* Prepare banner */
1117 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
1118 hildon_banner_ensure_child (banner, image_widget, 0,
1119 GTK_TYPE_IMAGE, "yalign", 0.0, NULL);
1121 priv = HILDON_BANNER_GET_PRIVATE (banner);
1122 priv->name_suffix = "animation";
1123 banner_do_set_text (banner, text, FALSE);
1124 hildon_banner_bind_style (banner);
1127 reshow_banner (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 priv->name_suffix = "progress";
1163 banner_do_set_text (banner, text, FALSE);
1164 hildon_banner_bind_style (banner);
1167 hildon_gtk_window_set_progress_indicator (priv->parent, 1);
1169 /* Show the banner */
1170 reshow_banner (banner);
1172 return GTK_WIDGET (banner);
1176 * hildon_banner_set_text:
1177 * @self: a #HildonBanner widget
1178 * @text: a new text to display in banner
1180 * Sets the text that is displayed in the banner.
1184 hildon_banner_set_text (HildonBanner *self,
1187 g_return_if_fail (HILDON_IS_BANNER (self));
1189 banner_do_set_text (self, text, FALSE);
1191 if (GTK_WIDGET_VISIBLE (self))
1192 reshow_banner (self);
1196 * hildon_banner_set_markup:
1197 * @self: a #HildonBanner widget
1198 * @markup: a new text with Pango markup to display in the banner
1200 * Sets the text with markup that is displayed in the banner.
1204 hildon_banner_set_markup (HildonBanner *self,
1205 const gchar *markup)
1207 g_return_if_fail (HILDON_IS_BANNER (self));
1209 banner_do_set_text (self, markup, TRUE);
1211 if (GTK_WIDGET_VISIBLE (self))
1212 reshow_banner (self);
1216 * hildon_banner_set_fraction:
1217 * @self: a #HildonBanner widget
1218 * @fraction: #gdouble
1220 * The fraction is the completion of progressbar,
1221 * the scale is from 0.0 to 1.0.
1222 * Sets the amount of fraction the progressbar has.
1224 * Note that this method only has effect if @self was created with
1225 * hildon_banner_show_progress()
1227 * Deprecated: This function does nothing. As of Hildon 2.2, hildon
1228 * banners don't have progress bars.
1231 hildon_banner_set_fraction (HildonBanner *self,
1237 * hildon_banner_set_timeout:
1238 * @self: a #HildonBanner widget
1239 * @timeout: timeout to set in miliseconds.
1241 * Sets the timeout on the banner. After the given amount of miliseconds
1242 * has elapsed the banner will be destroyed. Setting this only makes
1243 * sense on banners that are timed and that have not been yet displayed
1246 * Note that this method only has effect if @self is an information
1247 * banner (created using hildon_banner_show_information() and
1251 hildon_banner_set_timeout (HildonBanner *self,
1254 HildonBannerPrivate *priv;
1256 g_return_if_fail (HILDON_IS_BANNER (self));
1257 priv = HILDON_BANNER_GET_PRIVATE (self);
1260 priv->timeout = timeout;
1264 * hildon_banner_set_icon:
1265 * @self: a #HildonBanner widget
1266 * @icon_name: the name of icon to use. Can be %NULL for default icon
1268 * Sets the icon to be used in the banner.
1270 * Deprecated: This function does nothing. As of hildon 2.2, hildon
1271 * banners don't allow changing their icons.
1274 hildon_banner_set_icon (HildonBanner *self,
1275 const gchar *icon_name)
1280 * hildon_banner_set_icon_from_file:
1281 * @self: a #HildonBanner widget
1282 * @icon_file: the filename of icon to use. Can be %NULL for default icon
1284 * Sets the icon from its filename to be used in the banner.
1286 * Deprecated: This function does nothing. As of hildon 2.2, hildon
1287 * banners don't allow changing their icons.
1290 hildon_banner_set_icon_from_file (HildonBanner *self,
1291 const gchar *icon_file)