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 dissapear automatically 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.
66 #include <X11/Xatom.h>
69 #undef HILDON_DISABLE_DEPRECATED
71 #include "hildon-banner.h"
72 #include "hildon-banner-private.h"
73 #include "hildon-defines.h"
74 #include "hildon-gtk.h"
76 /* position relative to the screen */
78 #define HILDON_BANNER_WINDOW_X 0
80 #define HILDON_BANNER_WINDOW_Y HILDON_WINDOW_TITLEBAR_HEIGHT
84 #define HILDON_BANNER_LABEL_MAX_TIMED \
85 (gdk_screen_width() - ((HILDON_MARGIN_TRIPLE) * 2))
87 #define HILDON_BANNER_LABEL_MAX_PROGRESS 375 /*265*/
91 #define HILDON_BANNER_DEFAULT_TIMEOUT 3000
95 #define HILDON_BANNER_DEFAULT_PROGRESS_ANIMATION "indicator_update"
97 /* animation related stuff */
99 #define HILDON_BANNER_ANIMATION_FRAMERATE ((float)1000/150)
101 #define HILDON_BANNER_ANIMATION_TMPL "indicator_update%d"
103 #define HILDON_BANNER_ANIMATION_NFRAMES 8
113 static GtkWidget* global_timed_banner = NULL;
116 hildon_banner_timed_quark (void);
119 hildon_banner_bind_style (HildonBanner *self,
123 hildon_banner_timeout (gpointer data);
126 hildon_banner_clear_timeout (HildonBanner *self);
129 hildon_banner_ensure_timeout (HildonBanner *self);
132 hildon_banner_set_property (GObject *object,
138 hildon_banner_get_property (GObject *object,
144 hildon_banner_destroy (GtkObject *object);
147 hildon_banner_real_get_instance (GObject *window,
151 hildon_banner_constructor (GType type,
152 guint n_construct_params,
153 GObjectConstructParam *construct_params);
156 hildon_banner_finalize (GObject *object);
159 hildon_banner_button_press_event (GtkWidget* widget,
160 GdkEventButton* event);
163 hildon_banner_map_event (GtkWidget *widget,
166 hildon_banner_reset_wrap_state (HildonBanner *banner);
169 force_to_wrap_truncated (HildonBanner *banner);
172 hildon_banner_check_position (GtkWidget *widget);
175 hildon_banner_realize (GtkWidget *widget);
178 hildon_banner_class_init (HildonBannerClass *klass);
181 hildon_banner_init (HildonBanner *self);
184 hildon_banner_ensure_child (HildonBanner *self,
185 GtkWidget *user_widget,
188 const gchar *first_property,
192 hildon_banner_get_instance_for_widget (GtkWidget *widget,
196 hildon_banner_set_override_flag (HildonBanner *banner);
199 hildon_banner_real_show_information (GtkWidget *widget,
201 gboolean override_dnd);
204 G_DEFINE_TYPE (HildonBanner, hildon_banner, GTK_TYPE_WINDOW)
207 hildon_banner_timed_quark (void)
209 static GQuark quark = 0;
211 if (G_UNLIKELY(quark == 0))
212 quark = g_quark_from_static_string ("hildon-banner-timed");
217 /* Set the widget and label name to make the correct rc-style attached into them */
219 hildon_banner_bind_style (HildonBanner *self,
220 const gchar *name_sufix)
222 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
227 name = g_strconcat ("HildonBannerLabel-", name_sufix, NULL);
228 gtk_widget_set_name (priv->label, name);
231 name = g_strconcat ("HildonBanner-", name_sufix, NULL);
232 gtk_widget_set_name (GTK_WIDGET (self), name);
236 /* In timeout function we automatically destroy timed banners */
238 simulate_close (GtkWidget* widget)
240 gboolean result = FALSE;
242 /* If the banner is currently visible (it normally should),
243 we simulate clicking the close button of the window.
244 This allows applications to reuse the banner by prevent
246 if (GTK_WIDGET_DRAWABLE (widget))
248 GdkEvent *event = gdk_event_new (GDK_DELETE);
249 event->any.window = g_object_ref (widget->window);
250 event->any.send_event = FALSE;
251 result = gtk_widget_event (widget, event);
252 gdk_event_free (event);
259 hildon_banner_timeout (gpointer data)
262 gboolean continue_timeout = FALSE;
264 GDK_THREADS_ENTER ();
266 g_assert (HILDON_IS_BANNER (data));
268 widget = GTK_WIDGET (data);
269 g_object_ref (widget);
271 continue_timeout = simulate_close (widget);
273 if (! continue_timeout) {
274 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (data);
275 priv->timeout_id = 0;
276 gtk_widget_destroy (widget);
279 g_object_unref (widget);
281 GDK_THREADS_LEAVE ();
283 return continue_timeout;
287 hildon_banner_clear_timeout (HildonBanner *self)
289 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
292 if (priv->timeout_id != 0) {
293 g_source_remove (priv->timeout_id);
294 priv->timeout_id = 0;
302 hildon_banner_ensure_timeout (HildonBanner *self)
304 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
307 if (priv->timeout_id == 0 && priv->is_timed && priv->timeout > 0)
308 priv->timeout_id = g_timeout_add (priv->timeout,
309 hildon_banner_timeout, self);
313 hildon_banner_set_property (GObject *object,
319 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
325 priv->timeout = g_value_get_uint (value);
329 priv->is_timed = g_value_get_boolean (value);
332 case PROP_PARENT_WINDOW:
333 window = g_value_get_object (value);
335 g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent);
338 gtk_window_set_transient_for (GTK_WINDOW (object), (GtkWindow *) window);
339 priv->parent = (GtkWindow *) window;
342 gtk_window_set_destroy_with_parent (GTK_WINDOW (object), TRUE);
343 g_object_add_weak_pointer(G_OBJECT (window), (gpointer) &priv->parent);
349 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
355 hildon_banner_get_property (GObject *object,
360 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
366 g_value_set_uint (value, priv->timeout);
370 g_value_set_boolean (value, priv->is_timed);
373 case PROP_PARENT_WINDOW:
374 g_value_set_object (value, gtk_window_get_transient_for (GTK_WINDOW (object)));
378 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
384 hildon_banner_destroy (GtkObject *object)
386 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
390 GObject *parent_window = (GObject *) priv->parent;
392 g_assert (HILDON_IS_BANNER (object));
393 self = HILDON_BANNER (object);
395 /* Drop possible global pointer. That can hold reference to us */
396 if ((gpointer) object == (gpointer) global_timed_banner) {
397 global_timed_banner = NULL;
398 g_object_unref (object);
401 /* Remove the data from parent window for timed banners. Those hold reference */
402 if (priv->is_timed && parent_window != NULL) {
403 g_object_set_qdata (parent_window, hildon_banner_timed_quark (), NULL);
406 if (!priv->is_timed && priv->parent) {
407 hildon_gtk_window_set_progress_indicator (priv->parent, 0);
410 (void) hildon_banner_clear_timeout (self);
412 if (GTK_OBJECT_CLASS (hildon_banner_parent_class)->destroy)
413 GTK_OBJECT_CLASS (hildon_banner_parent_class)->destroy (object);
416 /* Search a previous banner instance */
418 hildon_banner_real_get_instance (GObject *window,
422 /* If we have a parent window, the previous instance is stored there */
424 return g_object_get_qdata(window, hildon_banner_timed_quark ());
427 /* System notification instance is stored into global pointer */
428 return (GObject *) global_timed_banner;
431 /* Non-timed banners are normal (non-singleton) objects */
435 /* By overriding constructor we force timed banners to be
436 singletons for each window */
438 hildon_banner_constructor (GType type,
439 guint n_construct_params,
440 GObjectConstructParam *construct_params)
442 GObject *banner, *window = NULL;
443 gboolean timed = FALSE;
446 /* Search banner type information from parameters in order
447 to locate the possible previous banner instance. */
448 for (i = 0; i < n_construct_params; i++)
450 if (strcmp(construct_params[i].pspec->name, "parent-window") == 0)
451 window = g_value_get_object (construct_params[i].value);
452 else if (strcmp(construct_params[i].pspec->name, "is-timed") == 0)
453 timed = g_value_get_boolean (construct_params[i].value);
456 /* Try to get a previous instance if such exists */
457 banner = hildon_banner_real_get_instance (window, timed);
460 /* We have to create a new banner */
461 banner = G_OBJECT_CLASS (hildon_banner_parent_class)->constructor (type, n_construct_params, construct_params);
463 /* Store the newly created singleton instance either into parent
464 window data or into global variables. */
467 g_object_set_qdata_full (G_OBJECT (window), hildon_banner_timed_quark (),
468 g_object_ref (banner), g_object_unref);
470 g_assert (global_timed_banner == NULL);
471 global_timed_banner = g_object_ref (banner);
476 /* FIXME: This is a hack! We have to manually freeze
477 notifications. This is normally done by g_object_init, but we
478 are not going to call that. g_object_newv will otherwise give
479 a critical like this:
481 GLIB CRITICAL ** GLib-GObject - g_object_notify_queue_thaw:
482 assertion `nqueue->freeze_count > 0' failed */
484 g_object_freeze_notify (banner);
485 hildon_banner_reset_wrap_state (HILDON_BANNER (banner));
488 /* We restart possible timeouts for each new timed banner request */
489 if (timed && hildon_banner_clear_timeout (HILDON_BANNER (banner)))
490 hildon_banner_ensure_timeout (HILDON_BANNER(banner));
496 hildon_banner_finalize (GObject *object)
498 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
501 g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent);
504 G_OBJECT_CLASS (hildon_banner_parent_class)->finalize (object);
508 hildon_banner_button_press_event (GtkWidget* widget,
509 GdkEventButton* event)
511 gboolean result = simulate_close (widget);
514 /* signal emission not stopped - basically behave like
515 * gtk_main_do_event() for a delete event, but just hide the
516 * banner instead of destroying it, as it is already meant to
517 * be destroyed by hildon_banner_timeout() (if it's timed) or
518 * the application (if it's not). */
519 gtk_widget_hide (widget);
525 #if defined(MAEMO_GTK)
527 hildon_banner_map (GtkWidget *widget)
529 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->map) {
530 /* Make the banner temporary _before_ mapping it, to avoid closing
531 * other temporary windows */
532 gtk_window_set_is_temporary (GTK_WINDOW (widget), TRUE);
534 GTK_WIDGET_CLASS (hildon_banner_parent_class)->map (widget);
536 /* Make the banner non-temporary _after_ mapping it, to avoid
537 * being closed by other non-temporary windows */
538 gtk_window_set_is_temporary (GTK_WINDOW (widget), FALSE);
540 hildon_banner_check_position (widget);
545 /* We start the timer for timed notifications after the window appears on screen */
547 hildon_banner_map_event (GtkWidget *widget,
550 gboolean result = FALSE;
552 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->map_event)
553 result = GTK_WIDGET_CLASS (hildon_banner_parent_class)->map_event (widget, event);
555 hildon_banner_ensure_timeout (HILDON_BANNER(widget));
561 hildon_banner_reset_wrap_state (HildonBanner *banner)
564 HildonBannerPrivate *priv;
566 priv = HILDON_BANNER_GET_PRIVATE (banner);
569 layout = gtk_label_get_layout (GTK_LABEL (priv->label));
571 pango_layout_set_width (layout, -1);
572 priv->has_been_wrapped = FALSE;
573 priv->has_been_truncated = FALSE;
575 gtk_widget_set_size_request (priv->label, -1, -1);
576 gtk_widget_set_size_request (GTK_WIDGET (banner), -1, -1);
579 /* force to wrap truncated label by setting explicit size request
580 * see N#27000 and G#329646 */
582 force_to_wrap_truncated (HildonBanner *banner)
586 int width_text, width_max;
589 PangoRectangle logical;
590 GtkRequisition requisition;
591 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (banner);
593 g_return_if_fail (priv);
595 label = GTK_LABEL (priv->label);
597 layout = gtk_label_get_layout (label);
599 pango_layout_get_extents (layout, NULL, &logical);
600 width_text = PANGO_PIXELS (logical.width);
602 width_max = priv->is_timed ? HILDON_BANNER_LABEL_MAX_TIMED
603 : HILDON_BANNER_LABEL_MAX_PROGRESS;
605 /* If the width of the label is going to exceed the maximum allowed
606 * width, enforce the maximum allowed width now.
608 if (priv->has_been_wrapped
609 || width_text >= width_max
610 || pango_layout_is_wrapped (layout)) {
611 /* Force wrapping by setting the maximum size */
614 priv->has_been_wrapped = TRUE;
617 /* Make the label update its layout; and update our layout pointer
618 * because the layout will be cleared and refreshed.
620 gtk_widget_set_size_request (GTK_WIDGET (label), width, height);
621 gtk_widget_size_request (GTK_WIDGET (label), &requisition);
623 layout = gtk_label_get_layout (label);
625 /* If the layout has now been wrapped and exceeds 3 lines, we truncate
626 * the rest of the label according to spec.
628 if (priv->has_been_truncated
629 || (pango_layout_is_wrapped (layout)
630 && pango_layout_get_line_count (layout) > 3)) {
633 pango_layout_get_extents (layout, NULL, &logical);
634 lines = pango_layout_get_line_count (layout);
636 /* This calculation assumes that the same font is used
637 * throughout the banner -- this is usually the case on maemo
639 * FIXME: Pango >= 1.20 has pango_layout_set_height().
641 height = (PANGO_PIXELS (logical.height) * 3) / lines + 1;
642 priv->has_been_truncated = TRUE;
645 /* Set the new width/height if applicable */
646 gtk_widget_set_size_request (GTK_WIDGET (label), width, height);
651 hildon_banner_check_position (GtkWidget *widget)
656 gtk_widget_set_size_request (widget, gdk_screen_width (), -1);
658 force_to_wrap_truncated (HILDON_BANNER(widget)); /* see N#27000 and G#329646 */
660 gtk_widget_size_request (widget, &req);
667 x = HILDON_BANNER_WINDOW_X;
669 y = HILDON_BANNER_WINDOW_Y;
671 gtk_window_move (GTK_WINDOW (widget), x, y);
675 screen_size_changed (GdkScreen *screen,
679 gtk_window_reshow_with_initial_size (banner);
683 hildon_banner_realize (GtkWidget *widget)
688 guint32 portrait = 1;
689 const gchar *notification_type = "_HILDON_NOTIFICATION_TYPE_BANNER";
690 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (widget);
693 /* We let the parent to init widget->window before we need it */
694 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->realize)
695 GTK_WIDGET_CLASS (hildon_banner_parent_class)->realize (widget);
697 /* We use special hint to turn the banner into information notification. */
698 gdk_window_set_type_hint (widget->window, GDK_WINDOW_TYPE_HINT_NOTIFICATION);
699 gtk_window_set_transient_for (GTK_WINDOW (widget), (GtkWindow *) priv->parent);
701 hildon_banner_check_position (widget);
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->map_event = hildon_banner_map_event;
754 widget_class->realize = hildon_banner_realize;
755 widget_class->unrealize = hildon_banner_unrealize;
756 widget_class->button_press_event = hildon_banner_button_press_event;
757 #if defined(MAEMO_GTK)
758 widget_class->map = hildon_banner_map;
761 /* Install properties.
762 We need construct properties for singleton purposes */
765 * HildonBanner:parent-window:
767 * The window for which the banner will be singleton.
770 g_object_class_install_property (object_class, PROP_PARENT_WINDOW,
771 g_param_spec_object ("parent-window",
773 "The window for which the banner will be singleton",
774 GTK_TYPE_WINDOW, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
777 * HildonBanner:is-timed:
779 * Whether the banner is timed and goes away automatically.
782 g_object_class_install_property (object_class, PROP_IS_TIMED,
783 g_param_spec_boolean ("is-timed",
785 "Whether or not the notification goes away automatically "
786 "after the specified time has passed",
787 FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
790 * HildonBanner:timeout:
792 * The time before making the banner banner go away. This needs
793 * to be adjusted before the banner is mapped to the screen.
796 g_object_class_install_property (object_class, PROP_TIMEOUT,
797 g_param_spec_uint ("timeout",
799 "The time before making the banner banner go away",
802 HILDON_BANNER_DEFAULT_TIMEOUT,
803 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
807 hildon_banner_init (HildonBanner *self)
809 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
813 priv->overrides_dnd = FALSE;
814 priv->require_override_dnd = FALSE;
816 /* Initialize the common layout inside banner */
817 priv->layout = gtk_hbox_new (FALSE, HILDON_MARGIN_DEFAULT);
819 priv->label = g_object_new (GTK_TYPE_LABEL, NULL);
820 gtk_label_set_line_wrap (GTK_LABEL (priv->label), TRUE);
821 gtk_label_set_line_wrap_mode (GTK_LABEL (priv->label), PANGO_WRAP_WORD_CHAR);
823 gtk_container_set_border_width (GTK_CONTAINER (priv->layout), HILDON_MARGIN_DEFAULT);
824 gtk_container_add (GTK_CONTAINER (self), priv->layout);
825 gtk_box_pack_start (GTK_BOX (priv->layout), priv->label, TRUE, TRUE, 0);
827 gtk_window_set_accept_focus (GTK_WINDOW (self), FALSE);
829 hildon_banner_reset_wrap_state (self);
831 gtk_widget_add_events (GTK_WIDGET (self), GDK_BUTTON_PRESS_MASK);
834 /* Makes sure that icon/progress item contains the desired type
835 of item. If possible, tries to avoid creating a new widget but
836 reuses the existing one */
838 hildon_banner_ensure_child (HildonBanner *self,
839 GtkWidget *user_widget,
842 const gchar *first_property,
847 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
851 widget = priv->main_item;
852 va_start (args, first_property);
854 /* Reuse existing widget if possible */
855 if (! user_widget && G_TYPE_CHECK_INSTANCE_TYPE (widget, type))
857 g_object_set_valist (G_OBJECT (widget), first_property, args);
861 /* We have to abandon old content widget */
863 gtk_container_remove (GTK_CONTAINER (priv->layout), widget);
865 /* Use user provided widget or create a new one */
866 priv->main_item = widget = user_widget ?
867 user_widget : GTK_WIDGET (g_object_new_valist(type, first_property, args));
868 gtk_box_pack_start (GTK_BOX (priv->layout), widget, TRUE, TRUE, 0);
871 /* We make sure that the widget exists in desired position. Different
872 banners place this child widget to different places */
873 gtk_box_reorder_child (GTK_BOX (priv->layout), widget, pos);
877 /* Creates a new banner instance or uses an existing one */
879 hildon_banner_get_instance_for_widget (GtkWidget *widget,
884 window = widget ? gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW) : NULL;
885 return g_object_new (HILDON_TYPE_BANNER, "parent-window", window, "is-timed", timed, NULL);
889 hildon_banner_create_animation (void)
892 GdkPixbufSimpleAnim *anim;
895 GError *error = NULL;
899 anim = gdk_pixbuf_simple_anim_new (HILDON_ICON_PIXEL_SIZE_STYLUS,
900 HILDON_ICON_PIXEL_SIZE_STYLUS,
901 HILDON_BANNER_ANIMATION_FRAMERATE);
902 gdk_pixbuf_simple_anim_set_loop (anim, TRUE);
903 theme = gtk_icon_theme_get_default ();
905 for (i = 1; i <= HILDON_BANNER_ANIMATION_NFRAMES; i++) {
906 icon_name = g_strdup_printf (HILDON_BANNER_ANIMATION_TMPL, i);
907 frame = gtk_icon_theme_load_icon (theme, icon_name, HILDON_ICON_PIXEL_SIZE_STYLUS,
911 g_warning ("Icon theme lookup for icon `%s' failed: %s",
912 icon_name, error->message);
913 g_error_free (error);
916 gdk_pixbuf_simple_anim_add_frame (anim, frame);
919 g_object_unref (frame);
923 image = gtk_image_new_from_animation (GDK_PIXBUF_ANIMATION (anim));
924 g_object_unref (anim);
930 * hildon_banner_show_information:
931 * @widget: the #GtkWidget that is the owner of the banner
932 * @icon_name: since Hildon 2.2 this parameter is not used anymore and
933 * any value that you pass will be ignored
934 * @text: Text to display
936 * This function creates and displays an information banner that
937 * automatically goes away after certain time period. For each window
938 * in your application there can only be one timed banner, so if you
939 * spawn a new banner before the earlier one has timed out, the
940 * previous one will be replaced.
942 * Returns: The newly created banner
946 hildon_banner_show_information (GtkWidget *widget,
947 const gchar *icon_name,
950 return hildon_banner_real_show_information (widget, text, FALSE);
954 * hildon_banner_show_information_override_dnd:
955 * @widget: the #GtkWidget that is the owner of the banner
956 * @text: Text to display
958 * Equivalent to hildon_banner_show_information() but it overrides the do not
959 * disturb flag, in the special cases that could be needed. It is required
960 * because this method calls internally gtk_widget_show before returns the banner,
961 * but the do not disturb flag is checked on the mapping of the widget
964 * Returns: The newly created banner
970 hildon_banner_show_information_override_dnd (GtkWidget *widget,
973 return hildon_banner_real_show_information (widget, text, TRUE);
977 hildon_banner_set_override_flag (HildonBanner *banner)
981 gdk_property_change (GTK_WIDGET (banner)->window,
982 gdk_atom_intern_static_string ("_HILDON_DO_NOT_DISTURB_OVERRIDE"),
983 gdk_x11_xatom_to_atom (XA_INTEGER),
985 GDK_PROP_MODE_REPLACE,
986 (const guchar*) &state,
992 hildon_banner_real_show_information (GtkWidget *widget,
994 gboolean override_dnd)
996 HildonBanner *banner;
997 HildonBannerPrivate *priv = NULL;
999 g_return_val_if_fail (text != NULL, NULL);
1001 /* Prepare banner */
1002 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
1003 priv = HILDON_BANNER_GET_PRIVATE (banner);
1005 hildon_banner_set_text (banner, text);
1006 hildon_banner_bind_style (banner, "information");
1009 /* so on the realize it will set the property */
1010 priv->require_override_dnd = TRUE;
1013 /* Show the banner, since caller cannot do that */
1014 gtk_widget_show_all (GTK_WIDGET (banner));
1016 return GTK_WIDGET (banner);
1020 * hildon_banner_show_informationf:
1021 * @widget: the #GtkWidget that is the owner of the banner
1022 * @icon_name: since Hildon 2.2 this parameter is not used anymore and
1023 * any value that you pass will be ignored
1024 * @format: a printf-like format string
1025 * @Varargs: arguments for the format string
1027 * A helper function for #hildon_banner_show_information with
1028 * string formatting.
1030 * Returns: the newly created banner
1033 hildon_banner_show_informationf (GtkWidget *widget,
1034 const gchar *icon_name,
1035 const gchar *format,
1038 g_return_val_if_fail (format != NULL, NULL);
1044 va_start (args, format);
1045 message = g_strdup_vprintf (format, args);
1048 banner = hildon_banner_show_information (widget, icon_name, message);
1056 * hildon_banner_show_information_with_markup:
1057 * @widget: the #GtkWidget that wants to display banner
1058 * @icon_name: since Hildon 2.2 this parameter is not used anymore and
1059 * any value that you pass will be ignored
1060 * @markup: a markup string to display (see <link linkend="PangoMarkupFormat">Pango markup format</link>)
1062 * This function creates and displays an information banner that
1063 * automatically goes away after certain time period. For each window
1064 * in your application there can only be one timed banner, so if you
1065 * spawn a new banner before the earlier one has timed out, the
1066 * previous one will be replaced.
1068 * Returns: the newly created banner
1072 hildon_banner_show_information_with_markup (GtkWidget *widget,
1073 const gchar *icon_name,
1074 const gchar *markup)
1076 HildonBanner *banner;
1078 g_return_val_if_fail (icon_name == NULL || icon_name[0] != 0, NULL);
1079 g_return_val_if_fail (markup != NULL, NULL);
1081 /* Prepare banner */
1082 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
1084 hildon_banner_set_markup (banner, markup);
1085 hildon_banner_bind_style (banner, "information");
1087 /* Show the banner, since caller cannot do that */
1088 gtk_widget_show_all (GTK_WIDGET (banner));
1090 return (GtkWidget *) banner;
1094 * hildon_banner_show_animation:
1095 * @widget: the #GtkWidget that wants to display banner
1096 * @animation_name: since Hildon 2.2 this parameter is not used
1097 * anymore and any value that you pass will be
1099 * @text: the text to display.
1101 * Shows an animated progress notification. It's recommended not to try
1102 * to show more than one progress notification at a time, since
1103 * they will appear on top of each other. You can use progress
1104 * notifications with timed banners. In this case the banners are
1105 * located so that you can somehow see both.
1107 * Please note that banners are destroyed automatically once the
1108 * window they are attached to is closed. The pointer that you receive
1109 * with this function does not contain additional references, so it
1110 * can become invalid without warning (this is true for all toplevel
1111 * windows in gtk). To make sure that the banner does not disappear
1112 * automatically, you can separately ref the return value (this
1113 * doesn't prevent the banner from disappearing, just the object from
1114 * being finalized). In this case you have to call both
1115 * gtk_widget_destroy() followed by g_object_unref() (in this order).
1117 * Returns: a #HildonBanner widget. You must call gtk_widget_destroy()
1118 * once you are done with the banner.
1120 * Deprecated: Hildon 2.2: use
1121 * hildon_gtk_window_set_progress_indicator() instead.
1124 hildon_banner_show_animation (GtkWidget *widget,
1125 const gchar *animation_name,
1128 HildonBanner *banner;
1129 GtkWidget *image_widget;
1131 g_return_val_if_fail (text != NULL, NULL);
1133 image_widget = hildon_banner_create_animation ();
1135 /* Prepare banner */
1136 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
1137 hildon_banner_ensure_child (banner, image_widget, 0,
1138 GTK_TYPE_IMAGE, "yalign", 0.0, NULL);
1140 hildon_banner_set_text (banner, text);
1141 hildon_banner_bind_style (banner, "animation");
1144 gtk_widget_show_all (GTK_WIDGET (banner));
1146 return (GtkWidget *) banner;
1150 * hildon_banner_show_progress:
1151 * @widget: the #GtkWidget that wants to display banner
1152 * @bar: since Hildon 2.2 this parameter is not used anymore and
1153 * any value that you pass will be ignored
1154 * @text: text to display.
1156 * Shows progress notification. See #hildon_banner_show_animation
1157 * for more information.
1159 * Returns: a #HildonBanner widget. You must call #gtk_widget_destroy
1160 * once you are done with the banner.
1162 * Deprecated: Hildon 2.2: use hildon_gtk_window_set_progress_indicator() instead.
1165 hildon_banner_show_progress (GtkWidget *widget,
1166 GtkProgressBar *bar,
1169 HildonBanner *banner;
1170 HildonBannerPrivate *priv;
1172 g_return_val_if_fail (text != NULL, NULL);
1174 /* Prepare banner */
1175 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
1176 priv = HILDON_BANNER_GET_PRIVATE (banner);
1179 hildon_banner_set_text (banner, text);
1180 hildon_banner_bind_style (banner, "progress");
1183 hildon_gtk_window_set_progress_indicator (priv->parent, 1);
1185 /* Show the banner */
1186 gtk_widget_show_all (GTK_WIDGET (banner));
1188 return GTK_WIDGET (banner);
1192 * hildon_banner_set_text:
1193 * @self: a #HildonBanner widget
1194 * @text: a new text to display in banner
1196 * Sets the text that is displayed in the banner.
1200 hildon_banner_set_text (HildonBanner *self,
1204 HildonBannerPrivate *priv;
1205 const gchar *existing_text;
1207 g_return_if_fail (HILDON_IS_BANNER (self));
1209 priv = HILDON_BANNER_GET_PRIVATE (self);
1212 label = GTK_LABEL (priv->label);
1213 existing_text = gtk_label_get_text (label);
1215 if (existing_text != NULL &&
1217 strcmp (existing_text, text) != 0) {
1218 gtk_label_set_text (label, text);
1219 hildon_banner_reset_wrap_state (self);
1222 hildon_banner_check_position (GTK_WIDGET (self));
1226 * hildon_banner_set_markup:
1227 * @self: a #HildonBanner widget
1228 * @markup: a new text with Pango markup to display in the banner
1230 * Sets the text with markup that is displayed in the banner.
1234 hildon_banner_set_markup (HildonBanner *self,
1235 const gchar *markup)
1238 HildonBannerPrivate *priv;
1240 g_return_if_fail (HILDON_IS_BANNER (self));
1242 priv = HILDON_BANNER_GET_PRIVATE (self);
1245 label = GTK_LABEL (priv->label);
1246 gtk_label_set_markup (label, markup);
1248 hildon_banner_reset_wrap_state (self);
1250 hildon_banner_check_position (GTK_WIDGET(self));
1254 * hildon_banner_set_fraction:
1255 * @self: a #HildonBanner widget
1256 * @fraction: #gdouble
1258 * The fraction is the completion of progressbar,
1259 * the scale is from 0.0 to 1.0.
1260 * Sets the amount of fraction the progressbar has.
1262 * Note that this method only has effect if @self was created with
1263 * hildon_banner_show_progress()
1265 * Deprecated: This function does nothing. As of Hildon 2.2, hildon
1266 * banners don't have progress bars.
1269 hildon_banner_set_fraction (HildonBanner *self,
1275 * hildon_banner_set_timeout:
1276 * @self: a #HildonBanner widget
1277 * @timeout: timeout to set in miliseconds.
1279 * Sets the timeout on the banner. After the given amount of miliseconds
1280 * has elapsed the banner will go away. Note that settings this only makes
1281 * sense on the banners that are timed and that have not been yet displayed
1284 * Note that this method only has effect if @self is an information
1285 * banner (created using hildon_banner_show_information() and
1289 hildon_banner_set_timeout (HildonBanner *self,
1292 HildonBannerPrivate *priv;
1294 g_return_if_fail (HILDON_IS_BANNER (self));
1295 priv = HILDON_BANNER_GET_PRIVATE (self);
1298 priv->timeout = timeout;
1302 * hildon_banner_set_icon:
1303 * @self: a #HildonBanner widget
1304 * @icon_name: the name of icon to use. Can be %NULL for default icon
1306 * Sets the icon to be used in the banner.
1308 * Deprecated: This function does nothing. As of hildon 2.2, hildon
1309 * banners don't allow changing their icons.
1312 hildon_banner_set_icon (HildonBanner *self,
1313 const gchar *icon_name)
1318 * hildon_banner_set_icon_from_file:
1319 * @self: a #HildonBanner widget
1320 * @icon_file: the filename of icon to use. Can be %NULL for default icon
1322 * Sets the icon from its filename to be used in the banner.
1324 * Deprecated: This function does nothing. As of hildon 2.2, hildon
1325 * banners don't allow changing their icons.
1328 hildon_banner_set_icon_from_file (HildonBanner *self,
1329 const gchar *icon_file)