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 priv->timeout_id = 0;
310 gtk_widget_destroy (widget);
313 g_object_unref (widget);
315 return continue_timeout;
319 hildon_banner_clear_timeout (HildonBanner *self)
321 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
324 if (priv->timeout_id != 0) {
325 g_source_remove (priv->timeout_id);
326 priv->timeout_id = 0;
334 hildon_banner_ensure_timeout (HildonBanner *self)
336 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
339 if (priv->timeout_id == 0 && priv->is_timed && priv->timeout > 0)
340 priv->timeout_id = gdk_threads_add_timeout (priv->timeout,
341 hildon_banner_timeout, self);
345 hildon_banner_set_property (GObject *object,
351 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
357 priv->timeout = g_value_get_uint (value);
361 priv->is_timed = g_value_get_boolean (value);
364 case PROP_PARENT_WINDOW:
365 window = g_value_get_object (value);
367 g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent);
370 gtk_window_set_transient_for (GTK_WINDOW (object), (GtkWindow *) window);
371 priv->parent = (GtkWindow *) window;
374 gtk_window_set_destroy_with_parent (GTK_WINDOW (object), TRUE);
375 g_object_add_weak_pointer(G_OBJECT (window), (gpointer) &priv->parent);
381 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
387 hildon_banner_get_property (GObject *object,
392 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
398 g_value_set_uint (value, priv->timeout);
402 g_value_set_boolean (value, priv->is_timed);
405 case PROP_PARENT_WINDOW:
406 g_value_set_object (value, gtk_window_get_transient_for (GTK_WINDOW (object)));
410 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
416 hildon_banner_destroy (GtkObject *object)
418 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
422 GObject *parent_window = (GObject *) priv->parent;
424 g_assert (HILDON_IS_BANNER (object));
425 self = HILDON_BANNER (object);
427 /* Drop possible global pointer. That can hold reference to us */
428 if ((gpointer) object == (gpointer) global_timed_banner) {
429 global_timed_banner = NULL;
430 g_object_unref (object);
433 /* Remove the data from parent window for timed banners. Those hold reference */
434 if (priv->is_timed && parent_window != NULL) {
435 g_object_set_qdata (parent_window, hildon_banner_timed_quark (), NULL);
438 if (!priv->is_timed && priv->parent) {
439 hildon_gtk_window_set_progress_indicator (priv->parent, 0);
442 (void) hildon_banner_clear_timeout (self);
444 if (GTK_OBJECT_CLASS (hildon_banner_parent_class)->destroy)
445 GTK_OBJECT_CLASS (hildon_banner_parent_class)->destroy (object);
448 /* Search a previous banner instance */
450 hildon_banner_real_get_instance (GObject *window,
454 /* If we have a parent window, the previous instance is stored there */
456 return g_object_get_qdata(window, hildon_banner_timed_quark ());
459 /* System notification instance is stored into global pointer */
460 return (GObject *) global_timed_banner;
463 /* Non-timed banners are normal (non-singleton) objects */
467 /* By overriding constructor we force timed banners to be
468 singletons for each window */
470 hildon_banner_constructor (GType type,
471 guint n_construct_params,
472 GObjectConstructParam *construct_params)
474 GObject *banner, *window = NULL;
475 gboolean timed = FALSE;
478 /* Search banner type information from parameters in order
479 to locate the possible previous banner instance. */
480 for (i = 0; i < n_construct_params; i++)
482 if (strcmp(construct_params[i].pspec->name, "parent-window") == 0)
483 window = g_value_get_object (construct_params[i].value);
484 else if (strcmp(construct_params[i].pspec->name, "is-timed") == 0)
485 timed = g_value_get_boolean (construct_params[i].value);
488 /* Try to get a previous instance if such exists */
489 banner = hildon_banner_real_get_instance (window, timed);
492 /* We have to create a new banner */
493 banner = G_OBJECT_CLASS (hildon_banner_parent_class)->constructor (type, n_construct_params, construct_params);
495 /* Store the newly created singleton instance either into parent
496 window data or into global variables. */
499 g_object_set_qdata_full (G_OBJECT (window), hildon_banner_timed_quark (),
500 g_object_ref (banner), g_object_unref);
502 g_assert (global_timed_banner == NULL);
503 global_timed_banner = g_object_ref (banner);
508 /* FIXME: This is a hack! We have to manually freeze
509 notifications. This is normally done by g_object_init, but we
510 are not going to call that. g_object_newv will otherwise give
511 a critical like this:
513 GLIB CRITICAL ** GLib-GObject - g_object_notify_queue_thaw:
514 assertion `nqueue->freeze_count > 0' failed */
516 g_object_freeze_notify (banner);
519 /* We restart possible timeouts for each new timed banner request */
520 if (timed && hildon_banner_clear_timeout (HILDON_BANNER (banner)))
521 hildon_banner_ensure_timeout (HILDON_BANNER(banner));
527 hildon_banner_finalize (GObject *object)
529 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
532 g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent);
535 G_OBJECT_CLASS (hildon_banner_parent_class)->finalize (object);
539 hildon_banner_button_press_event (GtkWidget* widget,
540 GdkEventButton* event)
542 gboolean result = simulate_close (widget);
545 /* signal emission not stopped - basically behave like
546 * gtk_main_do_event() for a delete event, but just hide the
547 * banner instead of destroying it, as it is already meant to
548 * be destroyed by hildon_banner_timeout() (if it's timed) or
549 * the application (if it's not). */
550 gtk_widget_hide (widget);
556 #if defined(MAEMO_GTK)
558 hildon_banner_map (GtkWidget *widget)
560 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->map) {
561 /* Make the banner temporary _before_ mapping it, to avoid closing
562 * other temporary windows */
563 gtk_window_set_is_temporary (GTK_WINDOW (widget), TRUE);
565 GTK_WIDGET_CLASS (hildon_banner_parent_class)->map (widget);
567 /* Make the banner non-temporary _after_ mapping it, to avoid
568 * being closed by other non-temporary windows */
569 gtk_window_set_is_temporary (GTK_WINDOW (widget), FALSE);
571 gtk_window_move (GTK_WINDOW (widget), 0, HILDON_WINDOW_TITLEBAR_HEIGHT);
576 /* We start the timer for timed notifications after the window appears on screen */
578 hildon_banner_map_event (GtkWidget *widget,
581 gboolean result = FALSE;
583 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->map_event)
584 result = GTK_WIDGET_CLASS (hildon_banner_parent_class)->map_event (widget, event);
586 hildon_banner_ensure_timeout (HILDON_BANNER(widget));
592 banner_do_set_text (HildonBanner *banner,
596 HildonBannerPrivate *priv;
599 priv = HILDON_BANNER_GET_PRIVATE (banner);
602 gtk_label_set_markup (GTK_LABEL (priv->label), text);
604 gtk_label_set_text (GTK_LABEL (priv->label), text);
606 gtk_widget_set_size_request (priv->label, -1, -1);
607 gtk_widget_size_request (priv->label, &req);
609 force_to_wrap_truncated (banner);
612 /* force to wrap truncated label by setting explicit size request
613 * see N#27000 and G#329646 */
615 force_to_wrap_truncated (HildonBanner *banner)
622 PangoRectangle logical;
623 GtkRequisition requisition;
624 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (banner);
626 g_return_if_fail (priv);
628 label = GTK_LABEL (priv->label);
630 layout = gtk_label_get_layout (label);
632 pango_layout_get_extents (layout, NULL, &logical);
633 width = PANGO_PIXELS (logical.width);
635 width_max = priv->is_timed ? HILDON_BANNER_LABEL_MAX_TIMED
636 : HILDON_BANNER_LABEL_MAX_PROGRESS;
638 /* If the width of the label is going to exceed the maximum allowed
639 * width, enforce the maximum allowed width now.
641 if (width >= width_max || pango_layout_is_wrapped (layout)) {
645 /* Make the label update its layout; and update our layout pointer
646 * because the layout will be cleared and refreshed.
648 gtk_widget_set_size_request (GTK_WIDGET (label), width, height);
649 gtk_widget_size_request (GTK_WIDGET (label), &requisition);
651 layout = gtk_label_get_layout (label);
653 /* If the layout has now been wrapped and exceeds 3 lines, we truncate
654 * the rest of the label according to spec.
656 if (pango_layout_is_wrapped (layout) && pango_layout_get_line_count (layout) > 3) {
659 pango_layout_get_extents (layout, NULL, &logical);
660 lines = pango_layout_get_line_count (layout);
662 /* This calculation assumes that the same font is used
663 * throughout the banner -- this is usually the case on maemo
665 * FIXME: Pango >= 1.20 has pango_layout_set_height().
667 height = (PANGO_PIXELS (logical.height) * 3) / lines + 1;
670 /* Set the new width/height if applicable */
671 gtk_widget_set_size_request (GTK_WIDGET (label), width, height);
675 screen_size_changed (GdkScreen *screen,
679 HildonBanner *hbanner = HILDON_BANNER (banner);
680 hildon_banner_bind_style (hbanner);
681 reshow_banner (hbanner);
685 hildon_banner_realize (GtkWidget *widget)
690 guint32 portrait = 1;
691 const gchar *notification_type = "_HILDON_NOTIFICATION_TYPE_BANNER";
692 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (widget);
695 /* We let the parent to init widget->window before we need it */
696 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->realize)
697 GTK_WIDGET_CLASS (hildon_banner_parent_class)->realize (widget);
699 /* We use special hint to turn the banner into information notification. */
700 gdk_window_set_type_hint (widget->window, GDK_WINDOW_TYPE_HINT_NOTIFICATION);
701 gtk_window_set_transient_for (GTK_WINDOW (widget), (GtkWindow *) priv->parent);
703 gdkwin = widget->window;
705 /* Set the _HILDON_NOTIFICATION_TYPE property so Matchbox places the window correctly */
706 atom = gdk_atom_intern ("_HILDON_NOTIFICATION_TYPE", FALSE);
707 gdk_property_change (gdkwin, atom, gdk_x11_xatom_to_atom (XA_STRING), 8, GDK_PROP_MODE_REPLACE,
708 (gpointer) notification_type, strlen (notification_type));
710 /* HildonBanner supports portrait mode */
711 atom = gdk_atom_intern ("_HILDON_PORTRAIT_MODE_SUPPORT", FALSE);
712 gdk_property_change (gdkwin, atom, gdk_x11_xatom_to_atom (XA_CARDINAL), 32,
713 GDK_PROP_MODE_REPLACE, (gpointer) &portrait, 1);
715 /* Manage override flag */
716 if ((priv->require_override_dnd)&&(!priv->overrides_dnd)) {
717 hildon_banner_set_override_flag (HILDON_BANNER (widget));
718 priv->overrides_dnd = TRUE;
721 screen = gtk_widget_get_screen (widget);
722 g_signal_connect (screen, "size-changed", G_CALLBACK (screen_size_changed), widget);
726 hildon_banner_unrealize (GtkWidget *widget)
728 GdkScreen *screen = gtk_widget_get_screen (widget);
729 g_signal_handlers_disconnect_by_func (screen, G_CALLBACK (screen_size_changed), widget);
731 GTK_WIDGET_CLASS (hildon_banner_parent_class)->unrealize (widget);
735 hildon_banner_class_init (HildonBannerClass *klass)
737 GObjectClass *object_class;
738 GtkWidgetClass *widget_class;
740 object_class = G_OBJECT_CLASS (klass);
741 widget_class = GTK_WIDGET_CLASS (klass);
743 /* Append private structure to class. This is more elegant than
744 on g_new based approach */
745 g_type_class_add_private (klass, sizeof (HildonBannerPrivate));
747 /* Override virtual methods */
748 object_class->constructor = hildon_banner_constructor;
749 object_class->finalize = hildon_banner_finalize;
750 object_class->set_property = hildon_banner_set_property;
751 object_class->get_property = hildon_banner_get_property;
752 GTK_OBJECT_CLASS (klass)->destroy = hildon_banner_destroy;
753 widget_class->size_request = hildon_banner_size_request;
754 widget_class->map_event = hildon_banner_map_event;
755 widget_class->realize = hildon_banner_realize;
756 widget_class->unrealize = hildon_banner_unrealize;
757 widget_class->button_press_event = hildon_banner_button_press_event;
758 #if defined(MAEMO_GTK)
759 widget_class->map = hildon_banner_map;
762 /* Install properties.
763 We need construct properties for singleton purposes */
766 * HildonBanner:parent-window:
768 * The window for which the banner will be singleton.
771 g_object_class_install_property (object_class, PROP_PARENT_WINDOW,
772 g_param_spec_object ("parent-window",
774 "The window for which the banner will be singleton",
775 GTK_TYPE_WINDOW, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
778 * HildonBanner:is-timed:
780 * Whether the banner is timed and goes away automatically.
783 g_object_class_install_property (object_class, PROP_IS_TIMED,
784 g_param_spec_boolean ("is-timed",
786 "Whether or not the notification goes away automatically "
787 "after the specified time has passed",
788 FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
791 * HildonBanner:timeout:
793 * The time before destroying the banner. This needs
794 * to be adjusted before the banner is mapped to the screen.
797 g_object_class_install_property (object_class, PROP_TIMEOUT,
798 g_param_spec_uint ("timeout",
800 "The time before making the banner banner go away",
803 HILDON_BANNER_DEFAULT_TIMEOUT,
804 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
808 hildon_banner_init (HildonBanner *self)
810 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
814 priv->overrides_dnd = FALSE;
815 priv->require_override_dnd = FALSE;
816 priv->name_suffix = NULL;
818 /* Initialize the common layout inside banner */
819 priv->alignment = gtk_alignment_new (0.5, 0.5, 0, 0);
820 priv->layout = gtk_hbox_new (FALSE, HILDON_MARGIN_DEFAULT);
822 priv->label = g_object_new (GTK_TYPE_LABEL, NULL);
823 gtk_label_set_line_wrap (GTK_LABEL (priv->label), TRUE);
824 gtk_label_set_line_wrap_mode (GTK_LABEL (priv->label), PANGO_WRAP_WORD_CHAR);
825 gtk_label_set_justify (GTK_LABEL (priv->label), GTK_JUSTIFY_CENTER);
827 gtk_container_set_border_width (GTK_CONTAINER (priv->layout), HILDON_MARGIN_DEFAULT);
828 gtk_container_add (GTK_CONTAINER (self), priv->alignment);
829 gtk_container_add (GTK_CONTAINER (priv->alignment), priv->layout);
830 gtk_box_pack_start (GTK_BOX (priv->layout), priv->label, FALSE, FALSE, 0);
832 gtk_window_set_accept_focus (GTK_WINDOW (self), FALSE);
834 gtk_widget_add_events (GTK_WIDGET (self), GDK_BUTTON_PRESS_MASK);
837 /* Makes sure that icon/progress item contains the desired type
838 of item. If possible, tries to avoid creating a new widget but
839 reuses the existing one */
841 hildon_banner_ensure_child (HildonBanner *self,
842 GtkWidget *user_widget,
845 const gchar *first_property,
850 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
854 widget = priv->main_item;
855 va_start (args, first_property);
857 /* Reuse existing widget if possible */
858 if (! user_widget && G_TYPE_CHECK_INSTANCE_TYPE (widget, type))
860 g_object_set_valist (G_OBJECT (widget), first_property, args);
864 /* We have to abandon old content widget */
866 gtk_container_remove (GTK_CONTAINER (priv->layout), widget);
868 /* Use user provided widget or create a new one */
869 priv->main_item = widget = user_widget ?
870 user_widget : GTK_WIDGET (g_object_new_valist(type, first_property, args));
871 gtk_box_pack_start (GTK_BOX (priv->layout), widget, FALSE, FALSE, 0);
874 /* We make sure that the widget exists in desired position. Different
875 banners place this child widget to different places */
876 gtk_box_reorder_child (GTK_BOX (priv->layout), widget, pos);
880 /* Creates a new banner instance or uses an existing one */
882 hildon_banner_get_instance_for_widget (GtkWidget *widget,
887 window = widget ? gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW) : NULL;
888 return g_object_new (HILDON_TYPE_BANNER, "parent-window", window, "is-timed", timed, NULL);
892 * hildon_banner_show_information:
893 * @widget: the #GtkWidget that is the owner of the banner
894 * @icon_name: since Hildon 2.2 this parameter is not used anymore and
895 * any value that you pass will be ignored
896 * @text: Text to display
898 * This function creates and displays an information banner that is
899 * automatically destroyed after a certain time period (see
900 * hildon_banner_set_timeout()). For each window in your application
901 * there can only be one timed banner, so if you spawn a new banner
902 * before the earlier one has timed out, the previous one will be
905 * Returns: The newly created banner
909 hildon_banner_show_information (GtkWidget *widget,
910 const gchar *icon_name,
913 return hildon_banner_real_show_information (widget, text, FALSE);
917 * hildon_banner_show_information_override_dnd:
918 * @widget: the #GtkWidget that is the owner of the banner
919 * @text: Text to display
921 * Equivalent to hildon_banner_show_information(), but overriding the
922 * "do not disturb" flag.
924 * Returns: The newly created banner
930 hildon_banner_show_information_override_dnd (GtkWidget *widget,
933 return hildon_banner_real_show_information (widget, text, TRUE);
937 hildon_banner_set_override_flag (HildonBanner *banner)
941 gdk_property_change (GTK_WIDGET (banner)->window,
942 gdk_atom_intern_static_string ("_HILDON_DO_NOT_DISTURB_OVERRIDE"),
943 gdk_x11_xatom_to_atom (XA_INTEGER),
945 GDK_PROP_MODE_REPLACE,
946 (const guchar*) &state,
951 reshow_banner (HildonBanner *banner)
953 if (GTK_WIDGET_VISIBLE (banner)) {
954 gint width = gdk_screen_get_width (gtk_widget_get_screen (GTK_WIDGET (banner)));
955 gtk_window_resize (GTK_WINDOW (banner), width, 1);
957 force_to_wrap_truncated (banner);
958 gtk_widget_show_all (GTK_WIDGET (banner));
962 hildon_banner_real_show_information (GtkWidget *widget,
964 gboolean override_dnd)
966 HildonBanner *banner;
967 HildonBannerPrivate *priv = NULL;
969 g_return_val_if_fail (text != NULL, NULL);
972 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
973 priv = HILDON_BANNER_GET_PRIVATE (banner);
975 priv->name_suffix = "information";
976 banner_do_set_text (banner, text, FALSE);
977 hildon_banner_bind_style (banner);
980 /* so on the realize it will set the property */
981 priv->require_override_dnd = TRUE;
984 /* Show the banner, since caller cannot do that */
985 reshow_banner (banner);
987 return GTK_WIDGET (banner);
991 * hildon_banner_show_informationf:
992 * @widget: the #GtkWidget that is the owner of the banner
993 * @icon_name: since Hildon 2.2 this parameter is not used anymore and
994 * any value that you pass will be ignored
995 * @format: a printf-like format string
996 * @Varargs: arguments for the format string
998 * A helper function for hildon_banner_show_information() with
1001 * Returns: the newly created banner
1004 hildon_banner_show_informationf (GtkWidget *widget,
1005 const gchar *icon_name,
1006 const gchar *format,
1009 g_return_val_if_fail (format != NULL, NULL);
1015 va_start (args, format);
1016 message = g_strdup_vprintf (format, args);
1019 banner = hildon_banner_show_information (widget, icon_name, message);
1027 * hildon_banner_show_information_with_markup:
1028 * @widget: the #GtkWidget that wants to display banner
1029 * @icon_name: since Hildon 2.2 this parameter is not used anymore and
1030 * any value that you pass will be ignored
1031 * @markup: a markup string to display (see <link linkend="PangoMarkupFormat">Pango markup format</link>)
1033 * This function creates and displays an information banner that is
1034 * automatically destroyed after certain time period (see
1035 * hildon_banner_set_timeout()). For each window in your application
1036 * there can only be one timed banner, so if you spawn a new banner
1037 * before the earlier one has timed out, the previous one will be
1040 * Returns: the newly created banner
1044 hildon_banner_show_information_with_markup (GtkWidget *widget,
1045 const gchar *icon_name,
1046 const gchar *markup)
1048 HildonBanner *banner;
1049 HildonBannerPrivate *priv;
1051 g_return_val_if_fail (icon_name == NULL || icon_name[0] != 0, NULL);
1052 g_return_val_if_fail (markup != NULL, NULL);
1054 /* Prepare banner */
1055 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
1056 priv = HILDON_BANNER_GET_PRIVATE (banner);
1058 priv->name_suffix = "information";
1059 banner_do_set_text (banner, markup, TRUE);
1060 hildon_banner_bind_style (banner);
1062 /* Show the banner, since caller cannot do that */
1063 reshow_banner (banner);
1065 return (GtkWidget *) banner;
1069 * hildon_banner_show_animation:
1070 * @widget: the #GtkWidget that wants to display banner
1071 * @animation_name: since Hildon 2.2 this parameter is not used
1072 * anymore and any value that you pass will be
1074 * @text: the text to display.
1076 * Shows an animated progress notification. It's recommended not to try
1077 * to show more than one progress notification at a time, since
1078 * they will appear on top of each other. You can use progress
1079 * notifications with timed banners. In this case the banners are
1080 * located so that you can somehow see both.
1082 * Unlike information banners (created with
1083 * hildon_banner_show_information()), animation banners are not
1084 * destroyed automatically using a timeout. You have to destroy them
1087 * Please note also that these banners are destroyed automatically if the
1088 * window they are attached to is closed. The pointer that you receive
1089 * with this function does not contain additional references, so it
1090 * can become invalid without warning (this is true for all toplevel
1091 * windows in gtk). To make sure that the banner does not disappear
1092 * automatically, you can separately ref the return value (this
1093 * doesn't prevent the banner from disappearing, just the object from
1094 * being finalized). In this case you have to call
1095 * gtk_widget_destroy() followed by g_object_unref().
1097 * Returns: a #HildonBanner widget. You must call gtk_widget_destroy()
1098 * once you are done with the banner.
1100 * Deprecated: Hildon 2.2: use
1101 * hildon_gtk_window_set_progress_indicator() instead.
1104 hildon_banner_show_animation (GtkWidget *widget,
1105 const gchar *animation_name,
1108 HildonBanner *banner;
1109 GtkWidget *image_widget;
1110 HildonBannerPrivate *priv;
1112 g_return_val_if_fail (text != NULL, NULL);
1114 image_widget = hildon_private_create_animation (
1115 HILDON_BANNER_ANIMATION_FRAMERATE,
1116 HILDON_BANNER_ANIMATION_TMPL,
1117 HILDON_BANNER_ANIMATION_NFRAMES);
1119 /* Prepare banner */
1120 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
1121 hildon_banner_ensure_child (banner, image_widget, 0,
1122 GTK_TYPE_IMAGE, "yalign", 0.0, NULL);
1124 priv = HILDON_BANNER_GET_PRIVATE (banner);
1125 priv->name_suffix = "animation";
1126 banner_do_set_text (banner, text, FALSE);
1127 hildon_banner_bind_style (banner);
1130 reshow_banner (banner);
1132 return (GtkWidget *) banner;
1136 * hildon_banner_show_progress:
1137 * @widget: the #GtkWidget that wants to display banner
1138 * @bar: since Hildon 2.2 this parameter is not used anymore and
1139 * any value that you pass will be ignored
1140 * @text: text to display.
1142 * Shows progress notification. See hildon_banner_show_animation()
1143 * for more information.
1145 * Returns: a #HildonBanner widget. You must call #gtk_widget_destroy
1146 * once you are done with the banner.
1148 * Deprecated: Hildon 2.2: use hildon_gtk_window_set_progress_indicator() instead.
1151 hildon_banner_show_progress (GtkWidget *widget,
1152 GtkProgressBar *bar,
1155 HildonBanner *banner;
1156 HildonBannerPrivate *priv;
1158 g_return_val_if_fail (text != NULL, NULL);
1160 /* Prepare banner */
1161 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
1162 priv = HILDON_BANNER_GET_PRIVATE (banner);
1165 priv->name_suffix = "progress";
1166 banner_do_set_text (banner, text, FALSE);
1167 hildon_banner_bind_style (banner);
1170 hildon_gtk_window_set_progress_indicator (priv->parent, 1);
1172 /* Show the banner */
1173 reshow_banner (banner);
1175 return GTK_WIDGET (banner);
1179 * hildon_banner_set_text:
1180 * @self: a #HildonBanner widget
1181 * @text: a new text to display in banner
1183 * Sets the text that is displayed in the banner.
1187 hildon_banner_set_text (HildonBanner *self,
1190 g_return_if_fail (HILDON_IS_BANNER (self));
1192 banner_do_set_text (self, text, FALSE);
1194 if (GTK_WIDGET_VISIBLE (self))
1195 reshow_banner (self);
1199 * hildon_banner_set_markup:
1200 * @self: a #HildonBanner widget
1201 * @markup: a new text with Pango markup to display in the banner
1203 * Sets the text with markup that is displayed in the banner.
1207 hildon_banner_set_markup (HildonBanner *self,
1208 const gchar *markup)
1210 g_return_if_fail (HILDON_IS_BANNER (self));
1212 banner_do_set_text (self, markup, TRUE);
1214 if (GTK_WIDGET_VISIBLE (self))
1215 reshow_banner (self);
1219 * hildon_banner_set_fraction:
1220 * @self: a #HildonBanner widget
1221 * @fraction: #gdouble
1223 * The fraction is the completion of progressbar,
1224 * the scale is from 0.0 to 1.0.
1225 * Sets the amount of fraction the progressbar has.
1227 * Note that this method only has effect if @self was created with
1228 * hildon_banner_show_progress()
1230 * Deprecated: This function does nothing. As of Hildon 2.2, hildon
1231 * banners don't have progress bars.
1234 hildon_banner_set_fraction (HildonBanner *self,
1240 * hildon_banner_set_timeout:
1241 * @self: a #HildonBanner widget
1242 * @timeout: timeout to set in miliseconds.
1244 * Sets the timeout on the banner. After the given amount of miliseconds
1245 * has elapsed the banner will be destroyed. Setting this only makes
1246 * sense on banners that are timed and that have not been yet displayed
1249 * Note that this method only has effect if @self is an information
1250 * banner (created using hildon_banner_show_information() and
1254 hildon_banner_set_timeout (HildonBanner *self,
1257 HildonBannerPrivate *priv;
1259 g_return_if_fail (HILDON_IS_BANNER (self));
1260 priv = HILDON_BANNER_GET_PRIVATE (self);
1263 priv->timeout = timeout;
1267 * hildon_banner_set_icon:
1268 * @self: a #HildonBanner widget
1269 * @icon_name: the name of icon to use. Can be %NULL for default icon
1271 * Sets the icon to be used in the banner.
1273 * Deprecated: This function does nothing. As of hildon 2.2, hildon
1274 * banners don't allow changing their icons.
1277 hildon_banner_set_icon (HildonBanner *self,
1278 const gchar *icon_name)
1283 * hildon_banner_set_icon_from_file:
1284 * @self: a #HildonBanner widget
1285 * @icon_file: the filename of icon to use. Can be %NULL for default icon
1287 * Sets the icon from its filename to be used in the banner.
1289 * Deprecated: This function does nothing. As of hildon 2.2, hildon
1290 * banners don't allow changing their icons.
1293 hildon_banner_set_icon_from_file (HildonBanner *self,
1294 const gchar *icon_file)