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 reshow_banner (HildonBanner *banner);
205 hildon_banner_real_show_information (GtkWidget *widget,
207 gboolean override_dnd);
209 G_DEFINE_TYPE (HildonBanner, hildon_banner, GTK_TYPE_WINDOW)
211 typedef struct _HildonBannerPrivate HildonBannerPrivate;
213 #define HILDON_BANNER_GET_PRIVATE(obj) \
214 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
215 HILDON_TYPE_BANNER, HildonBannerPrivate));
217 struct _HildonBannerPrivate
219 GtkWidget *main_item;
220 GtkWidget *alignment;
224 const gchar *name_suffix;
228 guint require_override_dnd : 1;
229 guint overrides_dnd : 1;
233 hildon_banner_timed_quark (void)
235 static GQuark quark = 0;
237 if (G_UNLIKELY(quark == 0))
238 quark = g_quark_from_static_string ("hildon-banner-timed");
243 /* Set the widget and label name to make the correct rc-style attached into them */
245 hildon_banner_bind_style (HildonBanner *self)
247 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
248 GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (self));
249 gboolean portrait = gdk_screen_get_width (screen) < gdk_screen_get_height (screen);
250 const gchar *portrait_suffix = portrait ? "-portrait" : NULL;
255 name = g_strconcat ("HildonBannerLabel-", priv->name_suffix, NULL);
256 gtk_widget_set_name (priv->label, name);
259 name = g_strconcat ("HildonBanner-", priv->name_suffix, portrait_suffix, NULL);
260 gtk_widget_set_name (GTK_WIDGET (self), name);
264 /* In timeout function we automatically destroy timed banners */
266 simulate_close (GtkWidget* widget)
268 gboolean result = FALSE;
270 /* If the banner is currently visible (it normally should),
271 we simulate clicking the close button of the window.
272 This allows applications to reuse the banner by prevent
274 if (GTK_WIDGET_DRAWABLE (widget))
276 GdkEvent *event = gdk_event_new (GDK_DELETE);
277 event->any.window = g_object_ref (widget->window);
278 event->any.send_event = FALSE;
279 result = gtk_widget_event (widget, event);
280 gdk_event_free (event);
287 hildon_banner_size_request (GtkWidget *self,
290 GTK_WIDGET_CLASS (hildon_banner_parent_class)->size_request (self, req);
291 req->width = gdk_screen_get_width (gtk_widget_get_screen (self));
295 hildon_banner_timeout (gpointer data)
298 gboolean continue_timeout = FALSE;
300 g_assert (HILDON_IS_BANNER (data));
302 widget = GTK_WIDGET (data);
303 g_object_ref (widget);
305 continue_timeout = simulate_close (widget);
307 if (! continue_timeout) {
308 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (data);
309 if (priv->timeout_id) {
310 g_source_remove (priv->timeout_id);
311 priv->timeout_id = 0;
313 gtk_widget_destroy (widget);
316 g_object_unref (widget);
318 return continue_timeout;
322 hildon_banner_clear_timeout (HildonBanner *self)
324 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
327 if (priv->timeout_id != 0) {
328 g_source_remove (priv->timeout_id);
329 priv->timeout_id = 0;
337 hildon_banner_ensure_timeout (HildonBanner *self)
339 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
342 if (priv->timeout_id == 0 && priv->is_timed && priv->timeout > 0)
343 priv->timeout_id = gdk_threads_add_timeout (priv->timeout,
344 hildon_banner_timeout, self);
348 hildon_banner_set_property (GObject *object,
354 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
360 priv->timeout = g_value_get_uint (value);
364 priv->is_timed = g_value_get_boolean (value);
367 case PROP_PARENT_WINDOW:
368 window = g_value_get_object (value);
370 g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent);
373 gtk_window_set_transient_for (GTK_WINDOW (object), (GtkWindow *) window);
374 priv->parent = (GtkWindow *) window;
377 gtk_window_set_destroy_with_parent (GTK_WINDOW (object), TRUE);
378 g_object_add_weak_pointer(G_OBJECT (window), (gpointer) &priv->parent);
384 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
390 hildon_banner_get_property (GObject *object,
395 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
401 g_value_set_uint (value, priv->timeout);
405 g_value_set_boolean (value, priv->is_timed);
408 case PROP_PARENT_WINDOW:
409 g_value_set_object (value, gtk_window_get_transient_for (GTK_WINDOW (object)));
413 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
419 hildon_banner_destroy (GtkObject *object)
421 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
425 GObject *parent_window = (GObject *) priv->parent;
427 g_assert (HILDON_IS_BANNER (object));
428 self = HILDON_BANNER (object);
430 /* Drop possible global pointer. That can hold reference to us */
431 if ((gpointer) object == (gpointer) global_timed_banner) {
432 global_timed_banner = NULL;
433 g_object_unref (object);
436 /* Remove the data from parent window for timed banners. Those hold reference */
437 if (priv->is_timed && parent_window != NULL) {
438 g_object_set_qdata (parent_window, hildon_banner_timed_quark (), NULL);
441 if (!priv->is_timed && priv->parent) {
442 hildon_gtk_window_set_progress_indicator (priv->parent, 0);
445 (void) hildon_banner_clear_timeout (self);
447 if (GTK_OBJECT_CLASS (hildon_banner_parent_class)->destroy)
448 GTK_OBJECT_CLASS (hildon_banner_parent_class)->destroy (object);
451 /* Search a previous banner instance */
453 hildon_banner_real_get_instance (GObject *window,
457 /* If we have a parent window, the previous instance is stored there */
459 return g_object_get_qdata(window, hildon_banner_timed_quark ());
462 /* System notification instance is stored into global pointer */
463 return (GObject *) global_timed_banner;
466 /* Non-timed banners are normal (non-singleton) objects */
470 /* By overriding constructor we force timed banners to be
471 singletons for each window */
473 hildon_banner_constructor (GType type,
474 guint n_construct_params,
475 GObjectConstructParam *construct_params)
477 GObject *banner, *window = NULL;
478 gboolean timed = FALSE;
481 /* Search banner type information from parameters in order
482 to locate the possible previous banner instance. */
483 for (i = 0; i < n_construct_params; i++)
485 if (strcmp(construct_params[i].pspec->name, "parent-window") == 0)
486 window = g_value_get_object (construct_params[i].value);
487 else if (strcmp(construct_params[i].pspec->name, "is-timed") == 0)
488 timed = g_value_get_boolean (construct_params[i].value);
491 /* Try to get a previous instance if such exists */
492 banner = hildon_banner_real_get_instance (window, timed);
495 /* We have to create a new banner */
496 banner = G_OBJECT_CLASS (hildon_banner_parent_class)->constructor (type, n_construct_params, construct_params);
498 /* Store the newly created singleton instance either into parent
499 window data or into global variables. */
502 g_object_set_qdata_full (G_OBJECT (window), hildon_banner_timed_quark (),
503 g_object_ref (banner), g_object_unref);
505 g_assert (global_timed_banner == NULL);
506 global_timed_banner = g_object_ref (banner);
511 /* FIXME: This is a hack! We have to manually freeze
512 notifications. This is normally done by g_object_init, but we
513 are not going to call that. g_object_newv will otherwise give
514 a critical like this:
516 GLIB CRITICAL ** GLib-GObject - g_object_notify_queue_thaw:
517 assertion `nqueue->freeze_count > 0' failed */
519 g_object_freeze_notify (banner);
522 /* We restart possible timeouts for each new timed banner request */
523 if (timed && hildon_banner_clear_timeout (HILDON_BANNER (banner)))
524 hildon_banner_ensure_timeout (HILDON_BANNER(banner));
530 hildon_banner_finalize (GObject *object)
532 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
535 g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent);
538 G_OBJECT_CLASS (hildon_banner_parent_class)->finalize (object);
542 hildon_banner_button_press_event (GtkWidget* widget,
543 GdkEventButton* event)
545 gboolean result = simulate_close (widget);
548 /* signal emission not stopped - basically behave like
549 * gtk_main_do_event() for a delete event, but just hide the
550 * banner instead of destroying it, as it is already meant to
551 * be destroyed by hildon_banner_timeout() (if it's timed) or
552 * the application (if it's not). */
553 gtk_widget_hide (widget);
559 #if defined(MAEMO_GTK)
561 hildon_banner_map (GtkWidget *widget)
563 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->map) {
564 /* Make the banner temporary _before_ mapping it, to avoid closing
565 * other temporary windows */
566 gtk_window_set_is_temporary (GTK_WINDOW (widget), TRUE);
568 GTK_WIDGET_CLASS (hildon_banner_parent_class)->map (widget);
570 /* Make the banner non-temporary _after_ mapping it, to avoid
571 * being closed by other non-temporary windows */
572 gtk_window_set_is_temporary (GTK_WINDOW (widget), FALSE);
574 gtk_window_move (GTK_WINDOW (widget), 0, HILDON_WINDOW_TITLEBAR_HEIGHT);
579 /* We start the timer for timed notifications after the window appears on screen */
581 hildon_banner_map_event (GtkWidget *widget,
584 gboolean result = FALSE;
586 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->map_event)
587 result = GTK_WIDGET_CLASS (hildon_banner_parent_class)->map_event (widget, event);
589 hildon_banner_ensure_timeout (HILDON_BANNER(widget));
595 banner_do_set_text (HildonBanner *banner,
599 HildonBannerPrivate *priv;
602 priv = HILDON_BANNER_GET_PRIVATE (banner);
605 gtk_label_set_markup (GTK_LABEL (priv->label), text);
607 gtk_label_set_text (GTK_LABEL (priv->label), text);
609 gtk_widget_set_size_request (priv->label, -1, -1);
610 gtk_widget_size_request (priv->label, &req);
612 force_to_wrap_truncated (banner);
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)
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 = 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 (width >= width_max || pango_layout_is_wrapped (layout)) {
648 /* Make the label update its layout; and update our layout pointer
649 * because the layout will be cleared and refreshed.
651 gtk_widget_set_size_request (GTK_WIDGET (label), width, height);
652 gtk_widget_size_request (GTK_WIDGET (label), &requisition);
654 layout = gtk_label_get_layout (label);
656 /* If the layout has now been wrapped and exceeds 3 lines, we truncate
657 * the rest of the label according to spec.
659 if (pango_layout_is_wrapped (layout) && pango_layout_get_line_count (layout) > 3) {
662 pango_layout_get_extents (layout, NULL, &logical);
663 lines = pango_layout_get_line_count (layout);
665 /* This calculation assumes that the same font is used
666 * throughout the banner -- this is usually the case on maemo
668 * FIXME: Pango >= 1.20 has pango_layout_set_height().
670 height = (PANGO_PIXELS (logical.height) * 3) / lines + 1;
673 /* Set the new width/height if applicable */
674 gtk_widget_set_size_request (GTK_WIDGET (label), width, height);
678 screen_size_changed (GdkScreen *screen,
682 HildonBanner *hbanner = HILDON_BANNER (banner);
683 hildon_banner_bind_style (hbanner);
684 reshow_banner (hbanner);
688 hildon_banner_realize (GtkWidget *widget)
693 guint32 portrait = 1;
694 const gchar *notification_type = "_HILDON_NOTIFICATION_TYPE_BANNER";
695 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (widget);
698 /* We let the parent to init widget->window before we need it */
699 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->realize)
700 GTK_WIDGET_CLASS (hildon_banner_parent_class)->realize (widget);
702 /* We use special hint to turn the banner into information notification. */
703 gdk_window_set_type_hint (widget->window, GDK_WINDOW_TYPE_HINT_NOTIFICATION);
704 gtk_window_set_transient_for (GTK_WINDOW (widget), (GtkWindow *) priv->parent);
706 gdkwin = widget->window;
708 /* Set the _HILDON_NOTIFICATION_TYPE property so Matchbox places the window correctly */
709 atom = gdk_atom_intern ("_HILDON_NOTIFICATION_TYPE", FALSE);
710 gdk_property_change (gdkwin, atom, gdk_x11_xatom_to_atom (XA_STRING), 8, GDK_PROP_MODE_REPLACE,
711 (gpointer) notification_type, strlen (notification_type));
713 /* HildonBanner supports portrait mode */
714 atom = gdk_atom_intern ("_HILDON_PORTRAIT_MODE_SUPPORT", FALSE);
715 gdk_property_change (gdkwin, atom, gdk_x11_xatom_to_atom (XA_CARDINAL), 32,
716 GDK_PROP_MODE_REPLACE, (gpointer) &portrait, 1);
718 /* Manage override flag */
719 if ((priv->require_override_dnd)&&(!priv->overrides_dnd)) {
720 hildon_banner_set_override_flag (HILDON_BANNER (widget));
721 priv->overrides_dnd = TRUE;
724 screen = gtk_widget_get_screen (widget);
725 g_signal_connect (screen, "size-changed", G_CALLBACK (screen_size_changed), widget);
729 hildon_banner_unrealize (GtkWidget *widget)
731 GdkScreen *screen = gtk_widget_get_screen (widget);
732 g_signal_handlers_disconnect_by_func (screen, G_CALLBACK (screen_size_changed), widget);
734 GTK_WIDGET_CLASS (hildon_banner_parent_class)->unrealize (widget);
738 hildon_banner_class_init (HildonBannerClass *klass)
740 GObjectClass *object_class;
741 GtkWidgetClass *widget_class;
743 object_class = G_OBJECT_CLASS (klass);
744 widget_class = GTK_WIDGET_CLASS (klass);
746 /* Append private structure to class. This is more elegant than
747 on g_new based approach */
748 g_type_class_add_private (klass, sizeof (HildonBannerPrivate));
750 /* Override virtual methods */
751 object_class->constructor = hildon_banner_constructor;
752 object_class->finalize = hildon_banner_finalize;
753 object_class->set_property = hildon_banner_set_property;
754 object_class->get_property = hildon_banner_get_property;
755 GTK_OBJECT_CLASS (klass)->destroy = hildon_banner_destroy;
756 widget_class->size_request = hildon_banner_size_request;
757 widget_class->map_event = hildon_banner_map_event;
758 widget_class->realize = hildon_banner_realize;
759 widget_class->unrealize = hildon_banner_unrealize;
760 widget_class->button_press_event = hildon_banner_button_press_event;
761 #if defined(MAEMO_GTK)
762 widget_class->map = hildon_banner_map;
765 /* Install properties.
766 We need construct properties for singleton purposes */
769 * HildonBanner:parent-window:
771 * The window for which the banner will be singleton.
774 g_object_class_install_property (object_class, PROP_PARENT_WINDOW,
775 g_param_spec_object ("parent-window",
777 "The window for which the banner will be singleton",
778 GTK_TYPE_WINDOW, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
781 * HildonBanner:is-timed:
783 * Whether the banner is timed and goes away automatically.
786 g_object_class_install_property (object_class, PROP_IS_TIMED,
787 g_param_spec_boolean ("is-timed",
789 "Whether or not the notification goes away automatically "
790 "after the specified time has passed",
791 FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
794 * HildonBanner:timeout:
796 * The time before destroying the banner. This needs
797 * to be adjusted before the banner is mapped to the screen.
800 g_object_class_install_property (object_class, PROP_TIMEOUT,
801 g_param_spec_uint ("timeout",
803 "The time before making the banner banner go away",
806 HILDON_BANNER_DEFAULT_TIMEOUT,
807 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
811 hildon_banner_init (HildonBanner *self)
813 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
817 priv->overrides_dnd = FALSE;
818 priv->require_override_dnd = FALSE;
819 priv->name_suffix = NULL;
821 /* Initialize the common layout inside banner */
822 priv->alignment = gtk_alignment_new (0.5, 0.5, 0, 0);
823 priv->layout = gtk_hbox_new (FALSE, HILDON_MARGIN_DEFAULT);
825 priv->label = g_object_new (GTK_TYPE_LABEL, NULL);
826 gtk_label_set_line_wrap (GTK_LABEL (priv->label), TRUE);
827 gtk_label_set_line_wrap_mode (GTK_LABEL (priv->label), PANGO_WRAP_WORD_CHAR);
828 gtk_label_set_justify (GTK_LABEL (priv->label), GTK_JUSTIFY_CENTER);
830 gtk_container_set_border_width (GTK_CONTAINER (priv->layout), HILDON_MARGIN_DEFAULT);
831 gtk_container_add (GTK_CONTAINER (self), priv->alignment);
832 gtk_container_add (GTK_CONTAINER (priv->alignment), priv->layout);
833 gtk_box_pack_start (GTK_BOX (priv->layout), priv->label, FALSE, FALSE, 0);
835 gtk_window_set_accept_focus (GTK_WINDOW (self), FALSE);
837 gtk_widget_add_events (GTK_WIDGET (self), GDK_BUTTON_PRESS_MASK);
840 /* Makes sure that icon/progress item contains the desired type
841 of item. If possible, tries to avoid creating a new widget but
842 reuses the existing one */
844 hildon_banner_ensure_child (HildonBanner *self,
845 GtkWidget *user_widget,
848 const gchar *first_property,
853 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
857 widget = priv->main_item;
858 va_start (args, first_property);
860 /* Reuse existing widget if possible */
861 if (! user_widget && G_TYPE_CHECK_INSTANCE_TYPE (widget, type))
863 g_object_set_valist (G_OBJECT (widget), first_property, args);
867 /* We have to abandon old content widget */
869 gtk_container_remove (GTK_CONTAINER (priv->layout), widget);
871 /* Use user provided widget or create a new one */
872 priv->main_item = widget = user_widget ?
873 user_widget : GTK_WIDGET (g_object_new_valist(type, first_property, args));
874 gtk_box_pack_start (GTK_BOX (priv->layout), widget, FALSE, FALSE, 0);
877 /* We make sure that the widget exists in desired position. Different
878 banners place this child widget to different places */
879 gtk_box_reorder_child (GTK_BOX (priv->layout), widget, pos);
883 /* Creates a new banner instance or uses an existing one */
885 hildon_banner_get_instance_for_widget (GtkWidget *widget,
890 window = widget ? gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW) : NULL;
891 return g_object_new (HILDON_TYPE_BANNER, "parent-window", window, "is-timed", timed, NULL);
895 * hildon_banner_show_information:
896 * @widget: the #GtkWidget that is the owner of the banner
897 * @icon_name: since Hildon 2.2 this parameter is not used anymore and
898 * any value that you pass will be ignored
899 * @text: Text to display
901 * This function creates and displays an information banner that is
902 * automatically destroyed after a certain time period (see
903 * hildon_banner_set_timeout()). For each window in your application
904 * there can only be one timed banner, so if you spawn a new banner
905 * before the earlier one has timed out, the previous one will be
908 * Returns: The newly created banner
912 hildon_banner_show_information (GtkWidget *widget,
913 const gchar *icon_name,
916 return hildon_banner_real_show_information (widget, text, FALSE);
920 * hildon_banner_show_information_override_dnd:
921 * @widget: the #GtkWidget that is the owner of the banner
922 * @text: Text to display
924 * Equivalent to hildon_banner_show_information(), but overriding the
925 * "do not disturb" flag.
927 * Returns: The newly created banner
933 hildon_banner_show_information_override_dnd (GtkWidget *widget,
936 return hildon_banner_real_show_information (widget, text, TRUE);
940 hildon_banner_set_override_flag (HildonBanner *banner)
944 gdk_property_change (GTK_WIDGET (banner)->window,
945 gdk_atom_intern_static_string ("_HILDON_DO_NOT_DISTURB_OVERRIDE"),
946 gdk_x11_xatom_to_atom (XA_INTEGER),
948 GDK_PROP_MODE_REPLACE,
949 (const guchar*) &state,
954 reshow_banner (HildonBanner *banner)
956 if (GTK_WIDGET_VISIBLE (banner)) {
957 gint width = gdk_screen_get_width (gtk_widget_get_screen (GTK_WIDGET (banner)));
958 gtk_window_resize (GTK_WINDOW (banner), width, 1);
960 force_to_wrap_truncated (banner);
961 gtk_widget_show_all (GTK_WIDGET (banner));
965 hildon_banner_real_show_information (GtkWidget *widget,
967 gboolean override_dnd)
969 HildonBanner *banner;
970 HildonBannerPrivate *priv = NULL;
972 g_return_val_if_fail (text != NULL, NULL);
975 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
976 priv = HILDON_BANNER_GET_PRIVATE (banner);
978 priv->name_suffix = "information";
979 banner_do_set_text (banner, text, FALSE);
980 hildon_banner_bind_style (banner);
983 /* so on the realize it will set the property */
984 priv->require_override_dnd = TRUE;
987 /* Show the banner, since caller cannot do that */
988 reshow_banner (banner);
990 return GTK_WIDGET (banner);
994 * hildon_banner_show_informationf:
995 * @widget: the #GtkWidget that is the owner of the banner
996 * @icon_name: since Hildon 2.2 this parameter is not used anymore and
997 * any value that you pass will be ignored
998 * @format: a printf-like format string
999 * @Varargs: arguments for the format string
1001 * A helper function for hildon_banner_show_information() with
1002 * string formatting.
1004 * Returns: the newly created banner
1007 hildon_banner_show_informationf (GtkWidget *widget,
1008 const gchar *icon_name,
1009 const gchar *format,
1012 g_return_val_if_fail (format != NULL, NULL);
1018 va_start (args, format);
1019 message = g_strdup_vprintf (format, args);
1022 banner = hildon_banner_show_information (widget, icon_name, message);
1030 * hildon_banner_show_information_with_markup:
1031 * @widget: the #GtkWidget that wants to display banner
1032 * @icon_name: since Hildon 2.2 this parameter is not used anymore and
1033 * any value that you pass will be ignored
1034 * @markup: a markup string to display (see <link linkend="PangoMarkupFormat">Pango markup format</link>)
1036 * This function creates and displays an information banner that is
1037 * automatically destroyed after certain time period (see
1038 * hildon_banner_set_timeout()). For each window in your application
1039 * there can only be one timed banner, so if you spawn a new banner
1040 * before the earlier one has timed out, the previous one will be
1043 * Returns: the newly created banner
1047 hildon_banner_show_information_with_markup (GtkWidget *widget,
1048 const gchar *icon_name,
1049 const gchar *markup)
1051 HildonBanner *banner;
1052 HildonBannerPrivate *priv;
1054 g_return_val_if_fail (icon_name == NULL || icon_name[0] != 0, NULL);
1055 g_return_val_if_fail (markup != NULL, NULL);
1057 /* Prepare banner */
1058 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
1059 priv = HILDON_BANNER_GET_PRIVATE (banner);
1061 priv->name_suffix = "information";
1062 banner_do_set_text (banner, markup, TRUE);
1063 hildon_banner_bind_style (banner);
1065 /* Show the banner, since caller cannot do that */
1066 reshow_banner (banner);
1068 return (GtkWidget *) banner;
1072 * hildon_banner_show_animation:
1073 * @widget: the #GtkWidget that wants to display banner
1074 * @animation_name: since Hildon 2.2 this parameter is not used
1075 * anymore and any value that you pass will be
1077 * @text: the text to display.
1079 * Shows an animated progress notification. It's recommended not to try
1080 * to show more than one progress notification at a time, since
1081 * they will appear on top of each other. You can use progress
1082 * notifications with timed banners. In this case the banners are
1083 * located so that you can somehow see both.
1085 * Unlike information banners (created with
1086 * hildon_banner_show_information()), animation banners are not
1087 * destroyed automatically using a timeout. You have to destroy them
1090 * Please note also that these banners are destroyed automatically if the
1091 * window they are attached to is closed. The pointer that you receive
1092 * with this function does not contain additional references, so it
1093 * can become invalid without warning (this is true for all toplevel
1094 * windows in gtk). To make sure that the banner does not disappear
1095 * automatically, you can separately ref the return value (this
1096 * doesn't prevent the banner from disappearing, just the object from
1097 * being finalized). In this case you have to call
1098 * gtk_widget_destroy() followed by g_object_unref().
1100 * Returns: a #HildonBanner widget. You must call gtk_widget_destroy()
1101 * once you are done with the banner.
1103 * Deprecated: Hildon 2.2: use
1104 * hildon_gtk_window_set_progress_indicator() instead.
1107 hildon_banner_show_animation (GtkWidget *widget,
1108 const gchar *animation_name,
1111 HildonBanner *banner;
1112 GtkWidget *image_widget;
1113 HildonBannerPrivate *priv;
1115 g_return_val_if_fail (text != NULL, NULL);
1117 image_widget = hildon_private_create_animation (
1118 HILDON_BANNER_ANIMATION_FRAMERATE,
1119 HILDON_BANNER_ANIMATION_TMPL,
1120 HILDON_BANNER_ANIMATION_NFRAMES);
1122 /* Prepare banner */
1123 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
1124 hildon_banner_ensure_child (banner, image_widget, 0,
1125 GTK_TYPE_IMAGE, "yalign", 0.0, NULL);
1127 priv = HILDON_BANNER_GET_PRIVATE (banner);
1128 priv->name_suffix = "animation";
1129 banner_do_set_text (banner, text, FALSE);
1130 hildon_banner_bind_style (banner);
1133 reshow_banner (banner);
1135 return (GtkWidget *) banner;
1139 * hildon_banner_show_progress:
1140 * @widget: the #GtkWidget that wants to display banner
1141 * @bar: since Hildon 2.2 this parameter is not used anymore and
1142 * any value that you pass will be ignored
1143 * @text: text to display.
1145 * Shows progress notification. See hildon_banner_show_animation()
1146 * for more information.
1148 * Returns: a #HildonBanner widget. You must call #gtk_widget_destroy
1149 * once you are done with the banner.
1151 * Deprecated: Hildon 2.2: use hildon_gtk_window_set_progress_indicator() instead.
1154 hildon_banner_show_progress (GtkWidget *widget,
1155 GtkProgressBar *bar,
1158 HildonBanner *banner;
1159 HildonBannerPrivate *priv;
1161 g_return_val_if_fail (text != NULL, NULL);
1163 /* Prepare banner */
1164 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
1165 priv = HILDON_BANNER_GET_PRIVATE (banner);
1168 priv->name_suffix = "progress";
1169 banner_do_set_text (banner, text, FALSE);
1170 hildon_banner_bind_style (banner);
1173 hildon_gtk_window_set_progress_indicator (priv->parent, 1);
1175 /* Show the banner */
1176 reshow_banner (banner);
1178 return GTK_WIDGET (banner);
1182 * hildon_banner_set_text:
1183 * @self: a #HildonBanner widget
1184 * @text: a new text to display in banner
1186 * Sets the text that is displayed in the banner.
1190 hildon_banner_set_text (HildonBanner *self,
1193 g_return_if_fail (HILDON_IS_BANNER (self));
1195 banner_do_set_text (self, text, FALSE);
1197 if (GTK_WIDGET_VISIBLE (self))
1198 reshow_banner (self);
1202 * hildon_banner_set_markup:
1203 * @self: a #HildonBanner widget
1204 * @markup: a new text with Pango markup to display in the banner
1206 * Sets the text with markup that is displayed in the banner.
1210 hildon_banner_set_markup (HildonBanner *self,
1211 const gchar *markup)
1213 g_return_if_fail (HILDON_IS_BANNER (self));
1215 banner_do_set_text (self, markup, TRUE);
1217 if (GTK_WIDGET_VISIBLE (self))
1218 reshow_banner (self);
1222 * hildon_banner_set_fraction:
1223 * @self: a #HildonBanner widget
1224 * @fraction: #gdouble
1226 * The fraction is the completion of progressbar,
1227 * the scale is from 0.0 to 1.0.
1228 * Sets the amount of fraction the progressbar has.
1230 * Note that this method only has effect if @self was created with
1231 * hildon_banner_show_progress()
1233 * Deprecated: This function does nothing. As of Hildon 2.2, hildon
1234 * banners don't have progress bars.
1237 hildon_banner_set_fraction (HildonBanner *self,
1243 * hildon_banner_set_timeout:
1244 * @self: a #HildonBanner widget
1245 * @timeout: timeout to set in miliseconds.
1247 * Sets the timeout on the banner. After the given amount of miliseconds
1248 * has elapsed the banner will be destroyed. Setting this only makes
1249 * sense on banners that are timed and that have not been yet displayed
1252 * Note that this method only has effect if @self is an information
1253 * banner (created using hildon_banner_show_information() and
1257 hildon_banner_set_timeout (HildonBanner *self,
1260 HildonBannerPrivate *priv;
1262 g_return_if_fail (HILDON_IS_BANNER (self));
1263 priv = HILDON_BANNER_GET_PRIVATE (self);
1266 priv->timeout = timeout;
1270 * hildon_banner_set_icon:
1271 * @self: a #HildonBanner widget
1272 * @icon_name: the name of icon to use. Can be %NULL for default icon
1274 * Sets the icon to be used in the banner.
1276 * Deprecated: This function does nothing. As of hildon 2.2, hildon
1277 * banners don't allow changing their icons.
1280 hildon_banner_set_icon (HildonBanner *self,
1281 const gchar *icon_name)
1286 * hildon_banner_set_icon_from_file:
1287 * @self: a #HildonBanner widget
1288 * @icon_file: the filename of icon to use. Can be %NULL for default icon
1290 * Sets the icon from its filename to be used in the banner.
1292 * Deprecated: This function does nothing. As of hildon 2.2, hildon
1293 * banners don't allow changing their icons.
1296 hildon_banner_set_icon_from_file (HildonBanner *self,
1297 const gchar *icon_file)