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"
91 /* position relative to the screen */
93 #define HILDON_BANNER_WINDOW_X 0
95 #define HILDON_BANNER_WINDOW_Y HILDON_WINDOW_TITLEBAR_HEIGHT
99 #define HILDON_BANNER_LABEL_MAX_TIMED \
100 (gdk_screen_width() - ((HILDON_MARGIN_TRIPLE) * 2))
102 #define HILDON_BANNER_LABEL_MAX_PROGRESS 375 /*265*/
104 /* default timeout */
106 #define HILDON_BANNER_DEFAULT_TIMEOUT 3000
110 #define HILDON_BANNER_DEFAULT_PROGRESS_ANIMATION "indicator_update"
112 /* animation related stuff */
114 #define HILDON_BANNER_ANIMATION_FRAMERATE ((float)1000/150)
116 #define HILDON_BANNER_ANIMATION_TMPL "indicator_update%d"
118 #define HILDON_BANNER_ANIMATION_NFRAMES 8
128 static GtkWidget* global_timed_banner = NULL;
131 hildon_banner_timed_quark (void);
134 hildon_banner_bind_style (HildonBanner *self);
137 hildon_banner_timeout (gpointer data);
140 hildon_banner_clear_timeout (HildonBanner *self);
143 hildon_banner_ensure_timeout (HildonBanner *self);
146 hildon_banner_set_property (GObject *object,
152 hildon_banner_get_property (GObject *object,
158 hildon_banner_destroy (GtkObject *object);
161 hildon_banner_real_get_instance (GObject *window,
165 hildon_banner_constructor (GType type,
166 guint n_construct_params,
167 GObjectConstructParam *construct_params);
170 hildon_banner_finalize (GObject *object);
173 hildon_banner_button_press_event (GtkWidget* widget,
174 GdkEventButton* event);
177 hildon_banner_map_event (GtkWidget *widget,
180 hildon_banner_reset_wrap_state (HildonBanner *banner);
183 force_to_wrap_truncated (HildonBanner *banner);
186 hildon_banner_check_position (GtkWidget *widget);
189 hildon_banner_realize (GtkWidget *widget);
192 hildon_banner_class_init (HildonBannerClass *klass);
195 hildon_banner_init (HildonBanner *self);
198 hildon_banner_ensure_child (HildonBanner *self,
199 GtkWidget *user_widget,
202 const gchar *first_property,
206 hildon_banner_get_instance_for_widget (GtkWidget *widget,
210 hildon_banner_set_override_flag (HildonBanner *banner);
213 hildon_banner_real_show_information (GtkWidget *widget,
215 gboolean override_dnd);
217 G_DEFINE_TYPE (HildonBanner, hildon_banner, GTK_TYPE_WINDOW)
219 typedef struct _HildonBannerPrivate HildonBannerPrivate;
221 #define HILDON_BANNER_GET_PRIVATE(obj) \
222 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
223 HILDON_TYPE_BANNER, HildonBannerPrivate));
225 struct _HildonBannerPrivate
227 GtkWidget *main_item;
228 GtkWidget *alignment;
232 const gchar *name_suffix;
236 guint has_been_wrapped : 1;
237 guint has_been_truncated : 1;
238 guint require_override_dnd : 1;
239 guint overrides_dnd : 1;
243 hildon_banner_timed_quark (void)
245 static GQuark quark = 0;
247 if (G_UNLIKELY(quark == 0))
248 quark = g_quark_from_static_string ("hildon-banner-timed");
253 /* Set the widget and label name to make the correct rc-style attached into them */
255 hildon_banner_bind_style (HildonBanner *self)
257 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
258 GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (self));
259 gboolean portrait = gdk_screen_get_width (screen) < gdk_screen_get_height (screen);
260 const gchar *portrait_suffix = portrait ? "-portrait" : NULL;
265 name = g_strconcat ("HildonBannerLabel-", priv->name_suffix, NULL);
266 gtk_widget_set_name (priv->label, name);
269 name = g_strconcat ("HildonBanner-", priv->name_suffix, portrait_suffix, NULL);
270 gtk_widget_set_name (GTK_WIDGET (self), name);
274 /* In timeout function we automatically destroy timed banners */
276 simulate_close (GtkWidget* widget)
278 gboolean result = FALSE;
280 /* If the banner is currently visible (it normally should),
281 we simulate clicking the close button of the window.
282 This allows applications to reuse the banner by prevent
284 if (GTK_WIDGET_DRAWABLE (widget))
286 GdkEvent *event = gdk_event_new (GDK_DELETE);
287 event->any.window = g_object_ref (widget->window);
288 event->any.send_event = FALSE;
289 result = gtk_widget_event (widget, event);
290 gdk_event_free (event);
297 hildon_banner_timeout (gpointer data)
300 gboolean continue_timeout = FALSE;
302 GDK_THREADS_ENTER ();
304 g_assert (HILDON_IS_BANNER (data));
306 widget = GTK_WIDGET (data);
307 g_object_ref (widget);
309 continue_timeout = simulate_close (widget);
311 if (! continue_timeout) {
312 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (data);
313 priv->timeout_id = 0;
314 gtk_widget_destroy (widget);
317 g_object_unref (widget);
319 GDK_THREADS_LEAVE ();
321 return continue_timeout;
325 hildon_banner_clear_timeout (HildonBanner *self)
327 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
330 if (priv->timeout_id != 0) {
331 g_source_remove (priv->timeout_id);
332 priv->timeout_id = 0;
340 hildon_banner_ensure_timeout (HildonBanner *self)
342 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
345 if (priv->timeout_id == 0 && priv->is_timed && priv->timeout > 0)
346 priv->timeout_id = g_timeout_add (priv->timeout,
347 hildon_banner_timeout, self);
351 hildon_banner_set_property (GObject *object,
357 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
363 priv->timeout = g_value_get_uint (value);
367 priv->is_timed = g_value_get_boolean (value);
370 case PROP_PARENT_WINDOW:
371 window = g_value_get_object (value);
373 g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent);
376 gtk_window_set_transient_for (GTK_WINDOW (object), (GtkWindow *) window);
377 priv->parent = (GtkWindow *) window;
380 gtk_window_set_destroy_with_parent (GTK_WINDOW (object), TRUE);
381 g_object_add_weak_pointer(G_OBJECT (window), (gpointer) &priv->parent);
387 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
393 hildon_banner_get_property (GObject *object,
398 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
404 g_value_set_uint (value, priv->timeout);
408 g_value_set_boolean (value, priv->is_timed);
411 case PROP_PARENT_WINDOW:
412 g_value_set_object (value, gtk_window_get_transient_for (GTK_WINDOW (object)));
416 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
422 hildon_banner_destroy (GtkObject *object)
424 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
428 GObject *parent_window = (GObject *) priv->parent;
430 g_assert (HILDON_IS_BANNER (object));
431 self = HILDON_BANNER (object);
433 /* Drop possible global pointer. That can hold reference to us */
434 if ((gpointer) object == (gpointer) global_timed_banner) {
435 global_timed_banner = NULL;
436 g_object_unref (object);
439 /* Remove the data from parent window for timed banners. Those hold reference */
440 if (priv->is_timed && parent_window != NULL) {
441 g_object_set_qdata (parent_window, hildon_banner_timed_quark (), NULL);
444 if (!priv->is_timed && priv->parent) {
445 hildon_gtk_window_set_progress_indicator (priv->parent, 0);
448 (void) hildon_banner_clear_timeout (self);
450 if (GTK_OBJECT_CLASS (hildon_banner_parent_class)->destroy)
451 GTK_OBJECT_CLASS (hildon_banner_parent_class)->destroy (object);
454 /* Search a previous banner instance */
456 hildon_banner_real_get_instance (GObject *window,
460 /* If we have a parent window, the previous instance is stored there */
462 return g_object_get_qdata(window, hildon_banner_timed_quark ());
465 /* System notification instance is stored into global pointer */
466 return (GObject *) global_timed_banner;
469 /* Non-timed banners are normal (non-singleton) objects */
473 /* By overriding constructor we force timed banners to be
474 singletons for each window */
476 hildon_banner_constructor (GType type,
477 guint n_construct_params,
478 GObjectConstructParam *construct_params)
480 GObject *banner, *window = NULL;
481 gboolean timed = FALSE;
484 /* Search banner type information from parameters in order
485 to locate the possible previous banner instance. */
486 for (i = 0; i < n_construct_params; i++)
488 if (strcmp(construct_params[i].pspec->name, "parent-window") == 0)
489 window = g_value_get_object (construct_params[i].value);
490 else if (strcmp(construct_params[i].pspec->name, "is-timed") == 0)
491 timed = g_value_get_boolean (construct_params[i].value);
494 /* Try to get a previous instance if such exists */
495 banner = hildon_banner_real_get_instance (window, timed);
498 /* We have to create a new banner */
499 banner = G_OBJECT_CLASS (hildon_banner_parent_class)->constructor (type, n_construct_params, construct_params);
501 /* Store the newly created singleton instance either into parent
502 window data or into global variables. */
505 g_object_set_qdata_full (G_OBJECT (window), hildon_banner_timed_quark (),
506 g_object_ref (banner), g_object_unref);
508 g_assert (global_timed_banner == NULL);
509 global_timed_banner = g_object_ref (banner);
514 /* FIXME: This is a hack! We have to manually freeze
515 notifications. This is normally done by g_object_init, but we
516 are not going to call that. g_object_newv will otherwise give
517 a critical like this:
519 GLIB CRITICAL ** GLib-GObject - g_object_notify_queue_thaw:
520 assertion `nqueue->freeze_count > 0' failed */
522 g_object_freeze_notify (banner);
523 hildon_banner_reset_wrap_state (HILDON_BANNER (banner));
526 /* We restart possible timeouts for each new timed banner request */
527 if (timed && hildon_banner_clear_timeout (HILDON_BANNER (banner)))
528 hildon_banner_ensure_timeout (HILDON_BANNER(banner));
534 hildon_banner_finalize (GObject *object)
536 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
539 g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent);
542 G_OBJECT_CLASS (hildon_banner_parent_class)->finalize (object);
546 hildon_banner_button_press_event (GtkWidget* widget,
547 GdkEventButton* event)
549 gboolean result = simulate_close (widget);
552 /* signal emission not stopped - basically behave like
553 * gtk_main_do_event() for a delete event, but just hide the
554 * banner instead of destroying it, as it is already meant to
555 * be destroyed by hildon_banner_timeout() (if it's timed) or
556 * the application (if it's not). */
557 gtk_widget_hide (widget);
563 #if defined(MAEMO_GTK)
565 hildon_banner_map (GtkWidget *widget)
567 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->map) {
568 /* Make the banner temporary _before_ mapping it, to avoid closing
569 * other temporary windows */
570 gtk_window_set_is_temporary (GTK_WINDOW (widget), TRUE);
572 GTK_WIDGET_CLASS (hildon_banner_parent_class)->map (widget);
574 /* Make the banner non-temporary _after_ mapping it, to avoid
575 * being closed by other non-temporary windows */
576 gtk_window_set_is_temporary (GTK_WINDOW (widget), FALSE);
578 hildon_banner_check_position (widget);
583 /* We start the timer for timed notifications after the window appears on screen */
585 hildon_banner_map_event (GtkWidget *widget,
588 gboolean result = FALSE;
590 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->map_event)
591 result = GTK_WIDGET_CLASS (hildon_banner_parent_class)->map_event (widget, event);
593 hildon_banner_ensure_timeout (HILDON_BANNER(widget));
599 hildon_banner_reset_wrap_state (HildonBanner *banner)
602 HildonBannerPrivate *priv;
604 priv = HILDON_BANNER_GET_PRIVATE (banner);
607 layout = gtk_label_get_layout (GTK_LABEL (priv->label));
609 pango_layout_set_width (layout, -1);
610 priv->has_been_wrapped = FALSE;
611 priv->has_been_truncated = FALSE;
613 gtk_widget_set_size_request (priv->label, -1, -1);
614 gtk_widget_set_size_request (GTK_WIDGET (banner), -1, -1);
617 /* force to wrap truncated label by setting explicit size request
618 * see N#27000 and G#329646 */
620 force_to_wrap_truncated (HildonBanner *banner)
624 int width_text, width_max;
627 PangoRectangle logical;
628 GtkRequisition requisition;
629 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (banner);
631 g_return_if_fail (priv);
633 label = GTK_LABEL (priv->label);
635 layout = gtk_label_get_layout (label);
637 pango_layout_get_extents (layout, NULL, &logical);
638 width_text = PANGO_PIXELS (logical.width);
640 width_max = priv->is_timed ? HILDON_BANNER_LABEL_MAX_TIMED
641 : HILDON_BANNER_LABEL_MAX_PROGRESS;
643 /* If the width of the label is going to exceed the maximum allowed
644 * width, enforce the maximum allowed width now.
646 if (priv->has_been_wrapped
647 || width_text >= width_max
648 || pango_layout_is_wrapped (layout)) {
649 /* Force wrapping by setting the maximum size */
652 priv->has_been_wrapped = TRUE;
655 /* Make the label update its layout; and update our layout pointer
656 * because the layout will be cleared and refreshed.
658 gtk_widget_set_size_request (GTK_WIDGET (label), width, height);
659 gtk_widget_size_request (GTK_WIDGET (label), &requisition);
661 layout = gtk_label_get_layout (label);
663 /* If the layout has now been wrapped and exceeds 3 lines, we truncate
664 * the rest of the label according to spec.
666 if (priv->has_been_truncated
667 || (pango_layout_is_wrapped (layout)
668 && pango_layout_get_line_count (layout) > 3)) {
671 pango_layout_get_extents (layout, NULL, &logical);
672 lines = pango_layout_get_line_count (layout);
674 /* This calculation assumes that the same font is used
675 * throughout the banner -- this is usually the case on maemo
677 * FIXME: Pango >= 1.20 has pango_layout_set_height().
679 height = (PANGO_PIXELS (logical.height) * 3) / lines + 1;
680 priv->has_been_truncated = TRUE;
683 /* Set the new width/height if applicable */
684 gtk_widget_set_size_request (GTK_WIDGET (label), width, height);
689 hildon_banner_check_position (GtkWidget *widget)
694 gtk_widget_set_size_request (widget, gdk_screen_width (), -1);
696 force_to_wrap_truncated (HILDON_BANNER(widget)); /* see N#27000 and G#329646 */
698 gtk_widget_size_request (widget, &req);
705 x = HILDON_BANNER_WINDOW_X;
707 y = HILDON_BANNER_WINDOW_Y;
709 gtk_window_move (GTK_WINDOW (widget), x, y);
713 screen_size_changed (GdkScreen *screen,
717 hildon_banner_bind_style (HILDON_BANNER (banner));
718 gtk_window_reshow_with_initial_size (banner);
722 hildon_banner_realize (GtkWidget *widget)
727 guint32 portrait = 1;
728 const gchar *notification_type = "_HILDON_NOTIFICATION_TYPE_BANNER";
729 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (widget);
732 /* We let the parent to init widget->window before we need it */
733 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->realize)
734 GTK_WIDGET_CLASS (hildon_banner_parent_class)->realize (widget);
736 /* We use special hint to turn the banner into information notification. */
737 gdk_window_set_type_hint (widget->window, GDK_WINDOW_TYPE_HINT_NOTIFICATION);
738 gtk_window_set_transient_for (GTK_WINDOW (widget), (GtkWindow *) priv->parent);
740 hildon_banner_check_position (widget);
742 gdkwin = widget->window;
744 /* Set the _HILDON_NOTIFICATION_TYPE property so Matchbox places the window correctly */
745 atom = gdk_atom_intern ("_HILDON_NOTIFICATION_TYPE", FALSE);
746 gdk_property_change (gdkwin, atom, gdk_x11_xatom_to_atom (XA_STRING), 8, GDK_PROP_MODE_REPLACE,
747 (gpointer) notification_type, strlen (notification_type));
749 /* HildonBanner supports portrait mode */
750 atom = gdk_atom_intern ("_HILDON_PORTRAIT_MODE_SUPPORT", FALSE);
751 gdk_property_change (gdkwin, atom, gdk_x11_xatom_to_atom (XA_CARDINAL), 32,
752 GDK_PROP_MODE_REPLACE, (gpointer) &portrait, 1);
754 /* Manage override flag */
755 if ((priv->require_override_dnd)&&(!priv->overrides_dnd)) {
756 hildon_banner_set_override_flag (HILDON_BANNER (widget));
757 priv->overrides_dnd = TRUE;
760 screen = gtk_widget_get_screen (widget);
761 g_signal_connect (screen, "size-changed", G_CALLBACK (screen_size_changed), widget);
765 hildon_banner_unrealize (GtkWidget *widget)
767 GdkScreen *screen = gtk_widget_get_screen (widget);
768 g_signal_handlers_disconnect_by_func (screen, G_CALLBACK (screen_size_changed), widget);
770 GTK_WIDGET_CLASS (hildon_banner_parent_class)->unrealize (widget);
774 hildon_banner_class_init (HildonBannerClass *klass)
776 GObjectClass *object_class;
777 GtkWidgetClass *widget_class;
779 object_class = G_OBJECT_CLASS (klass);
780 widget_class = GTK_WIDGET_CLASS (klass);
782 /* Append private structure to class. This is more elegant than
783 on g_new based approach */
784 g_type_class_add_private (klass, sizeof (HildonBannerPrivate));
786 /* Override virtual methods */
787 object_class->constructor = hildon_banner_constructor;
788 object_class->finalize = hildon_banner_finalize;
789 object_class->set_property = hildon_banner_set_property;
790 object_class->get_property = hildon_banner_get_property;
791 GTK_OBJECT_CLASS (klass)->destroy = hildon_banner_destroy;
792 widget_class->map_event = hildon_banner_map_event;
793 widget_class->realize = hildon_banner_realize;
794 widget_class->unrealize = hildon_banner_unrealize;
795 widget_class->button_press_event = hildon_banner_button_press_event;
796 #if defined(MAEMO_GTK)
797 widget_class->map = hildon_banner_map;
800 /* Install properties.
801 We need construct properties for singleton purposes */
804 * HildonBanner:parent-window:
806 * The window for which the banner will be singleton.
809 g_object_class_install_property (object_class, PROP_PARENT_WINDOW,
810 g_param_spec_object ("parent-window",
812 "The window for which the banner will be singleton",
813 GTK_TYPE_WINDOW, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
816 * HildonBanner:is-timed:
818 * Whether the banner is timed and goes away automatically.
821 g_object_class_install_property (object_class, PROP_IS_TIMED,
822 g_param_spec_boolean ("is-timed",
824 "Whether or not the notification goes away automatically "
825 "after the specified time has passed",
826 FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
829 * HildonBanner:timeout:
831 * The time before destroying the banner. This needs
832 * to be adjusted before the banner is mapped to the screen.
835 g_object_class_install_property (object_class, PROP_TIMEOUT,
836 g_param_spec_uint ("timeout",
838 "The time before making the banner banner go away",
841 HILDON_BANNER_DEFAULT_TIMEOUT,
842 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
846 hildon_banner_init (HildonBanner *self)
848 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
852 priv->overrides_dnd = FALSE;
853 priv->require_override_dnd = FALSE;
854 priv->name_suffix = NULL;
856 /* Initialize the common layout inside banner */
857 priv->alignment = gtk_alignment_new (0.5, 0.5, 0, 0);
858 priv->layout = gtk_hbox_new (FALSE, HILDON_MARGIN_DEFAULT);
860 priv->label = g_object_new (GTK_TYPE_LABEL, NULL);
861 gtk_label_set_line_wrap (GTK_LABEL (priv->label), TRUE);
862 gtk_label_set_line_wrap_mode (GTK_LABEL (priv->label), PANGO_WRAP_WORD_CHAR);
864 gtk_container_set_border_width (GTK_CONTAINER (priv->layout), HILDON_MARGIN_DEFAULT);
865 gtk_container_add (GTK_CONTAINER (self), priv->alignment);
866 gtk_container_add (GTK_CONTAINER (priv->alignment), priv->layout);
867 gtk_box_pack_start (GTK_BOX (priv->layout), priv->label, FALSE, FALSE, 0);
869 gtk_window_set_accept_focus (GTK_WINDOW (self), FALSE);
871 hildon_banner_reset_wrap_state (self);
873 gtk_widget_add_events (GTK_WIDGET (self), GDK_BUTTON_PRESS_MASK);
876 /* Makes sure that icon/progress item contains the desired type
877 of item. If possible, tries to avoid creating a new widget but
878 reuses the existing one */
880 hildon_banner_ensure_child (HildonBanner *self,
881 GtkWidget *user_widget,
884 const gchar *first_property,
889 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
893 widget = priv->main_item;
894 va_start (args, first_property);
896 /* Reuse existing widget if possible */
897 if (! user_widget && G_TYPE_CHECK_INSTANCE_TYPE (widget, type))
899 g_object_set_valist (G_OBJECT (widget), first_property, args);
903 /* We have to abandon old content widget */
905 gtk_container_remove (GTK_CONTAINER (priv->layout), widget);
907 /* Use user provided widget or create a new one */
908 priv->main_item = widget = user_widget ?
909 user_widget : GTK_WIDGET (g_object_new_valist(type, first_property, args));
910 gtk_box_pack_start (GTK_BOX (priv->layout), widget, FALSE, FALSE, 0);
913 /* We make sure that the widget exists in desired position. Different
914 banners place this child widget to different places */
915 gtk_box_reorder_child (GTK_BOX (priv->layout), widget, pos);
919 /* Creates a new banner instance or uses an existing one */
921 hildon_banner_get_instance_for_widget (GtkWidget *widget,
926 window = widget ? gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW) : NULL;
927 return g_object_new (HILDON_TYPE_BANNER, "parent-window", window, "is-timed", timed, NULL);
931 * hildon_banner_show_information:
932 * @widget: the #GtkWidget that is the owner of the banner
933 * @icon_name: since Hildon 2.2 this parameter is not used anymore and
934 * any value that you pass will be ignored
935 * @text: Text to display
937 * This function creates and displays an information banner that is
938 * automatically destroyed after a certain time period (see
939 * hildon_banner_set_timeout()). For each window in your application
940 * there can only be one timed banner, so if you spawn a new banner
941 * before the earlier one has timed out, the previous one will be
944 * Returns: The newly created banner
948 hildon_banner_show_information (GtkWidget *widget,
949 const gchar *icon_name,
952 return hildon_banner_real_show_information (widget, text, FALSE);
956 * hildon_banner_show_information_override_dnd:
957 * @widget: the #GtkWidget that is the owner of the banner
958 * @text: Text to display
960 * Equivalent to hildon_banner_show_information(), but overriding the
961 * "do not disturb" flag.
963 * Returns: The newly created banner
969 hildon_banner_show_information_override_dnd (GtkWidget *widget,
972 return hildon_banner_real_show_information (widget, text, TRUE);
976 hildon_banner_set_override_flag (HildonBanner *banner)
980 gdk_property_change (GTK_WIDGET (banner)->window,
981 gdk_atom_intern_static_string ("_HILDON_DO_NOT_DISTURB_OVERRIDE"),
982 gdk_x11_xatom_to_atom (XA_INTEGER),
984 GDK_PROP_MODE_REPLACE,
985 (const guchar*) &state,
991 hildon_banner_real_show_information (GtkWidget *widget,
993 gboolean override_dnd)
995 HildonBanner *banner;
996 HildonBannerPrivate *priv = NULL;
998 g_return_val_if_fail (text != NULL, NULL);
1000 /* Prepare banner */
1001 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
1002 priv = HILDON_BANNER_GET_PRIVATE (banner);
1004 priv->name_suffix = "information";
1005 hildon_banner_set_text (banner, text);
1006 hildon_banner_bind_style (banner);
1009 /* so on the realize it will set the property */
1010 priv->require_override_dnd = TRUE;
1013 /* Show the banner, since caller cannot do that */
1014 gtk_widget_show_all (GTK_WIDGET (banner));
1016 return GTK_WIDGET (banner);
1020 * hildon_banner_show_informationf:
1021 * @widget: the #GtkWidget that is the owner of the banner
1022 * @icon_name: since Hildon 2.2 this parameter is not used anymore and
1023 * any value that you pass will be ignored
1024 * @format: a printf-like format string
1025 * @Varargs: arguments for the format string
1027 * A helper function for hildon_banner_show_information() with
1028 * string formatting.
1030 * Returns: the newly created banner
1033 hildon_banner_show_informationf (GtkWidget *widget,
1034 const gchar *icon_name,
1035 const gchar *format,
1038 g_return_val_if_fail (format != NULL, NULL);
1044 va_start (args, format);
1045 message = g_strdup_vprintf (format, args);
1048 banner = hildon_banner_show_information (widget, icon_name, message);
1056 * hildon_banner_show_information_with_markup:
1057 * @widget: the #GtkWidget that wants to display banner
1058 * @icon_name: since Hildon 2.2 this parameter is not used anymore and
1059 * any value that you pass will be ignored
1060 * @markup: a markup string to display (see <link linkend="PangoMarkupFormat">Pango markup format</link>)
1062 * This function creates and displays an information banner that is
1063 * automatically destroyed after certain time period (see
1064 * hildon_banner_set_timeout()). For each window in your application
1065 * there can only be one timed banner, so if you spawn a new banner
1066 * before the earlier one has timed out, the previous one will be
1069 * Returns: the newly created banner
1073 hildon_banner_show_information_with_markup (GtkWidget *widget,
1074 const gchar *icon_name,
1075 const gchar *markup)
1077 HildonBanner *banner;
1078 HildonBannerPrivate *priv;
1080 g_return_val_if_fail (icon_name == NULL || icon_name[0] != 0, NULL);
1081 g_return_val_if_fail (markup != NULL, NULL);
1083 /* Prepare banner */
1084 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
1085 priv = HILDON_BANNER_GET_PRIVATE (banner);
1087 priv->name_suffix = "information";
1088 hildon_banner_set_markup (banner, markup);
1089 hildon_banner_bind_style (banner);
1091 /* Show the banner, since caller cannot do that */
1092 gtk_widget_show_all (GTK_WIDGET (banner));
1094 return (GtkWidget *) banner;
1098 * hildon_banner_show_animation:
1099 * @widget: the #GtkWidget that wants to display banner
1100 * @animation_name: since Hildon 2.2 this parameter is not used
1101 * anymore and any value that you pass will be
1103 * @text: the text to display.
1105 * Shows an animated progress notification. It's recommended not to try
1106 * to show more than one progress notification at a time, since
1107 * they will appear on top of each other. You can use progress
1108 * notifications with timed banners. In this case the banners are
1109 * located so that you can somehow see both.
1111 * Unlike information banners (created with
1112 * hildon_banner_show_information()), animation banners are not
1113 * destroyed automatically using a timeout. You have to destroy them
1116 * Please note also that these banners are destroyed automatically if the
1117 * window they are attached to is closed. The pointer that you receive
1118 * with this function does not contain additional references, so it
1119 * can become invalid without warning (this is true for all toplevel
1120 * windows in gtk). To make sure that the banner does not disappear
1121 * automatically, you can separately ref the return value (this
1122 * doesn't prevent the banner from disappearing, just the object from
1123 * being finalized). In this case you have to call
1124 * gtk_widget_destroy() followed by g_object_unref().
1126 * Returns: a #HildonBanner widget. You must call gtk_widget_destroy()
1127 * once you are done with the banner.
1129 * Deprecated: Hildon 2.2: use
1130 * hildon_gtk_window_set_progress_indicator() instead.
1133 hildon_banner_show_animation (GtkWidget *widget,
1134 const gchar *animation_name,
1137 HildonBanner *banner;
1138 GtkWidget *image_widget;
1139 HildonBannerPrivate *priv;
1141 g_return_val_if_fail (text != NULL, NULL);
1143 image_widget = hildon_private_create_animation (
1144 HILDON_BANNER_ANIMATION_FRAMERATE,
1145 HILDON_BANNER_ANIMATION_TMPL,
1146 HILDON_BANNER_ANIMATION_NFRAMES);
1148 /* Prepare banner */
1149 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
1150 hildon_banner_ensure_child (banner, image_widget, 0,
1151 GTK_TYPE_IMAGE, "yalign", 0.0, NULL);
1153 priv = HILDON_BANNER_GET_PRIVATE (banner);
1154 priv->name_suffix = "animation";
1155 hildon_banner_set_text (banner, text);
1156 hildon_banner_bind_style (banner);
1159 gtk_widget_show_all (GTK_WIDGET (banner));
1161 return (GtkWidget *) banner;
1165 * hildon_banner_show_progress:
1166 * @widget: the #GtkWidget that wants to display banner
1167 * @bar: since Hildon 2.2 this parameter is not used anymore and
1168 * any value that you pass will be ignored
1169 * @text: text to display.
1171 * Shows progress notification. See hildon_banner_show_animation()
1172 * for more information.
1174 * Returns: a #HildonBanner widget. You must call #gtk_widget_destroy
1175 * once you are done with the banner.
1177 * Deprecated: Hildon 2.2: use hildon_gtk_window_set_progress_indicator() instead.
1180 hildon_banner_show_progress (GtkWidget *widget,
1181 GtkProgressBar *bar,
1184 HildonBanner *banner;
1185 HildonBannerPrivate *priv;
1187 g_return_val_if_fail (text != NULL, NULL);
1189 /* Prepare banner */
1190 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
1191 priv = HILDON_BANNER_GET_PRIVATE (banner);
1194 priv->name_suffix = "progress";
1195 hildon_banner_set_text (banner, text);
1196 hildon_banner_bind_style (banner);
1199 hildon_gtk_window_set_progress_indicator (priv->parent, 1);
1201 /* Show the banner */
1202 gtk_widget_show_all (GTK_WIDGET (banner));
1204 return GTK_WIDGET (banner);
1208 * hildon_banner_set_text:
1209 * @self: a #HildonBanner widget
1210 * @text: a new text to display in banner
1212 * Sets the text that is displayed in the banner.
1216 hildon_banner_set_text (HildonBanner *self,
1220 HildonBannerPrivate *priv;
1221 const gchar *existing_text;
1223 g_return_if_fail (HILDON_IS_BANNER (self));
1225 priv = HILDON_BANNER_GET_PRIVATE (self);
1228 label = GTK_LABEL (priv->label);
1229 existing_text = gtk_label_get_text (label);
1231 if (existing_text != NULL &&
1233 strcmp (existing_text, text) != 0) {
1234 gtk_label_set_text (label, text);
1235 hildon_banner_reset_wrap_state (self);
1238 hildon_banner_check_position (GTK_WIDGET (self));
1242 * hildon_banner_set_markup:
1243 * @self: a #HildonBanner widget
1244 * @markup: a new text with Pango markup to display in the banner
1246 * Sets the text with markup that is displayed in the banner.
1250 hildon_banner_set_markup (HildonBanner *self,
1251 const gchar *markup)
1254 HildonBannerPrivate *priv;
1256 g_return_if_fail (HILDON_IS_BANNER (self));
1258 priv = HILDON_BANNER_GET_PRIVATE (self);
1261 label = GTK_LABEL (priv->label);
1262 gtk_label_set_markup (label, markup);
1264 hildon_banner_reset_wrap_state (self);
1266 hildon_banner_check_position (GTK_WIDGET(self));
1270 * hildon_banner_set_fraction:
1271 * @self: a #HildonBanner widget
1272 * @fraction: #gdouble
1274 * The fraction is the completion of progressbar,
1275 * the scale is from 0.0 to 1.0.
1276 * Sets the amount of fraction the progressbar has.
1278 * Note that this method only has effect if @self was created with
1279 * hildon_banner_show_progress()
1281 * Deprecated: This function does nothing. As of Hildon 2.2, hildon
1282 * banners don't have progress bars.
1285 hildon_banner_set_fraction (HildonBanner *self,
1291 * hildon_banner_set_timeout:
1292 * @self: a #HildonBanner widget
1293 * @timeout: timeout to set in miliseconds.
1295 * Sets the timeout on the banner. After the given amount of miliseconds
1296 * has elapsed the banner will be destroyed. Setting this only makes
1297 * sense on banners that are timed and that have not been yet displayed
1300 * Note that this method only has effect if @self is an information
1301 * banner (created using hildon_banner_show_information() and
1305 hildon_banner_set_timeout (HildonBanner *self,
1308 HildonBannerPrivate *priv;
1310 g_return_if_fail (HILDON_IS_BANNER (self));
1311 priv = HILDON_BANNER_GET_PRIVATE (self);
1314 priv->timeout = timeout;
1318 * hildon_banner_set_icon:
1319 * @self: a #HildonBanner widget
1320 * @icon_name: the name of icon to use. Can be %NULL for default icon
1322 * Sets the icon to be used in the banner.
1324 * Deprecated: This function does nothing. As of hildon 2.2, hildon
1325 * banners don't allow changing their icons.
1328 hildon_banner_set_icon (HildonBanner *self,
1329 const gchar *icon_name)
1334 * hildon_banner_set_icon_from_file:
1335 * @self: a #HildonBanner widget
1336 * @icon_file: the filename of icon to use. Can be %NULL for default icon
1338 * Sets the icon from its filename to be used in the banner.
1340 * Deprecated: This function does nothing. As of hildon 2.2, hildon
1341 * banners don't allow changing their icons.
1344 hildon_banner_set_icon_from_file (HildonBanner *self,
1345 const gchar *icon_file)