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 GDK_THREADS_ENTER ();
299 g_assert (HILDON_IS_BANNER (data));
301 widget = GTK_WIDGET (data);
302 g_object_ref (widget);
304 continue_timeout = simulate_close (widget);
306 if (! continue_timeout) {
307 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (data);
308 priv->timeout_id = 0;
309 gtk_widget_destroy (widget);
312 g_object_unref (widget);
314 GDK_THREADS_LEAVE ();
316 return continue_timeout;
320 hildon_banner_clear_timeout (HildonBanner *self)
322 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
325 if (priv->timeout_id != 0) {
326 g_source_remove (priv->timeout_id);
327 priv->timeout_id = 0;
335 hildon_banner_ensure_timeout (HildonBanner *self)
337 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
340 if (priv->timeout_id == 0 && priv->is_timed && priv->timeout > 0)
341 priv->timeout_id = g_timeout_add (priv->timeout,
342 hildon_banner_timeout, self);
346 hildon_banner_set_property (GObject *object,
352 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
358 priv->timeout = g_value_get_uint (value);
362 priv->is_timed = g_value_get_boolean (value);
365 case PROP_PARENT_WINDOW:
366 window = g_value_get_object (value);
368 g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent);
371 gtk_window_set_transient_for (GTK_WINDOW (object), (GtkWindow *) window);
372 priv->parent = (GtkWindow *) window;
375 gtk_window_set_destroy_with_parent (GTK_WINDOW (object), TRUE);
376 g_object_add_weak_pointer(G_OBJECT (window), (gpointer) &priv->parent);
382 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
388 hildon_banner_get_property (GObject *object,
393 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
399 g_value_set_uint (value, priv->timeout);
403 g_value_set_boolean (value, priv->is_timed);
406 case PROP_PARENT_WINDOW:
407 g_value_set_object (value, gtk_window_get_transient_for (GTK_WINDOW (object)));
411 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
417 hildon_banner_destroy (GtkObject *object)
419 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
423 GObject *parent_window = (GObject *) priv->parent;
425 g_assert (HILDON_IS_BANNER (object));
426 self = HILDON_BANNER (object);
428 /* Drop possible global pointer. That can hold reference to us */
429 if ((gpointer) object == (gpointer) global_timed_banner) {
430 global_timed_banner = NULL;
431 g_object_unref (object);
434 /* Remove the data from parent window for timed banners. Those hold reference */
435 if (priv->is_timed && parent_window != NULL) {
436 g_object_set_qdata (parent_window, hildon_banner_timed_quark (), NULL);
439 if (!priv->is_timed && priv->parent) {
440 hildon_gtk_window_set_progress_indicator (priv->parent, 0);
443 (void) hildon_banner_clear_timeout (self);
445 if (GTK_OBJECT_CLASS (hildon_banner_parent_class)->destroy)
446 GTK_OBJECT_CLASS (hildon_banner_parent_class)->destroy (object);
449 /* Search a previous banner instance */
451 hildon_banner_real_get_instance (GObject *window,
455 /* If we have a parent window, the previous instance is stored there */
457 return g_object_get_qdata(window, hildon_banner_timed_quark ());
460 /* System notification instance is stored into global pointer */
461 return (GObject *) global_timed_banner;
464 /* Non-timed banners are normal (non-singleton) objects */
468 /* By overriding constructor we force timed banners to be
469 singletons for each window */
471 hildon_banner_constructor (GType type,
472 guint n_construct_params,
473 GObjectConstructParam *construct_params)
475 GObject *banner, *window = NULL;
476 gboolean timed = FALSE;
479 /* Search banner type information from parameters in order
480 to locate the possible previous banner instance. */
481 for (i = 0; i < n_construct_params; i++)
483 if (strcmp(construct_params[i].pspec->name, "parent-window") == 0)
484 window = g_value_get_object (construct_params[i].value);
485 else if (strcmp(construct_params[i].pspec->name, "is-timed") == 0)
486 timed = g_value_get_boolean (construct_params[i].value);
489 /* Try to get a previous instance if such exists */
490 banner = hildon_banner_real_get_instance (window, timed);
493 /* We have to create a new banner */
494 banner = G_OBJECT_CLASS (hildon_banner_parent_class)->constructor (type, n_construct_params, construct_params);
496 /* Store the newly created singleton instance either into parent
497 window data or into global variables. */
500 g_object_set_qdata_full (G_OBJECT (window), hildon_banner_timed_quark (),
501 g_object_ref (banner), g_object_unref);
503 g_assert (global_timed_banner == NULL);
504 global_timed_banner = g_object_ref (banner);
509 /* FIXME: This is a hack! We have to manually freeze
510 notifications. This is normally done by g_object_init, but we
511 are not going to call that. g_object_newv will otherwise give
512 a critical like this:
514 GLIB CRITICAL ** GLib-GObject - g_object_notify_queue_thaw:
515 assertion `nqueue->freeze_count > 0' failed */
517 g_object_freeze_notify (banner);
520 /* We restart possible timeouts for each new timed banner request */
521 if (timed && hildon_banner_clear_timeout (HILDON_BANNER (banner)))
522 hildon_banner_ensure_timeout (HILDON_BANNER(banner));
528 hildon_banner_finalize (GObject *object)
530 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
533 g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent);
536 G_OBJECT_CLASS (hildon_banner_parent_class)->finalize (object);
540 hildon_banner_button_press_event (GtkWidget* widget,
541 GdkEventButton* event)
543 gboolean result = simulate_close (widget);
546 /* signal emission not stopped - basically behave like
547 * gtk_main_do_event() for a delete event, but just hide the
548 * banner instead of destroying it, as it is already meant to
549 * be destroyed by hildon_banner_timeout() (if it's timed) or
550 * the application (if it's not). */
551 gtk_widget_hide (widget);
557 #if defined(MAEMO_GTK)
559 hildon_banner_map (GtkWidget *widget)
561 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->map) {
562 /* Make the banner temporary _before_ mapping it, to avoid closing
563 * other temporary windows */
564 gtk_window_set_is_temporary (GTK_WINDOW (widget), TRUE);
566 GTK_WIDGET_CLASS (hildon_banner_parent_class)->map (widget);
568 /* Make the banner non-temporary _after_ mapping it, to avoid
569 * being closed by other non-temporary windows */
570 gtk_window_set_is_temporary (GTK_WINDOW (widget), FALSE);
572 gtk_window_move (GTK_WINDOW (widget), 0, HILDON_WINDOW_TITLEBAR_HEIGHT);
577 /* We start the timer for timed notifications after the window appears on screen */
579 hildon_banner_map_event (GtkWidget *widget,
582 gboolean result = FALSE;
584 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->map_event)
585 result = GTK_WIDGET_CLASS (hildon_banner_parent_class)->map_event (widget, event);
587 hildon_banner_ensure_timeout (HILDON_BANNER(widget));
593 banner_do_set_text (HildonBanner *banner,
597 HildonBannerPrivate *priv;
600 priv = HILDON_BANNER_GET_PRIVATE (banner);
603 gtk_label_set_markup (GTK_LABEL (priv->label), text);
605 gtk_label_set_text (GTK_LABEL (priv->label), text);
607 gtk_widget_set_size_request (priv->label, -1, -1);
608 gtk_widget_size_request (priv->label, &req);
610 force_to_wrap_truncated (banner);
613 /* force to wrap truncated label by setting explicit size request
614 * see N#27000 and G#329646 */
616 force_to_wrap_truncated (HildonBanner *banner)
623 PangoRectangle logical;
624 GtkRequisition requisition;
625 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (banner);
627 g_return_if_fail (priv);
629 label = GTK_LABEL (priv->label);
631 layout = gtk_label_get_layout (label);
633 pango_layout_get_extents (layout, NULL, &logical);
634 width = PANGO_PIXELS (logical.width);
636 width_max = priv->is_timed ? HILDON_BANNER_LABEL_MAX_TIMED
637 : HILDON_BANNER_LABEL_MAX_PROGRESS;
639 /* If the width of the label is going to exceed the maximum allowed
640 * width, enforce the maximum allowed width now.
642 if (width >= width_max || pango_layout_is_wrapped (layout)) {
646 /* Make the label update its layout; and update our layout pointer
647 * because the layout will be cleared and refreshed.
649 gtk_widget_set_size_request (GTK_WIDGET (label), width, height);
650 gtk_widget_size_request (GTK_WIDGET (label), &requisition);
652 layout = gtk_label_get_layout (label);
654 /* If the layout has now been wrapped and exceeds 3 lines, we truncate
655 * the rest of the label according to spec.
657 if (pango_layout_is_wrapped (layout) && pango_layout_get_line_count (layout) > 3) {
660 pango_layout_get_extents (layout, NULL, &logical);
661 lines = pango_layout_get_line_count (layout);
663 /* This calculation assumes that the same font is used
664 * throughout the banner -- this is usually the case on maemo
666 * FIXME: Pango >= 1.20 has pango_layout_set_height().
668 height = (PANGO_PIXELS (logical.height) * 3) / lines + 1;
671 /* Set the new width/height if applicable */
672 gtk_widget_set_size_request (GTK_WIDGET (label), width, height);
676 screen_size_changed (GdkScreen *screen,
680 hildon_banner_bind_style (HILDON_BANNER (banner));
681 gtk_window_reshow_with_initial_size (banner);
682 force_to_wrap_truncated (HILDON_BANNER (banner));
686 hildon_banner_realize (GtkWidget *widget)
691 guint32 portrait = 1;
692 const gchar *notification_type = "_HILDON_NOTIFICATION_TYPE_BANNER";
693 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (widget);
696 /* We let the parent to init widget->window before we need it */
697 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->realize)
698 GTK_WIDGET_CLASS (hildon_banner_parent_class)->realize (widget);
700 /* We use special hint to turn the banner into information notification. */
701 gdk_window_set_type_hint (widget->window, GDK_WINDOW_TYPE_HINT_NOTIFICATION);
702 gtk_window_set_transient_for (GTK_WINDOW (widget), (GtkWindow *) priv->parent);
704 gdkwin = widget->window;
706 /* Set the _HILDON_NOTIFICATION_TYPE property so Matchbox places the window correctly */
707 atom = gdk_atom_intern ("_HILDON_NOTIFICATION_TYPE", FALSE);
708 gdk_property_change (gdkwin, atom, gdk_x11_xatom_to_atom (XA_STRING), 8, GDK_PROP_MODE_REPLACE,
709 (gpointer) notification_type, strlen (notification_type));
711 /* HildonBanner supports portrait mode */
712 atom = gdk_atom_intern ("_HILDON_PORTRAIT_MODE_SUPPORT", FALSE);
713 gdk_property_change (gdkwin, atom, gdk_x11_xatom_to_atom (XA_CARDINAL), 32,
714 GDK_PROP_MODE_REPLACE, (gpointer) &portrait, 1);
716 /* Manage override flag */
717 if ((priv->require_override_dnd)&&(!priv->overrides_dnd)) {
718 hildon_banner_set_override_flag (HILDON_BANNER (widget));
719 priv->overrides_dnd = TRUE;
722 screen = gtk_widget_get_screen (widget);
723 g_signal_connect (screen, "size-changed", G_CALLBACK (screen_size_changed), widget);
727 hildon_banner_unrealize (GtkWidget *widget)
729 GdkScreen *screen = gtk_widget_get_screen (widget);
730 g_signal_handlers_disconnect_by_func (screen, G_CALLBACK (screen_size_changed), widget);
732 GTK_WIDGET_CLASS (hildon_banner_parent_class)->unrealize (widget);
736 hildon_banner_class_init (HildonBannerClass *klass)
738 GObjectClass *object_class;
739 GtkWidgetClass *widget_class;
741 object_class = G_OBJECT_CLASS (klass);
742 widget_class = GTK_WIDGET_CLASS (klass);
744 /* Append private structure to class. This is more elegant than
745 on g_new based approach */
746 g_type_class_add_private (klass, sizeof (HildonBannerPrivate));
748 /* Override virtual methods */
749 object_class->constructor = hildon_banner_constructor;
750 object_class->finalize = hildon_banner_finalize;
751 object_class->set_property = hildon_banner_set_property;
752 object_class->get_property = hildon_banner_get_property;
753 GTK_OBJECT_CLASS (klass)->destroy = hildon_banner_destroy;
754 widget_class->size_request = hildon_banner_size_request;
755 widget_class->map_event = hildon_banner_map_event;
756 widget_class->realize = hildon_banner_realize;
757 widget_class->unrealize = hildon_banner_unrealize;
758 widget_class->button_press_event = hildon_banner_button_press_event;
759 #if defined(MAEMO_GTK)
760 widget_class->map = hildon_banner_map;
763 /* Install properties.
764 We need construct properties for singleton purposes */
767 * HildonBanner:parent-window:
769 * The window for which the banner will be singleton.
772 g_object_class_install_property (object_class, PROP_PARENT_WINDOW,
773 g_param_spec_object ("parent-window",
775 "The window for which the banner will be singleton",
776 GTK_TYPE_WINDOW, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
779 * HildonBanner:is-timed:
781 * Whether the banner is timed and goes away automatically.
784 g_object_class_install_property (object_class, PROP_IS_TIMED,
785 g_param_spec_boolean ("is-timed",
787 "Whether or not the notification goes away automatically "
788 "after the specified time has passed",
789 FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
792 * HildonBanner:timeout:
794 * The time before destroying the banner. This needs
795 * to be adjusted before the banner is mapped to the screen.
798 g_object_class_install_property (object_class, PROP_TIMEOUT,
799 g_param_spec_uint ("timeout",
801 "The time before making the banner banner go away",
804 HILDON_BANNER_DEFAULT_TIMEOUT,
805 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
809 hildon_banner_init (HildonBanner *self)
811 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
815 priv->overrides_dnd = FALSE;
816 priv->require_override_dnd = FALSE;
817 priv->name_suffix = NULL;
819 /* Initialize the common layout inside banner */
820 priv->alignment = gtk_alignment_new (0.5, 0.5, 0, 0);
821 priv->layout = gtk_hbox_new (FALSE, HILDON_MARGIN_DEFAULT);
823 priv->label = g_object_new (GTK_TYPE_LABEL, NULL);
824 gtk_label_set_line_wrap (GTK_LABEL (priv->label), TRUE);
825 gtk_label_set_line_wrap_mode (GTK_LABEL (priv->label), PANGO_WRAP_WORD_CHAR);
826 gtk_label_set_justify (GTK_LABEL (priv->label), GTK_JUSTIFY_CENTER);
828 gtk_container_set_border_width (GTK_CONTAINER (priv->layout), HILDON_MARGIN_DEFAULT);
829 gtk_container_add (GTK_CONTAINER (self), priv->alignment);
830 gtk_container_add (GTK_CONTAINER (priv->alignment), priv->layout);
831 gtk_box_pack_start (GTK_BOX (priv->layout), priv->label, FALSE, FALSE, 0);
833 gtk_window_set_accept_focus (GTK_WINDOW (self), FALSE);
835 gtk_widget_add_events (GTK_WIDGET (self), GDK_BUTTON_PRESS_MASK);
838 /* Makes sure that icon/progress item contains the desired type
839 of item. If possible, tries to avoid creating a new widget but
840 reuses the existing one */
842 hildon_banner_ensure_child (HildonBanner *self,
843 GtkWidget *user_widget,
846 const gchar *first_property,
851 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
855 widget = priv->main_item;
856 va_start (args, first_property);
858 /* Reuse existing widget if possible */
859 if (! user_widget && G_TYPE_CHECK_INSTANCE_TYPE (widget, type))
861 g_object_set_valist (G_OBJECT (widget), first_property, args);
865 /* We have to abandon old content widget */
867 gtk_container_remove (GTK_CONTAINER (priv->layout), widget);
869 /* Use user provided widget or create a new one */
870 priv->main_item = widget = user_widget ?
871 user_widget : GTK_WIDGET (g_object_new_valist(type, first_property, args));
872 gtk_box_pack_start (GTK_BOX (priv->layout), widget, FALSE, FALSE, 0);
875 /* We make sure that the widget exists in desired position. Different
876 banners place this child widget to different places */
877 gtk_box_reorder_child (GTK_BOX (priv->layout), widget, pos);
881 /* Creates a new banner instance or uses an existing one */
883 hildon_banner_get_instance_for_widget (GtkWidget *widget,
888 window = widget ? gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW) : NULL;
889 return g_object_new (HILDON_TYPE_BANNER, "parent-window", window, "is-timed", timed, NULL);
893 * hildon_banner_show_information:
894 * @widget: the #GtkWidget that is the owner of the banner
895 * @icon_name: since Hildon 2.2 this parameter is not used anymore and
896 * any value that you pass will be ignored
897 * @text: Text to display
899 * This function creates and displays an information banner that is
900 * automatically destroyed after a certain time period (see
901 * hildon_banner_set_timeout()). For each window in your application
902 * there can only be one timed banner, so if you spawn a new banner
903 * before the earlier one has timed out, the previous one will be
906 * Returns: The newly created banner
910 hildon_banner_show_information (GtkWidget *widget,
911 const gchar *icon_name,
914 return hildon_banner_real_show_information (widget, text, FALSE);
918 * hildon_banner_show_information_override_dnd:
919 * @widget: the #GtkWidget that is the owner of the banner
920 * @text: Text to display
922 * Equivalent to hildon_banner_show_information(), but overriding the
923 * "do not disturb" flag.
925 * Returns: The newly created banner
931 hildon_banner_show_information_override_dnd (GtkWidget *widget,
934 return hildon_banner_real_show_information (widget, text, TRUE);
938 hildon_banner_set_override_flag (HildonBanner *banner)
942 gdk_property_change (GTK_WIDGET (banner)->window,
943 gdk_atom_intern_static_string ("_HILDON_DO_NOT_DISTURB_OVERRIDE"),
944 gdk_x11_xatom_to_atom (XA_INTEGER),
946 GDK_PROP_MODE_REPLACE,
947 (const guchar*) &state,
952 reshow_banner (HildonBanner *banner)
954 if (GTK_WIDGET_VISIBLE (banner)) {
955 gint width = gdk_screen_get_width (gtk_widget_get_screen (GTK_WIDGET (banner)));
956 gtk_window_resize (GTK_WINDOW (banner), width, 1);
958 force_to_wrap_truncated (banner);
959 gtk_widget_show_all (GTK_WIDGET (banner));
963 hildon_banner_real_show_information (GtkWidget *widget,
965 gboolean override_dnd)
967 HildonBanner *banner;
968 HildonBannerPrivate *priv = NULL;
970 g_return_val_if_fail (text != NULL, NULL);
973 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
974 priv = HILDON_BANNER_GET_PRIVATE (banner);
976 priv->name_suffix = "information";
977 banner_do_set_text (banner, text, FALSE);
978 hildon_banner_bind_style (banner);
981 /* so on the realize it will set the property */
982 priv->require_override_dnd = TRUE;
985 /* Show the banner, since caller cannot do that */
986 reshow_banner (banner);
988 return GTK_WIDGET (banner);
992 * hildon_banner_show_informationf:
993 * @widget: the #GtkWidget that is the owner of the banner
994 * @icon_name: since Hildon 2.2 this parameter is not used anymore and
995 * any value that you pass will be ignored
996 * @format: a printf-like format string
997 * @Varargs: arguments for the format string
999 * A helper function for hildon_banner_show_information() with
1000 * string formatting.
1002 * Returns: the newly created banner
1005 hildon_banner_show_informationf (GtkWidget *widget,
1006 const gchar *icon_name,
1007 const gchar *format,
1010 g_return_val_if_fail (format != NULL, NULL);
1016 va_start (args, format);
1017 message = g_strdup_vprintf (format, args);
1020 banner = hildon_banner_show_information (widget, icon_name, message);
1028 * hildon_banner_show_information_with_markup:
1029 * @widget: the #GtkWidget that wants to display banner
1030 * @icon_name: since Hildon 2.2 this parameter is not used anymore and
1031 * any value that you pass will be ignored
1032 * @markup: a markup string to display (see <link linkend="PangoMarkupFormat">Pango markup format</link>)
1034 * This function creates and displays an information banner that is
1035 * automatically destroyed after certain time period (see
1036 * hildon_banner_set_timeout()). For each window in your application
1037 * there can only be one timed banner, so if you spawn a new banner
1038 * before the earlier one has timed out, the previous one will be
1041 * Returns: the newly created banner
1045 hildon_banner_show_information_with_markup (GtkWidget *widget,
1046 const gchar *icon_name,
1047 const gchar *markup)
1049 HildonBanner *banner;
1050 HildonBannerPrivate *priv;
1052 g_return_val_if_fail (icon_name == NULL || icon_name[0] != 0, NULL);
1053 g_return_val_if_fail (markup != NULL, NULL);
1055 /* Prepare banner */
1056 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
1057 priv = HILDON_BANNER_GET_PRIVATE (banner);
1059 priv->name_suffix = "information";
1060 banner_do_set_text (banner, markup, TRUE);
1061 hildon_banner_bind_style (banner);
1063 /* Show the banner, since caller cannot do that */
1064 reshow_banner (banner);
1066 return (GtkWidget *) banner;
1070 * hildon_banner_show_animation:
1071 * @widget: the #GtkWidget that wants to display banner
1072 * @animation_name: since Hildon 2.2 this parameter is not used
1073 * anymore and any value that you pass will be
1075 * @text: the text to display.
1077 * Shows an animated progress notification. It's recommended not to try
1078 * to show more than one progress notification at a time, since
1079 * they will appear on top of each other. You can use progress
1080 * notifications with timed banners. In this case the banners are
1081 * located so that you can somehow see both.
1083 * Unlike information banners (created with
1084 * hildon_banner_show_information()), animation banners are not
1085 * destroyed automatically using a timeout. You have to destroy them
1088 * Please note also that these banners are destroyed automatically if the
1089 * window they are attached to is closed. The pointer that you receive
1090 * with this function does not contain additional references, so it
1091 * can become invalid without warning (this is true for all toplevel
1092 * windows in gtk). To make sure that the banner does not disappear
1093 * automatically, you can separately ref the return value (this
1094 * doesn't prevent the banner from disappearing, just the object from
1095 * being finalized). In this case you have to call
1096 * gtk_widget_destroy() followed by g_object_unref().
1098 * Returns: a #HildonBanner widget. You must call gtk_widget_destroy()
1099 * once you are done with the banner.
1101 * Deprecated: Hildon 2.2: use
1102 * hildon_gtk_window_set_progress_indicator() instead.
1105 hildon_banner_show_animation (GtkWidget *widget,
1106 const gchar *animation_name,
1109 HildonBanner *banner;
1110 GtkWidget *image_widget;
1111 HildonBannerPrivate *priv;
1113 g_return_val_if_fail (text != NULL, NULL);
1115 image_widget = hildon_private_create_animation (
1116 HILDON_BANNER_ANIMATION_FRAMERATE,
1117 HILDON_BANNER_ANIMATION_TMPL,
1118 HILDON_BANNER_ANIMATION_NFRAMES);
1120 /* Prepare banner */
1121 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
1122 hildon_banner_ensure_child (banner, image_widget, 0,
1123 GTK_TYPE_IMAGE, "yalign", 0.0, NULL);
1125 priv = HILDON_BANNER_GET_PRIVATE (banner);
1126 priv->name_suffix = "animation";
1127 banner_do_set_text (banner, text, FALSE);
1128 hildon_banner_bind_style (banner);
1131 reshow_banner (banner);
1133 return (GtkWidget *) banner;
1137 * hildon_banner_show_progress:
1138 * @widget: the #GtkWidget that wants to display banner
1139 * @bar: since Hildon 2.2 this parameter is not used anymore and
1140 * any value that you pass will be ignored
1141 * @text: text to display.
1143 * Shows progress notification. See hildon_banner_show_animation()
1144 * for more information.
1146 * Returns: a #HildonBanner widget. You must call #gtk_widget_destroy
1147 * once you are done with the banner.
1149 * Deprecated: Hildon 2.2: use hildon_gtk_window_set_progress_indicator() instead.
1152 hildon_banner_show_progress (GtkWidget *widget,
1153 GtkProgressBar *bar,
1156 HildonBanner *banner;
1157 HildonBannerPrivate *priv;
1159 g_return_val_if_fail (text != NULL, NULL);
1161 /* Prepare banner */
1162 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
1163 priv = HILDON_BANNER_GET_PRIVATE (banner);
1166 priv->name_suffix = "progress";
1167 banner_do_set_text (banner, text, FALSE);
1168 hildon_banner_bind_style (banner);
1171 hildon_gtk_window_set_progress_indicator (priv->parent, 1);
1173 /* Show the banner */
1174 reshow_banner (banner);
1176 return GTK_WIDGET (banner);
1180 * hildon_banner_set_text:
1181 * @self: a #HildonBanner widget
1182 * @text: a new text to display in banner
1184 * Sets the text that is displayed in the banner.
1188 hildon_banner_set_text (HildonBanner *self,
1191 g_return_if_fail (HILDON_IS_BANNER (self));
1193 banner_do_set_text (self, text, FALSE);
1195 if (GTK_WIDGET_VISIBLE (self))
1196 reshow_banner (self);
1200 * hildon_banner_set_markup:
1201 * @self: a #HildonBanner widget
1202 * @markup: a new text with Pango markup to display in the banner
1204 * Sets the text with markup that is displayed in the banner.
1208 hildon_banner_set_markup (HildonBanner *self,
1209 const gchar *markup)
1211 g_return_if_fail (HILDON_IS_BANNER (self));
1213 banner_do_set_text (self, markup, TRUE);
1215 if (GTK_WIDGET_VISIBLE (self))
1216 reshow_banner (self);
1220 * hildon_banner_set_fraction:
1221 * @self: a #HildonBanner widget
1222 * @fraction: #gdouble
1224 * The fraction is the completion of progressbar,
1225 * the scale is from 0.0 to 1.0.
1226 * Sets the amount of fraction the progressbar has.
1228 * Note that this method only has effect if @self was created with
1229 * hildon_banner_show_progress()
1231 * Deprecated: This function does nothing. As of Hildon 2.2, hildon
1232 * banners don't have progress bars.
1235 hildon_banner_set_fraction (HildonBanner *self,
1241 * hildon_banner_set_timeout:
1242 * @self: a #HildonBanner widget
1243 * @timeout: timeout to set in miliseconds.
1245 * Sets the timeout on the banner. After the given amount of miliseconds
1246 * has elapsed the banner will be destroyed. Setting this only makes
1247 * sense on banners that are timed and that have not been yet displayed
1250 * Note that this method only has effect if @self is an information
1251 * banner (created using hildon_banner_show_information() and
1255 hildon_banner_set_timeout (HildonBanner *self,
1258 HildonBannerPrivate *priv;
1260 g_return_if_fail (HILDON_IS_BANNER (self));
1261 priv = HILDON_BANNER_GET_PRIVATE (self);
1264 priv->timeout = timeout;
1268 * hildon_banner_set_icon:
1269 * @self: a #HildonBanner widget
1270 * @icon_name: the name of icon to use. Can be %NULL for default icon
1272 * Sets the icon to be used in the banner.
1274 * Deprecated: This function does nothing. As of hildon 2.2, hildon
1275 * banners don't allow changing their icons.
1278 hildon_banner_set_icon (HildonBanner *self,
1279 const gchar *icon_name)
1284 * hildon_banner_set_icon_from_file:
1285 * @self: a #HildonBanner widget
1286 * @icon_file: the filename of icon to use. Can be %NULL for default icon
1288 * Sets the icon from its filename to be used in the banner.
1290 * Deprecated: This function does nothing. As of hildon 2.2, hildon
1291 * banners don't allow changing their icons.
1294 hildon_banner_set_icon_from_file (HildonBanner *self,
1295 const gchar *icon_file)