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,
138 hildon_banner_timeout (gpointer data);
141 hildon_banner_clear_timeout (HildonBanner *self);
144 hildon_banner_ensure_timeout (HildonBanner *self);
147 hildon_banner_set_property (GObject *object,
153 hildon_banner_get_property (GObject *object,
159 hildon_banner_destroy (GtkObject *object);
162 hildon_banner_real_get_instance (GObject *window,
166 hildon_banner_constructor (GType type,
167 guint n_construct_params,
168 GObjectConstructParam *construct_params);
171 hildon_banner_finalize (GObject *object);
174 hildon_banner_button_press_event (GtkWidget* widget,
175 GdkEventButton* event);
178 hildon_banner_map_event (GtkWidget *widget,
181 hildon_banner_reset_wrap_state (HildonBanner *banner);
184 force_to_wrap_truncated (HildonBanner *banner);
187 hildon_banner_check_position (GtkWidget *widget);
190 hildon_banner_realize (GtkWidget *widget);
193 hildon_banner_class_init (HildonBannerClass *klass);
196 hildon_banner_init (HildonBanner *self);
199 hildon_banner_ensure_child (HildonBanner *self,
200 GtkWidget *user_widget,
203 const gchar *first_property,
207 hildon_banner_get_instance_for_widget (GtkWidget *widget,
211 hildon_banner_set_override_flag (HildonBanner *banner);
214 hildon_banner_real_show_information (GtkWidget *widget,
216 gboolean override_dnd);
218 G_DEFINE_TYPE (HildonBanner, hildon_banner, GTK_TYPE_WINDOW)
220 typedef struct _HildonBannerPrivate HildonBannerPrivate;
222 #define HILDON_BANNER_GET_PRIVATE(obj) \
223 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
224 HILDON_TYPE_BANNER, HildonBannerPrivate));
226 struct _HildonBannerPrivate
228 GtkWidget *main_item;
229 GtkWidget *alignment;
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,
256 const gchar *name_sufix)
258 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
263 name = g_strconcat ("HildonBannerLabel-", name_sufix, NULL);
264 gtk_widget_set_name (priv->label, name);
267 name = g_strconcat ("HildonBanner-", name_sufix, NULL);
268 gtk_widget_set_name (GTK_WIDGET (self), name);
272 /* In timeout function we automatically destroy timed banners */
274 simulate_close (GtkWidget* widget)
276 gboolean result = FALSE;
278 /* If the banner is currently visible (it normally should),
279 we simulate clicking the close button of the window.
280 This allows applications to reuse the banner by prevent
282 if (GTK_WIDGET_DRAWABLE (widget))
284 GdkEvent *event = gdk_event_new (GDK_DELETE);
285 event->any.window = g_object_ref (widget->window);
286 event->any.send_event = FALSE;
287 result = gtk_widget_event (widget, event);
288 gdk_event_free (event);
295 hildon_banner_timeout (gpointer data)
298 gboolean continue_timeout = FALSE;
300 GDK_THREADS_ENTER ();
302 g_assert (HILDON_IS_BANNER (data));
304 widget = GTK_WIDGET (data);
305 g_object_ref (widget);
307 continue_timeout = simulate_close (widget);
309 if (! continue_timeout) {
310 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (data);
311 priv->timeout_id = 0;
312 gtk_widget_destroy (widget);
315 g_object_unref (widget);
317 GDK_THREADS_LEAVE ();
319 return continue_timeout;
323 hildon_banner_clear_timeout (HildonBanner *self)
325 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
328 if (priv->timeout_id != 0) {
329 g_source_remove (priv->timeout_id);
330 priv->timeout_id = 0;
338 hildon_banner_ensure_timeout (HildonBanner *self)
340 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
343 if (priv->timeout_id == 0 && priv->is_timed && priv->timeout > 0)
344 priv->timeout_id = g_timeout_add (priv->timeout,
345 hildon_banner_timeout, self);
349 hildon_banner_set_property (GObject *object,
355 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
361 priv->timeout = g_value_get_uint (value);
365 priv->is_timed = g_value_get_boolean (value);
368 case PROP_PARENT_WINDOW:
369 window = g_value_get_object (value);
371 g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent);
374 gtk_window_set_transient_for (GTK_WINDOW (object), (GtkWindow *) window);
375 priv->parent = (GtkWindow *) window;
378 gtk_window_set_destroy_with_parent (GTK_WINDOW (object), TRUE);
379 g_object_add_weak_pointer(G_OBJECT (window), (gpointer) &priv->parent);
385 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
391 hildon_banner_get_property (GObject *object,
396 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
402 g_value_set_uint (value, priv->timeout);
406 g_value_set_boolean (value, priv->is_timed);
409 case PROP_PARENT_WINDOW:
410 g_value_set_object (value, gtk_window_get_transient_for (GTK_WINDOW (object)));
414 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
420 hildon_banner_destroy (GtkObject *object)
422 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
426 GObject *parent_window = (GObject *) priv->parent;
428 g_assert (HILDON_IS_BANNER (object));
429 self = HILDON_BANNER (object);
431 /* Drop possible global pointer. That can hold reference to us */
432 if ((gpointer) object == (gpointer) global_timed_banner) {
433 global_timed_banner = NULL;
434 g_object_unref (object);
437 /* Remove the data from parent window for timed banners. Those hold reference */
438 if (priv->is_timed && parent_window != NULL) {
439 g_object_set_qdata (parent_window, hildon_banner_timed_quark (), NULL);
442 if (!priv->is_timed && priv->parent) {
443 hildon_gtk_window_set_progress_indicator (priv->parent, 0);
446 (void) hildon_banner_clear_timeout (self);
448 if (GTK_OBJECT_CLASS (hildon_banner_parent_class)->destroy)
449 GTK_OBJECT_CLASS (hildon_banner_parent_class)->destroy (object);
452 /* Search a previous banner instance */
454 hildon_banner_real_get_instance (GObject *window,
458 /* If we have a parent window, the previous instance is stored there */
460 return g_object_get_qdata(window, hildon_banner_timed_quark ());
463 /* System notification instance is stored into global pointer */
464 return (GObject *) global_timed_banner;
467 /* Non-timed banners are normal (non-singleton) objects */
471 /* By overriding constructor we force timed banners to be
472 singletons for each window */
474 hildon_banner_constructor (GType type,
475 guint n_construct_params,
476 GObjectConstructParam *construct_params)
478 GObject *banner, *window = NULL;
479 gboolean timed = FALSE;
482 /* Search banner type information from parameters in order
483 to locate the possible previous banner instance. */
484 for (i = 0; i < n_construct_params; i++)
486 if (strcmp(construct_params[i].pspec->name, "parent-window") == 0)
487 window = g_value_get_object (construct_params[i].value);
488 else if (strcmp(construct_params[i].pspec->name, "is-timed") == 0)
489 timed = g_value_get_boolean (construct_params[i].value);
492 /* Try to get a previous instance if such exists */
493 banner = hildon_banner_real_get_instance (window, timed);
496 /* We have to create a new banner */
497 banner = G_OBJECT_CLASS (hildon_banner_parent_class)->constructor (type, n_construct_params, construct_params);
499 /* Store the newly created singleton instance either into parent
500 window data or into global variables. */
503 g_object_set_qdata_full (G_OBJECT (window), hildon_banner_timed_quark (),
504 g_object_ref (banner), g_object_unref);
506 g_assert (global_timed_banner == NULL);
507 global_timed_banner = g_object_ref (banner);
512 /* FIXME: This is a hack! We have to manually freeze
513 notifications. This is normally done by g_object_init, but we
514 are not going to call that. g_object_newv will otherwise give
515 a critical like this:
517 GLIB CRITICAL ** GLib-GObject - g_object_notify_queue_thaw:
518 assertion `nqueue->freeze_count > 0' failed */
520 g_object_freeze_notify (banner);
521 hildon_banner_reset_wrap_state (HILDON_BANNER (banner));
524 /* We restart possible timeouts for each new timed banner request */
525 if (timed && hildon_banner_clear_timeout (HILDON_BANNER (banner)))
526 hildon_banner_ensure_timeout (HILDON_BANNER(banner));
532 hildon_banner_finalize (GObject *object)
534 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
537 g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent);
540 G_OBJECT_CLASS (hildon_banner_parent_class)->finalize (object);
544 hildon_banner_button_press_event (GtkWidget* widget,
545 GdkEventButton* event)
547 gboolean result = simulate_close (widget);
550 /* signal emission not stopped - basically behave like
551 * gtk_main_do_event() for a delete event, but just hide the
552 * banner instead of destroying it, as it is already meant to
553 * be destroyed by hildon_banner_timeout() (if it's timed) or
554 * the application (if it's not). */
555 gtk_widget_hide (widget);
561 #if defined(MAEMO_GTK)
563 hildon_banner_map (GtkWidget *widget)
565 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->map) {
566 /* Make the banner temporary _before_ mapping it, to avoid closing
567 * other temporary windows */
568 gtk_window_set_is_temporary (GTK_WINDOW (widget), TRUE);
570 GTK_WIDGET_CLASS (hildon_banner_parent_class)->map (widget);
572 /* Make the banner non-temporary _after_ mapping it, to avoid
573 * being closed by other non-temporary windows */
574 gtk_window_set_is_temporary (GTK_WINDOW (widget), FALSE);
576 hildon_banner_check_position (widget);
581 /* We start the timer for timed notifications after the window appears on screen */
583 hildon_banner_map_event (GtkWidget *widget,
586 gboolean result = FALSE;
588 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->map_event)
589 result = GTK_WIDGET_CLASS (hildon_banner_parent_class)->map_event (widget, event);
591 hildon_banner_ensure_timeout (HILDON_BANNER(widget));
597 hildon_banner_reset_wrap_state (HildonBanner *banner)
600 HildonBannerPrivate *priv;
602 priv = HILDON_BANNER_GET_PRIVATE (banner);
605 layout = gtk_label_get_layout (GTK_LABEL (priv->label));
607 pango_layout_set_width (layout, -1);
608 priv->has_been_wrapped = FALSE;
609 priv->has_been_truncated = FALSE;
611 gtk_widget_set_size_request (priv->label, -1, -1);
612 gtk_widget_set_size_request (GTK_WIDGET (banner), -1, -1);
615 /* force to wrap truncated label by setting explicit size request
616 * see N#27000 and G#329646 */
618 force_to_wrap_truncated (HildonBanner *banner)
622 int width_text, width_max;
625 PangoRectangle logical;
626 GtkRequisition requisition;
627 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (banner);
629 g_return_if_fail (priv);
631 label = GTK_LABEL (priv->label);
633 layout = gtk_label_get_layout (label);
635 pango_layout_get_extents (layout, NULL, &logical);
636 width_text = PANGO_PIXELS (logical.width);
638 width_max = priv->is_timed ? HILDON_BANNER_LABEL_MAX_TIMED
639 : HILDON_BANNER_LABEL_MAX_PROGRESS;
641 /* If the width of the label is going to exceed the maximum allowed
642 * width, enforce the maximum allowed width now.
644 if (priv->has_been_wrapped
645 || width_text >= width_max
646 || pango_layout_is_wrapped (layout)) {
647 /* Force wrapping by setting the maximum size */
650 priv->has_been_wrapped = TRUE;
653 /* Make the label update its layout; and update our layout pointer
654 * because the layout will be cleared and refreshed.
656 gtk_widget_set_size_request (GTK_WIDGET (label), width, height);
657 gtk_widget_size_request (GTK_WIDGET (label), &requisition);
659 layout = gtk_label_get_layout (label);
661 /* If the layout has now been wrapped and exceeds 3 lines, we truncate
662 * the rest of the label according to spec.
664 if (priv->has_been_truncated
665 || (pango_layout_is_wrapped (layout)
666 && pango_layout_get_line_count (layout) > 3)) {
669 pango_layout_get_extents (layout, NULL, &logical);
670 lines = pango_layout_get_line_count (layout);
672 /* This calculation assumes that the same font is used
673 * throughout the banner -- this is usually the case on maemo
675 * FIXME: Pango >= 1.20 has pango_layout_set_height().
677 height = (PANGO_PIXELS (logical.height) * 3) / lines + 1;
678 priv->has_been_truncated = TRUE;
681 /* Set the new width/height if applicable */
682 gtk_widget_set_size_request (GTK_WIDGET (label), width, height);
687 hildon_banner_check_position (GtkWidget *widget)
692 gtk_widget_set_size_request (widget, gdk_screen_width (), -1);
694 force_to_wrap_truncated (HILDON_BANNER(widget)); /* see N#27000 and G#329646 */
696 gtk_widget_size_request (widget, &req);
703 x = HILDON_BANNER_WINDOW_X;
705 y = HILDON_BANNER_WINDOW_Y;
707 gtk_window_move (GTK_WINDOW (widget), x, y);
711 screen_size_changed (GdkScreen *screen,
715 gtk_window_reshow_with_initial_size (banner);
719 hildon_banner_realize (GtkWidget *widget)
724 guint32 portrait = 1;
725 const gchar *notification_type = "_HILDON_NOTIFICATION_TYPE_BANNER";
726 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (widget);
729 /* We let the parent to init widget->window before we need it */
730 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->realize)
731 GTK_WIDGET_CLASS (hildon_banner_parent_class)->realize (widget);
733 /* We use special hint to turn the banner into information notification. */
734 gdk_window_set_type_hint (widget->window, GDK_WINDOW_TYPE_HINT_NOTIFICATION);
735 gtk_window_set_transient_for (GTK_WINDOW (widget), (GtkWindow *) priv->parent);
737 hildon_banner_check_position (widget);
739 gdkwin = widget->window;
741 /* Set the _HILDON_NOTIFICATION_TYPE property so Matchbox places the window correctly */
742 atom = gdk_atom_intern ("_HILDON_NOTIFICATION_TYPE", FALSE);
743 gdk_property_change (gdkwin, atom, gdk_x11_xatom_to_atom (XA_STRING), 8, GDK_PROP_MODE_REPLACE,
744 (gpointer) notification_type, strlen (notification_type));
746 /* HildonBanner supports portrait mode */
747 atom = gdk_atom_intern ("_HILDON_PORTRAIT_MODE_SUPPORT", FALSE);
748 gdk_property_change (gdkwin, atom, gdk_x11_xatom_to_atom (XA_CARDINAL), 32,
749 GDK_PROP_MODE_REPLACE, (gpointer) &portrait, 1);
751 /* Manage override flag */
752 if ((priv->require_override_dnd)&&(!priv->overrides_dnd)) {
753 hildon_banner_set_override_flag (HILDON_BANNER (widget));
754 priv->overrides_dnd = TRUE;
757 screen = gtk_widget_get_screen (widget);
758 g_signal_connect (screen, "size-changed", G_CALLBACK (screen_size_changed), widget);
762 hildon_banner_unrealize (GtkWidget *widget)
764 GdkScreen *screen = gtk_widget_get_screen (widget);
765 g_signal_handlers_disconnect_by_func (screen, G_CALLBACK (screen_size_changed), widget);
767 GTK_WIDGET_CLASS (hildon_banner_parent_class)->unrealize (widget);
771 hildon_banner_class_init (HildonBannerClass *klass)
773 GObjectClass *object_class;
774 GtkWidgetClass *widget_class;
776 object_class = G_OBJECT_CLASS (klass);
777 widget_class = GTK_WIDGET_CLASS (klass);
779 /* Append private structure to class. This is more elegant than
780 on g_new based approach */
781 g_type_class_add_private (klass, sizeof (HildonBannerPrivate));
783 /* Override virtual methods */
784 object_class->constructor = hildon_banner_constructor;
785 object_class->finalize = hildon_banner_finalize;
786 object_class->set_property = hildon_banner_set_property;
787 object_class->get_property = hildon_banner_get_property;
788 GTK_OBJECT_CLASS (klass)->destroy = hildon_banner_destroy;
789 widget_class->map_event = hildon_banner_map_event;
790 widget_class->realize = hildon_banner_realize;
791 widget_class->unrealize = hildon_banner_unrealize;
792 widget_class->button_press_event = hildon_banner_button_press_event;
793 #if defined(MAEMO_GTK)
794 widget_class->map = hildon_banner_map;
797 /* Install properties.
798 We need construct properties for singleton purposes */
801 * HildonBanner:parent-window:
803 * The window for which the banner will be singleton.
806 g_object_class_install_property (object_class, PROP_PARENT_WINDOW,
807 g_param_spec_object ("parent-window",
809 "The window for which the banner will be singleton",
810 GTK_TYPE_WINDOW, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
813 * HildonBanner:is-timed:
815 * Whether the banner is timed and goes away automatically.
818 g_object_class_install_property (object_class, PROP_IS_TIMED,
819 g_param_spec_boolean ("is-timed",
821 "Whether or not the notification goes away automatically "
822 "after the specified time has passed",
823 FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
826 * HildonBanner:timeout:
828 * The time before destroying the banner. This needs
829 * to be adjusted before the banner is mapped to the screen.
832 g_object_class_install_property (object_class, PROP_TIMEOUT,
833 g_param_spec_uint ("timeout",
835 "The time before making the banner banner go away",
838 HILDON_BANNER_DEFAULT_TIMEOUT,
839 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
843 hildon_banner_init (HildonBanner *self)
845 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
849 priv->overrides_dnd = FALSE;
850 priv->require_override_dnd = FALSE;
852 /* Initialize the common layout inside banner */
853 priv->alignment = gtk_alignment_new (0.5, 0.5, 0, 0);
854 priv->layout = gtk_hbox_new (FALSE, HILDON_MARGIN_DEFAULT);
856 priv->label = g_object_new (GTK_TYPE_LABEL, NULL);
857 gtk_label_set_line_wrap (GTK_LABEL (priv->label), TRUE);
858 gtk_label_set_line_wrap_mode (GTK_LABEL (priv->label), PANGO_WRAP_WORD_CHAR);
860 gtk_container_set_border_width (GTK_CONTAINER (priv->layout), HILDON_MARGIN_DEFAULT);
861 gtk_container_add (GTK_CONTAINER (self), priv->alignment);
862 gtk_container_add (GTK_CONTAINER (priv->alignment), priv->layout);
863 gtk_box_pack_start (GTK_BOX (priv->layout), priv->label, FALSE, FALSE, 0);
865 gtk_window_set_accept_focus (GTK_WINDOW (self), FALSE);
867 hildon_banner_reset_wrap_state (self);
869 gtk_widget_add_events (GTK_WIDGET (self), GDK_BUTTON_PRESS_MASK);
872 /* Makes sure that icon/progress item contains the desired type
873 of item. If possible, tries to avoid creating a new widget but
874 reuses the existing one */
876 hildon_banner_ensure_child (HildonBanner *self,
877 GtkWidget *user_widget,
880 const gchar *first_property,
885 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
889 widget = priv->main_item;
890 va_start (args, first_property);
892 /* Reuse existing widget if possible */
893 if (! user_widget && G_TYPE_CHECK_INSTANCE_TYPE (widget, type))
895 g_object_set_valist (G_OBJECT (widget), first_property, args);
899 /* We have to abandon old content widget */
901 gtk_container_remove (GTK_CONTAINER (priv->layout), widget);
903 /* Use user provided widget or create a new one */
904 priv->main_item = widget = user_widget ?
905 user_widget : GTK_WIDGET (g_object_new_valist(type, first_property, args));
906 gtk_box_pack_start (GTK_BOX (priv->layout), widget, FALSE, FALSE, 0);
909 /* We make sure that the widget exists in desired position. Different
910 banners place this child widget to different places */
911 gtk_box_reorder_child (GTK_BOX (priv->layout), widget, pos);
915 /* Creates a new banner instance or uses an existing one */
917 hildon_banner_get_instance_for_widget (GtkWidget *widget,
922 window = widget ? gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW) : NULL;
923 return g_object_new (HILDON_TYPE_BANNER, "parent-window", window, "is-timed", timed, NULL);
927 * hildon_banner_show_information:
928 * @widget: the #GtkWidget that is the owner of the banner
929 * @icon_name: since Hildon 2.2 this parameter is not used anymore and
930 * any value that you pass will be ignored
931 * @text: Text to display
933 * This function creates and displays an information banner that is
934 * automatically destroyed after a certain time period (see
935 * hildon_banner_set_timeout()). For each window in your application
936 * there can only be one timed banner, so if you spawn a new banner
937 * before the earlier one has timed out, the previous one will be
940 * Returns: The newly created banner
944 hildon_banner_show_information (GtkWidget *widget,
945 const gchar *icon_name,
948 return hildon_banner_real_show_information (widget, text, FALSE);
952 * hildon_banner_show_information_override_dnd:
953 * @widget: the #GtkWidget that is the owner of the banner
954 * @text: Text to display
956 * Equivalent to hildon_banner_show_information(), but overriding the
957 * "do not disturb" flag.
959 * Returns: The newly created banner
965 hildon_banner_show_information_override_dnd (GtkWidget *widget,
968 return hildon_banner_real_show_information (widget, text, TRUE);
972 hildon_banner_set_override_flag (HildonBanner *banner)
976 gdk_property_change (GTK_WIDGET (banner)->window,
977 gdk_atom_intern_static_string ("_HILDON_DO_NOT_DISTURB_OVERRIDE"),
978 gdk_x11_xatom_to_atom (XA_INTEGER),
980 GDK_PROP_MODE_REPLACE,
981 (const guchar*) &state,
987 hildon_banner_real_show_information (GtkWidget *widget,
989 gboolean override_dnd)
991 HildonBanner *banner;
992 HildonBannerPrivate *priv = NULL;
994 g_return_val_if_fail (text != NULL, NULL);
997 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
998 priv = HILDON_BANNER_GET_PRIVATE (banner);
1000 hildon_banner_set_text (banner, text);
1001 hildon_banner_bind_style (banner, "information");
1004 /* so on the realize it will set the property */
1005 priv->require_override_dnd = TRUE;
1008 /* Show the banner, since caller cannot do that */
1009 gtk_widget_show_all (GTK_WIDGET (banner));
1011 return GTK_WIDGET (banner);
1015 * hildon_banner_show_informationf:
1016 * @widget: the #GtkWidget that is the owner of the banner
1017 * @icon_name: since Hildon 2.2 this parameter is not used anymore and
1018 * any value that you pass will be ignored
1019 * @format: a printf-like format string
1020 * @Varargs: arguments for the format string
1022 * A helper function for hildon_banner_show_information() with
1023 * string formatting.
1025 * Returns: the newly created banner
1028 hildon_banner_show_informationf (GtkWidget *widget,
1029 const gchar *icon_name,
1030 const gchar *format,
1033 g_return_val_if_fail (format != NULL, NULL);
1039 va_start (args, format);
1040 message = g_strdup_vprintf (format, args);
1043 banner = hildon_banner_show_information (widget, icon_name, message);
1051 * hildon_banner_show_information_with_markup:
1052 * @widget: the #GtkWidget that wants to display banner
1053 * @icon_name: since Hildon 2.2 this parameter is not used anymore and
1054 * any value that you pass will be ignored
1055 * @markup: a markup string to display (see <link linkend="PangoMarkupFormat">Pango markup format</link>)
1057 * This function creates and displays an information banner that is
1058 * automatically destroyed after certain time period (see
1059 * hildon_banner_set_timeout()). For each window in your application
1060 * there can only be one timed banner, so if you spawn a new banner
1061 * before the earlier one has timed out, the previous one will be
1064 * Returns: the newly created banner
1068 hildon_banner_show_information_with_markup (GtkWidget *widget,
1069 const gchar *icon_name,
1070 const gchar *markup)
1072 HildonBanner *banner;
1074 g_return_val_if_fail (icon_name == NULL || icon_name[0] != 0, NULL);
1075 g_return_val_if_fail (markup != NULL, NULL);
1077 /* Prepare banner */
1078 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
1080 hildon_banner_set_markup (banner, markup);
1081 hildon_banner_bind_style (banner, "information");
1083 /* Show the banner, since caller cannot do that */
1084 gtk_widget_show_all (GTK_WIDGET (banner));
1086 return (GtkWidget *) banner;
1090 * hildon_banner_show_animation:
1091 * @widget: the #GtkWidget that wants to display banner
1092 * @animation_name: since Hildon 2.2 this parameter is not used
1093 * anymore and any value that you pass will be
1095 * @text: the text to display.
1097 * Shows an animated progress notification. It's recommended not to try
1098 * to show more than one progress notification at a time, since
1099 * they will appear on top of each other. You can use progress
1100 * notifications with timed banners. In this case the banners are
1101 * located so that you can somehow see both.
1103 * Unlike information banners (created with
1104 * hildon_banner_show_information()), animation banners are not
1105 * destroyed automatically using a timeout. You have to destroy them
1108 * Please note also that these banners are destroyed automatically if the
1109 * window they are attached to is closed. The pointer that you receive
1110 * with this function does not contain additional references, so it
1111 * can become invalid without warning (this is true for all toplevel
1112 * windows in gtk). To make sure that the banner does not disappear
1113 * automatically, you can separately ref the return value (this
1114 * doesn't prevent the banner from disappearing, just the object from
1115 * being finalized). In this case you have to call
1116 * gtk_widget_destroy() followed by g_object_unref().
1118 * Returns: a #HildonBanner widget. You must call gtk_widget_destroy()
1119 * once you are done with the banner.
1121 * Deprecated: Hildon 2.2: use
1122 * hildon_gtk_window_set_progress_indicator() instead.
1125 hildon_banner_show_animation (GtkWidget *widget,
1126 const gchar *animation_name,
1129 HildonBanner *banner;
1130 GtkWidget *image_widget;
1132 g_return_val_if_fail (text != NULL, NULL);
1134 image_widget = hildon_private_create_animation (
1135 HILDON_BANNER_ANIMATION_FRAMERATE,
1136 HILDON_BANNER_ANIMATION_TMPL,
1137 HILDON_BANNER_ANIMATION_NFRAMES);
1139 /* Prepare banner */
1140 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
1141 hildon_banner_ensure_child (banner, image_widget, 0,
1142 GTK_TYPE_IMAGE, "yalign", 0.0, NULL);
1144 hildon_banner_set_text (banner, text);
1145 hildon_banner_bind_style (banner, "animation");
1148 gtk_widget_show_all (GTK_WIDGET (banner));
1150 return (GtkWidget *) banner;
1154 * hildon_banner_show_progress:
1155 * @widget: the #GtkWidget that wants to display banner
1156 * @bar: since Hildon 2.2 this parameter is not used anymore and
1157 * any value that you pass will be ignored
1158 * @text: text to display.
1160 * Shows progress notification. See hildon_banner_show_animation()
1161 * for more information.
1163 * Returns: a #HildonBanner widget. You must call #gtk_widget_destroy
1164 * once you are done with the banner.
1166 * Deprecated: Hildon 2.2: use hildon_gtk_window_set_progress_indicator() instead.
1169 hildon_banner_show_progress (GtkWidget *widget,
1170 GtkProgressBar *bar,
1173 HildonBanner *banner;
1174 HildonBannerPrivate *priv;
1176 g_return_val_if_fail (text != NULL, NULL);
1178 /* Prepare banner */
1179 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
1180 priv = HILDON_BANNER_GET_PRIVATE (banner);
1183 hildon_banner_set_text (banner, text);
1184 hildon_banner_bind_style (banner, "progress");
1187 hildon_gtk_window_set_progress_indicator (priv->parent, 1);
1189 /* Show the banner */
1190 gtk_widget_show_all (GTK_WIDGET (banner));
1192 return GTK_WIDGET (banner);
1196 * hildon_banner_set_text:
1197 * @self: a #HildonBanner widget
1198 * @text: a new text to display in banner
1200 * Sets the text that is displayed in the banner.
1204 hildon_banner_set_text (HildonBanner *self,
1208 HildonBannerPrivate *priv;
1209 const gchar *existing_text;
1211 g_return_if_fail (HILDON_IS_BANNER (self));
1213 priv = HILDON_BANNER_GET_PRIVATE (self);
1216 label = GTK_LABEL (priv->label);
1217 existing_text = gtk_label_get_text (label);
1219 if (existing_text != NULL &&
1221 strcmp (existing_text, text) != 0) {
1222 gtk_label_set_text (label, text);
1223 hildon_banner_reset_wrap_state (self);
1226 hildon_banner_check_position (GTK_WIDGET (self));
1230 * hildon_banner_set_markup:
1231 * @self: a #HildonBanner widget
1232 * @markup: a new text with Pango markup to display in the banner
1234 * Sets the text with markup that is displayed in the banner.
1238 hildon_banner_set_markup (HildonBanner *self,
1239 const gchar *markup)
1242 HildonBannerPrivate *priv;
1244 g_return_if_fail (HILDON_IS_BANNER (self));
1246 priv = HILDON_BANNER_GET_PRIVATE (self);
1249 label = GTK_LABEL (priv->label);
1250 gtk_label_set_markup (label, markup);
1252 hildon_banner_reset_wrap_state (self);
1254 hildon_banner_check_position (GTK_WIDGET(self));
1258 * hildon_banner_set_fraction:
1259 * @self: a #HildonBanner widget
1260 * @fraction: #gdouble
1262 * The fraction is the completion of progressbar,
1263 * the scale is from 0.0 to 1.0.
1264 * Sets the amount of fraction the progressbar has.
1266 * Note that this method only has effect if @self was created with
1267 * hildon_banner_show_progress()
1269 * Deprecated: This function does nothing. As of Hildon 2.2, hildon
1270 * banners don't have progress bars.
1273 hildon_banner_set_fraction (HildonBanner *self,
1279 * hildon_banner_set_timeout:
1280 * @self: a #HildonBanner widget
1281 * @timeout: timeout to set in miliseconds.
1283 * Sets the timeout on the banner. After the given amount of miliseconds
1284 * has elapsed the banner will be destroyed. Setting this only makes
1285 * sense on banners that are timed and that have not been yet displayed
1288 * Note that this method only has effect if @self is an information
1289 * banner (created using hildon_banner_show_information() and
1293 hildon_banner_set_timeout (HildonBanner *self,
1296 HildonBannerPrivate *priv;
1298 g_return_if_fail (HILDON_IS_BANNER (self));
1299 priv = HILDON_BANNER_GET_PRIVATE (self);
1302 priv->timeout = timeout;
1306 * hildon_banner_set_icon:
1307 * @self: a #HildonBanner widget
1308 * @icon_name: the name of icon to use. Can be %NULL for default icon
1310 * Sets the icon to be used in the banner.
1312 * Deprecated: This function does nothing. As of hildon 2.2, hildon
1313 * banners don't allow changing their icons.
1316 hildon_banner_set_icon (HildonBanner *self,
1317 const gchar *icon_name)
1322 * hildon_banner_set_icon_from_file:
1323 * @self: a #HildonBanner widget
1324 * @icon_file: the filename of icon to use. Can be %NULL for default icon
1326 * Sets the icon from its filename to be used in the banner.
1328 * Deprecated: This function does nothing. As of hildon 2.2, hildon
1329 * banners don't allow changing their icons.
1332 hildon_banner_set_icon_from_file (HildonBanner *self,
1333 const gchar *icon_file)