2 * This file is a part of hildon
4 * Copyright (C) 2005, 2006, 2007 Nokia Corporation, all rights reserved.
6 * Contact: Michael Dominic Kostrzewa <michael.kostrzewa@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 can be used to display a short, timed notification
30 * or information to the user. It can communicate that a
31 * task has been finished or the application state has changed.
32 * Banners should be used only to display non-critical pieces of
41 #include "hildon-banner.h"
42 #include <gtk/gtkhbox.h>
43 #include <gtk/gtkimage.h>
44 #include <gtk/gtkicontheme.h>
47 #include <X11/Xatom.h>
48 #include "hildon-defines.h"
49 #include "hildon-banner-private.h"
51 /* position relative to the screen */
53 #define HILDON_BANNER_WINDOW_X 30
55 #define HILDON_BANNER_WINDOW_Y 73
57 #define HILDON_BANNER_WINDOW_FULLSCREEN_Y 20
61 #define HILDON_BANNER_PROGRESS_WIDTH 104
63 #define HILDON_BANNER_LABEL_MAX_TIMED 375
65 #define HILDON_BANNER_LABEL_MAX_PROGRESS 375 /*265*/
69 #define HILDON_BANNER_DEFAULT_TIMEOUT 3000
73 #define HILDON_BANNER_DEFAULT_ICON "qgn_note_infoprint"
75 #define HILDON_BANNER_DEFAULT_PROGRESS_ANIMATION "qgn_indi_pball_a"
85 static GtkWidget* global_timed_banner = NULL;
88 get_current_app_window (void);
91 check_fullscreen_state (Window window);
94 hildon_banner_timed_quark (void);
97 hildon_banner_bind_label_style (HildonBanner *self,
101 hildon_banner_timeout (gpointer data);
104 hildon_banner_clear_timeout (HildonBanner *self);
107 hildon_banner_ensure_timeout (HildonBanner *self);
110 hildon_banner_set_property (GObject *object,
116 hildon_banner_get_property (GObject *object,
122 hildon_banner_destroy (GtkObject *object);
125 hildon_banner_real_get_instance (GObject *window,
129 hildon_banner_constructor (GType type,
130 guint n_construct_params,
131 GObjectConstructParam *construct_params);
134 hildon_banner_finalize (GObject *object);
137 hildon_banner_map_event (GtkWidget *widget,
141 force_to_wrap_truncated (HildonBanner *banner);
144 hildon_banner_check_position (GtkWidget *widget);
147 hildon_banner_realize (GtkWidget *widget);
150 hildon_banner_class_init (HildonBannerClass *klass);
153 hildon_banner_init (HildonBanner *self);
156 hildon_banner_ensure_child (HildonBanner *self,
157 GtkWidget *user_widget,
160 const gchar *first_property,
164 hildon_banner_get_instance_for_widget (GtkWidget *widget,
168 hildon_banner_delete_event (GtkWidget *widget,
172 G_DEFINE_TYPE (HildonBanner, hildon_banner, GTK_TYPE_WINDOW)
174 /* copy/paste from old infoprint implementation: Use matchbox
175 properties to find the topmost application window */
177 get_current_app_window (void)
184 Atom atom_current_app_window = gdk_x11_get_xatom_by_name ("_MB_CURRENT_APP_WINDOW");
186 Window win_result = None;
187 guchar *data_return = NULL;
189 status = XGetWindowProperty (GDK_DISPLAY(), GDK_ROOT_WINDOW (),
190 atom_current_app_window, 0L, 16L,
191 0, XA_WINDOW, &realType, &format,
195 if (status == Success && realType == XA_WINDOW && format == 32 && n == 1 && data_return != NULL)
197 win_result = ((Window*) data_return)[0];
206 /* Checks if a window is in fullscreen state or not. This
207 information is needed when banners are positioned on screen.
208 copy/paste from old infoprint implementation. */
210 check_fullscreen_state (Window window)
214 int format, status, i;
215 guchar *data_return = NULL;
218 Atom atom_window_state = gdk_x11_get_xatom_by_name ("_NET_WM_STATE");
219 Atom atom_fullscreen = gdk_x11_get_xatom_by_name ("_NET_WM_STATE_FULLSCREEN");
224 /* in some cases XGetWindowProperty seems to generate BadWindow,
225 so at the moment this function does not always work perfectly */
226 gdk_error_trap_push ();
227 status = XGetWindowProperty (GDK_DISPLAY (), window,
228 atom_window_state, 0L, 1000000L,
229 0, XA_ATOM, &realType, &format,
230 &n, &extra, &data_return);
234 if (gdk_error_trap_pop ())
237 if (status == Success && realType == XA_ATOM && format == 32 && n > 0)
239 for (i=0; i < n; i++)
240 if (((Atom*)data_return)[i] && ((Atom*)data_return)[i] == atom_fullscreen)
242 if (data_return) XFree (data_return);
254 hildon_banner_timed_quark (void)
256 static GQuark quark = 0;
258 if (G_UNLIKELY(quark == 0))
259 quark = g_quark_from_static_string ("hildon-banner-timed");
264 /* Set the label name to make the correct rc-style attached into it */
266 hildon_banner_bind_label_style (HildonBanner *self,
269 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
272 GtkWidget *label = priv->label;
274 /* Too bad that we cannot really reset the widget name */
275 gtk_widget_set_name (label, name ? name : g_type_name (GTK_WIDGET_TYPE (label)));
278 /* In timeout function we automatically destroy timed banners */
280 hildon_banner_timeout (gpointer data)
284 gboolean continue_timeout = FALSE;
286 GDK_THREADS_ENTER ();
288 g_assert (HILDON_IS_BANNER (data));
290 widget = GTK_WIDGET (data);
291 g_object_ref (widget);
293 /* If the banner is currently visible (it normally should),
294 we simulate clicking the close button of the window.
295 This allows applications to reuse the banner by prevent
297 if (GTK_WIDGET_DRAWABLE (widget))
299 event = gdk_event_new (GDK_DELETE);
300 event->any.window = g_object_ref (widget->window);
301 event->any.send_event = FALSE;
302 continue_timeout = gtk_widget_event (widget, event);
303 gdk_event_free (event);
306 if (! continue_timeout)
307 gtk_widget_destroy (widget);
309 g_object_unref (widget);
311 GDK_THREADS_LEAVE ();
313 return continue_timeout;
317 hildon_banner_clear_timeout (HildonBanner *self)
319 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
322 if (priv->timeout_id != 0) {
323 g_source_remove (priv->timeout_id);
324 priv->timeout_id = 0;
332 hildon_banner_ensure_timeout (HildonBanner *self)
334 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
337 if (priv->timeout_id == 0 && priv->is_timed && priv->timeout > 0)
338 priv->timeout_id = g_timeout_add (priv->timeout,
339 hildon_banner_timeout, self);
343 hildon_banner_set_property (GObject *object,
350 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
356 priv->timeout = g_value_get_uint (value);
360 priv->is_timed = g_value_get_boolean (value);
362 /* Timed and progress notifications have different
363 pixel size values for text.
364 We force to use requisition size for timed banners
365 in order to avoid resize problems when reusing the
366 window (see bug #24339) */
367 geom.max_width = priv->is_timed ? -1
368 : HILDON_BANNER_LABEL_MAX_PROGRESS;
369 geom.max_height = -1;
370 gtk_window_set_geometry_hints (GTK_WINDOW (object),
371 priv->label, &geom, GDK_HINT_MAX_SIZE);
374 case PROP_PARENT_WINDOW:
375 window = g_value_get_object (value);
377 g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent);
380 gtk_window_set_transient_for (GTK_WINDOW (object), (GtkWindow *) window);
381 priv->parent = (GtkWindow *) window;
384 gtk_window_set_destroy_with_parent (GTK_WINDOW (object), TRUE);
385 g_object_add_weak_pointer(G_OBJECT (window), (gpointer) &priv->parent);
391 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
397 hildon_banner_get_property (GObject *object,
402 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
408 g_value_set_uint (value, priv->timeout);
412 g_value_set_boolean (value, priv->is_timed);
415 case PROP_PARENT_WINDOW:
416 g_value_set_object (value, gtk_window_get_transient_for (GTK_WINDOW (object)));
420 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
426 hildon_banner_destroy (GtkObject *object)
428 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
432 GObject *parent_window = (GObject *) priv->parent;
434 g_assert (HILDON_IS_BANNER (object));
435 self = HILDON_BANNER (object);
437 /* Drop possible global pointer. That can hold reference to us */
438 if ((gpointer) object == (gpointer) global_timed_banner) {
439 global_timed_banner = NULL;
440 g_object_unref (object);
443 /* Remove the data from parent window for timed banners. Those hold reference */
444 if (priv->is_timed && parent_window != NULL) {
445 g_object_set_qdata (parent_window, hildon_banner_timed_quark (), NULL);
448 (void) hildon_banner_clear_timeout (self);
450 if (GTK_OBJECT_CLASS (hildon_banner_parent_class)->destroy)
451 GTK_OBJECT_CLASS (hildon_banner_parent_class)->destroy (object);
454 /* Search a previous banner instance */
456 hildon_banner_real_get_instance (GObject *window,
460 /* If we have a parent window, the previous instance is stored there */
462 return g_object_get_qdata(window, hildon_banner_timed_quark ());
465 /* System notification instance is stored into global pointer */
466 return (GObject *) global_timed_banner;
469 /* Non-timed banners are normal (non-singleton) objects */
473 /* By overriding constructor we force timed banners to be
474 singletons for each window */
476 hildon_banner_constructor (GType type,
477 guint n_construct_params,
478 GObjectConstructParam *construct_params)
480 GObject *banner, *window = NULL;
481 gboolean timed = FALSE;
484 /* Search banner type information from parameters in order
485 to locate the possible previous banner instance. */
486 for (i = 0; i < n_construct_params; i++)
488 if (strcmp(construct_params[i].pspec->name, "parent-window") == 0)
489 window = g_value_get_object (construct_params[i].value);
490 else if (strcmp(construct_params[i].pspec->name, "is-timed") == 0)
491 timed = g_value_get_boolean (construct_params[i].value);
494 /* Try to get a previous instance if such exists */
495 banner = hildon_banner_real_get_instance (window, timed);
498 /* We have to create a new banner */
499 banner = G_OBJECT_CLASS (hildon_banner_parent_class)->constructor (type, n_construct_params, construct_params);
501 /* Store the newly created singleton instance either into parent
502 window data or into global variables. */
505 g_object_set_qdata_full (G_OBJECT (window), hildon_banner_timed_quark (),
506 g_object_ref (banner), g_object_unref);
508 g_assert (global_timed_banner == NULL);
509 global_timed_banner = g_object_ref (banner);
514 /* FIXME: This is a hack! We have to manually freeze
515 notifications. This is normally done by g_object_init, but we
516 are not going to call that. g_object_newv will otherwise give
517 a critical like this:
519 GLIB CRITICAL ** GLib-GObject - g_object_notify_queue_thaw:
520 assertion `nqueue->freeze_count > 0' failed */
522 g_object_freeze_notify (banner);
525 /* We restart possible timeouts for each new timed banner request */
526 if (timed && hildon_banner_clear_timeout (HILDON_BANNER (banner)))
527 hildon_banner_ensure_timeout (HILDON_BANNER(banner));
533 hildon_banner_finalize (GObject *object)
535 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
538 g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent);
541 G_OBJECT_CLASS (hildon_banner_parent_class)->finalize (object);
544 /* We start the timer for timed notifications after the window appears on screen */
546 hildon_banner_map_event (GtkWidget *widget,
549 gboolean result = FALSE;
551 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->map_event)
552 result = GTK_WIDGET_CLASS (hildon_banner_parent_class)->map_event (widget, event);
554 hildon_banner_ensure_timeout (HILDON_BANNER(widget));
559 #if defined(MAEMO_GTK)
561 static GdkAtom atom_temporaries = GDK_NONE;
563 /* Do nothing for _GTK_DELETE_TEMPORARIES */
565 hildon_banner_client_event (GtkWidget *widget,
566 GdkEventClient *event)
568 gboolean handled = FALSE;
570 if (atom_temporaries == GDK_NONE)
571 atom_temporaries = gdk_atom_intern_static_string ("_GTK_DELETE_TEMPORARIES");
573 if (event->message_type == atom_temporaries)
582 /* force to wrap truncated label by setting explicit size request
583 * see N#27000 and G#329646 */
585 force_to_wrap_truncated (HildonBanner *banner)
589 int width_text, width_max;
591 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (banner);
594 label = GTK_LABEL (priv->label);
596 layout = gtk_label_get_layout (label);
597 width_text = PANGO_PIXELS(pango_layout_get_width (layout));
598 /* = width to which the lines of the PangoLayout should be wrapped */
600 width_max = priv->is_timed ? HILDON_BANNER_LABEL_MAX_TIMED
601 : HILDON_BANNER_LABEL_MAX_PROGRESS;
603 if (width_text >= width_max) {
604 /* explicitly request maximum size to force wrapping */
605 PangoRectangle logical;
607 pango_layout_set_width (layout, width_max * PANGO_SCALE);
608 pango_layout_get_extents (layout, NULL, &logical);
610 width = PANGO_PIXELS (logical.width);
613 /* use fixed width when wrapping or natural one otherwise */
614 gtk_widget_set_size_request (GTK_WIDGET (label), width, -1);
619 hildon_banner_check_position (GtkWidget *widget)
624 force_to_wrap_truncated (HILDON_BANNER(widget)); /* see N#27000 and G#329646 */
626 gtk_widget_size_request (widget, &req);
633 x = gdk_screen_width() - HILDON_BANNER_WINDOW_X - req.width;
634 y = check_fullscreen_state (get_current_app_window ()) ?
635 HILDON_BANNER_WINDOW_FULLSCREEN_Y : HILDON_BANNER_WINDOW_Y;
637 gtk_window_move (GTK_WINDOW (widget), x, y);
641 hildon_banner_realize (GtkWidget *widget)
643 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (widget);
646 /* We let the parent to init widget->window before we need it */
647 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->realize)
648 GTK_WIDGET_CLASS (hildon_banner_parent_class)->realize (widget);
650 /* We use special hint to turn the banner into information notification. */
651 gdk_window_set_type_hint (widget->window, GDK_WINDOW_TYPE_HINT_NOTIFICATION);
652 gtk_window_set_transient_for (GTK_WINDOW (widget), (GtkWindow *) priv->parent);
654 hildon_banner_check_position (widget);
658 hildon_banner_class_init (HildonBannerClass *klass)
660 GObjectClass *object_class;
661 GtkWidgetClass *widget_class;
663 object_class = G_OBJECT_CLASS (klass);
664 widget_class = GTK_WIDGET_CLASS (klass);
666 /* Append private structure to class. This is more elegant than
667 on g_new based approach */
668 g_type_class_add_private (klass, sizeof (HildonBannerPrivate));
670 /* Override virtual methods */
671 object_class->constructor = hildon_banner_constructor;
672 object_class->finalize = hildon_banner_finalize;
673 object_class->set_property = hildon_banner_set_property;
674 object_class->get_property = hildon_banner_get_property;
675 GTK_OBJECT_CLASS (klass)->destroy = hildon_banner_destroy;
676 widget_class->map_event = hildon_banner_map_event;
677 widget_class->realize = hildon_banner_realize;
678 #if defined(MAEMO_GTK)
679 widget_class->client_event = hildon_banner_client_event;
682 /* Install properties.
683 We need construct properties for singleton purposes */
686 * HildonBanner:parent-window:
688 * The window for which the banner will be singleton.
691 g_object_class_install_property (object_class, PROP_PARENT_WINDOW,
692 g_param_spec_object ("parent-window",
694 "The window for which the banner will be singleton",
695 GTK_TYPE_WINDOW, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
698 * HildonBanner:is-timed:
700 * Whether the banner is timed and goes away automatically.
703 g_object_class_install_property (object_class, PROP_IS_TIMED,
704 g_param_spec_boolean ("is-timed",
706 "Whether or not the notification goes away automatically "
707 "after the specified time has passed",
708 FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
711 * HildonBanner:timeout:
713 * The time before making the banner banner go away. This needs
714 * to be adjusted before the banner is mapped to the screen.
717 g_object_class_install_property (object_class, PROP_TIMEOUT,
718 g_param_spec_uint ("timeout",
720 "The time before making the banner banner go away",
723 HILDON_BANNER_DEFAULT_TIMEOUT,
724 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
728 hildon_banner_init (HildonBanner *self)
730 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
735 /* Initialize the common layout inside banner */
736 priv->layout = gtk_hbox_new (FALSE, HILDON_MARGIN_DEFAULT);
738 priv->label = g_object_new (GTK_TYPE_LABEL, NULL);
739 gtk_label_set_line_wrap (GTK_LABEL (priv->label), TRUE);
741 gtk_container_set_border_width (GTK_CONTAINER (priv->layout), HILDON_MARGIN_DEFAULT);
742 gtk_container_add (GTK_CONTAINER (self), priv->layout);
743 gtk_box_pack_start (GTK_BOX (priv->layout), priv->label, TRUE, TRUE, 0);
745 gtk_window_set_accept_focus (GTK_WINDOW (self), FALSE);
747 #if defined(MAEMO_GTK)
748 gtk_window_set_is_temporary (GTK_WINDOW (self), TRUE);
752 /* Makes sure that icon/progress item contains the desired type
753 of item. If possible, tries to avoid creating a new widget but
754 reuses the existing one */
756 hildon_banner_ensure_child (HildonBanner *self,
757 GtkWidget *user_widget,
760 const gchar *first_property,
765 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
769 widget = priv->main_item;
770 va_start (args, first_property);
772 /* Reuse existing widget if possible */
773 if (! user_widget && G_TYPE_CHECK_INSTANCE_TYPE (widget, type))
775 g_object_set_valist (G_OBJECT (widget), first_property, args);
779 /* We have to abandon old content widget */
781 gtk_container_remove (GTK_CONTAINER (priv->layout), widget);
783 /* Use user provided widget or create a new one */
784 priv->main_item = widget = user_widget ?
785 user_widget : GTK_WIDGET (g_object_new_valist(type, first_property, args));
786 gtk_box_pack_start (GTK_BOX (priv->layout), widget, TRUE, TRUE, 0);
789 /* We make sure that the widget exists in desired position. Different
790 banners place this child widget to different places */
791 gtk_box_reorder_child (GTK_BOX (priv->layout), widget, pos);
795 /* Creates a new banner instance or uses an existing one */
797 hildon_banner_get_instance_for_widget (GtkWidget *widget,
802 window = widget ? gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW) : NULL;
803 return g_object_new (HILDON_TYPE_BANNER, "parent-window", window, "is-timed", timed, NULL);
807 * hildon_banner_show_information:
808 * @widget: the #GtkWidget that is the owner of the banner
809 * @icon_name: the name of icon to use. Can be %NULL for default icon
810 * @text: Text to display
812 * This function creates and displays an information banner that
813 * automatically goes away after certain time period. For each window
814 * in your application there can only be one timed banner, so if you
815 * spawn a new banner before the earlier one has timed out, the
816 * previous one will be replaced.
818 * Returns: The newly created banner
822 hildon_banner_show_information (GtkWidget *widget,
823 const gchar *icon_name,
826 HildonBanner *banner;
828 g_return_val_if_fail (icon_name == NULL || icon_name[0] != 0, NULL);
829 g_return_val_if_fail (text != NULL, NULL);
832 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
833 hildon_banner_ensure_child (banner, NULL, 0, GTK_TYPE_IMAGE,
834 "pixel-size", HILDON_ICON_PIXEL_SIZE_NOTE,
835 "icon-name", icon_name ? icon_name : HILDON_BANNER_DEFAULT_ICON,
839 hildon_banner_set_text (banner, text);
840 hildon_banner_bind_label_style (banner, NULL);
842 /* Show the banner, since caller cannot do that */
843 gtk_widget_show_all (GTK_WIDGET (banner));
845 return (GtkWidget *) banner;
849 * hildon_banner_show_informationf:
850 * @widget: the #GtkWidget that is the owner of the banner
851 * @icon_name: the name of icon to use. Can be %NULL for default icon
852 * @format: a printf-like format string
853 * @Varargs: arguments for the format string
855 * A helper function for #hildon_banner_show_information with
858 * Returns: the newly created banner
861 hildon_banner_show_informationf (GtkWidget *widget,
862 const gchar *icon_name,
866 g_return_val_if_fail (format != NULL, NULL);
872 va_start (args, format);
873 message = g_strdup_vprintf (format, args);
876 banner = hildon_banner_show_information (widget, icon_name, message);
884 * hildon_banner_show_information_with_markup:
885 * @widget: the #GtkWidget that wants to display banner
886 * @icon_name: the name of icon to use. Can be %NULL for default icon.
887 * @markup: a markup string to display (see <link linkend="PangoMarkupFormat">Pango markup format</link>)
889 * This function creates and displays an information banner that
890 * automatically goes away after certain time period. For each window
891 * in your application there can only be one timed banner, so if you
892 * spawn a new banner before the earlier one has timed out, the
893 * previous one will be replaced.
895 * Returns: the newly created banner
899 hildon_banner_show_information_with_markup (GtkWidget *widget,
900 const gchar *icon_name,
903 HildonBanner *banner;
905 g_return_val_if_fail (icon_name == NULL || icon_name[0] != 0, NULL);
906 g_return_val_if_fail (markup != NULL, NULL);
909 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
911 hildon_banner_ensure_child (banner, NULL, 0, GTK_TYPE_IMAGE,
912 "pixel-size", HILDON_ICON_PIXEL_SIZE_NOTE,
913 "icon-name", icon_name ? icon_name : HILDON_BANNER_DEFAULT_ICON,
917 hildon_banner_set_markup (banner, markup);
918 hildon_banner_bind_label_style (banner, NULL);
920 /* Show the banner, since caller cannot do that */
921 gtk_widget_show_all (GTK_WIDGET (banner));
923 return (GtkWidget *) banner;
927 * hildon_banner_show_animation:
928 * @widget: the #GtkWidget that wants to display banner
929 * @animation_name: The progress animation to use. You usually can just
930 * pass %NULL for the default animation.
931 * @text: the text to display.
933 * Shows an animated progress notification. It's recommended not to try
934 * to show more than one progress notification at a time, since
935 * they will appear on top of each other. You can use progress
936 * notifications with timed banners. In this case the banners are
937 * located so that you can somehow see both.
939 * Please note that banners are destroyed automatically once the
940 * window they are attached to is closed. The pointer that you
941 * receive with this function do not contain additional references,
942 * so it can become invalid without warning (this is true for
943 * all toplevel windows in gtk). To make sure that the banner do not disapear
944 * automatically, you can separately ref the return value (this
945 * doesn't prevent the banner from disappearing, but the object it just
946 * not finalized). In this case you have to call both #gtk_widget_destroy
947 * followed by #g_object_unref (in this order).
949 * Returns: a #HildonBanner widget. You must call #gtk_widget_destroy
950 * once you are done with the banner.
954 hildon_banner_show_animation (GtkWidget *widget,
955 const gchar *animation_name,
958 HildonBanner *banner;
961 GtkWidget *image_widget;
962 const gchar *filename;
964 g_return_val_if_fail (animation_name == NULL || animation_name[0] != 0, NULL);
965 g_return_val_if_fail (text != NULL, NULL);
967 /* Find out which animation to use */
968 theme = gtk_icon_theme_get_default ();
969 info = gtk_icon_theme_lookup_icon (theme, animation_name ? /* FIXME: consider using: gtk_icon_theme_load_icon() */
970 animation_name : HILDON_BANNER_DEFAULT_PROGRESS_ANIMATION,
971 HILDON_ICON_SIZE_NOTE, 0);
973 /* Try to load animation. One could try to optimize this
974 to avoid loading the default animation during each call */
976 filename = gtk_icon_info_get_filename (info);
977 image_widget = gtk_image_new_from_file (filename);
978 gtk_icon_info_free (info);
980 g_warning ("Icon theme lookup for icon failed!");
985 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
986 hildon_banner_ensure_child (banner, image_widget, 0,
987 GTK_TYPE_IMAGE, "yalign", 0.0, NULL);
989 hildon_banner_set_text (banner, text);
990 hildon_banner_bind_label_style (banner, NULL);
993 gtk_widget_show_all (GTK_WIDGET (banner));
995 return (GtkWidget *) banner;
999 * hildon_banner_show_progress:
1000 * @widget: the #GtkWidget that wants to display banner
1001 * @bar: Progressbar to use. You usually can just pass %NULL, unless
1002 * you want somehow customized progress bar.
1003 * @text: text to display.
1005 * Shows progress notification. See #hildon_banner_show_animation
1006 * for more information.
1008 * Returns: a #HildonBanner widget. You must call #gtk_widget_destroy
1009 * once you are done with the banner.
1013 hildon_banner_show_progress (GtkWidget *widget,
1014 GtkProgressBar *bar,
1017 HildonBanner *banner;
1018 HildonBannerPrivate *priv;
1020 g_return_val_if_fail (bar == NULL || GTK_IS_PROGRESS_BAR (bar), NULL);
1021 g_return_val_if_fail (text != NULL, NULL);
1024 /* Prepare banner */
1025 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
1026 priv = HILDON_BANNER_GET_PRIVATE (banner);
1028 hildon_banner_ensure_child (banner, (GtkWidget *) bar, -1, GTK_TYPE_PROGRESS_BAR, NULL);
1030 gtk_widget_set_size_request (priv->main_item,
1031 HILDON_BANNER_PROGRESS_WIDTH, -1);
1033 hildon_banner_set_text (banner, text);
1034 hildon_banner_bind_label_style (banner, NULL);
1036 /* Show the banner */
1037 gtk_widget_show_all (GTK_WIDGET (banner));
1039 return GTK_WIDGET (banner);
1043 * hildon_banner_set_text:
1044 * @self: a #HildonBanner widget
1045 * @text: a new text to display in banner
1047 * Sets the text that is displayed in the banner.
1051 hildon_banner_set_text (HildonBanner *self,
1055 HildonBannerPrivate *priv;
1056 const gchar *existing_text;
1058 g_return_if_fail (HILDON_IS_BANNER (self));
1060 priv = HILDON_BANNER_GET_PRIVATE (self);
1063 label = GTK_LABEL (priv->label);
1064 existing_text = gtk_label_get_text (label);
1066 if (existing_text != NULL &&
1068 strcmp (existing_text, text) != 0)
1069 gtk_label_set_text (label, text);
1071 hildon_banner_check_position (GTK_WIDGET (self));
1075 * hildon_banner_set_markup:
1076 * @self: a #HildonBanner widget
1077 * @markup: a new text with Pango markup to display in the banner
1079 * Sets the text with markup that is displayed in the banner.
1083 hildon_banner_set_markup (HildonBanner *self,
1084 const gchar *markup)
1087 HildonBannerPrivate *priv;
1089 g_return_if_fail (HILDON_IS_BANNER (self));
1091 priv = HILDON_BANNER_GET_PRIVATE (self);
1094 label = GTK_LABEL (priv->label);
1095 gtk_label_set_markup (label, markup);
1097 hildon_banner_check_position (GTK_WIDGET(self));
1101 * hildon_banner_set_fraction:
1102 * @self: a #HildonBanner widget
1103 * @fraction: #gdouble
1105 * The fraction is the completion of progressbar,
1106 * the scale is from 0.0 to 1.0.
1107 * Sets the amount of fraction the progressbar has.
1111 hildon_banner_set_fraction (HildonBanner *self,
1114 HildonBannerPrivate *priv;
1116 g_return_if_fail (HILDON_IS_BANNER (self));
1117 priv = HILDON_BANNER_GET_PRIVATE (self);
1120 g_return_if_fail (GTK_IS_PROGRESS_BAR (priv->main_item));
1121 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (priv->main_item), fraction);
1125 * hildon_banner_set_timeout:
1126 * @self: a #HildonBanner widget
1127 * @timeout: timeout to set in miliseconds.
1129 * Sets the timeout on the banner. After the given amount of miliseconds
1130 * has elapsed the banner will go away. Note that settings this only makes
1131 * sense on the banners that are timed and that have not been yet displayed
1136 hildon_banner_set_timeout (HildonBanner *self,
1139 HildonBannerPrivate *priv;
1141 g_return_if_fail (HILDON_IS_BANNER (self));
1142 priv = HILDON_BANNER_GET_PRIVATE (self);
1145 priv->timeout = timeout;
1149 * hildon_banner_set_icon:
1150 * @self: a #HildonBanner widget
1151 * @icon_name: the name of icon to use. Can be %NULL for default icon
1153 * Sets the icon to be used in the banner.
1157 hildon_banner_set_icon (HildonBanner *self,
1158 const gchar *icon_name)
1160 HildonBannerPrivate *priv;
1162 g_return_if_fail (HILDON_IS_BANNER (self));
1163 priv = HILDON_BANNER_GET_PRIVATE (self);
1166 hildon_banner_ensure_child (self, NULL, 0, GTK_TYPE_IMAGE,
1167 "pixel-size", HILDON_ICON_PIXEL_SIZE_NOTE,
1168 "icon-name", icon_name ? icon_name : HILDON_BANNER_DEFAULT_ICON,
1174 * hildon_banner_set_icon_from_file:
1175 * @self: a #HildonBanner widget
1176 * @icon_file: the filename of icon to use. Can be %NULL for default icon
1178 * Sets the icon from its filename to be used in the banner.
1182 hildon_banner_set_icon_from_file (HildonBanner *self,
1183 const gchar *icon_file)
1185 HildonBannerPrivate *priv;
1187 g_return_if_fail (HILDON_IS_BANNER (self));
1188 priv = HILDON_BANNER_GET_PRIVATE (self);
1191 if (icon_file != NULL) {
1192 hildon_banner_ensure_child (self, NULL, 0, GTK_TYPE_IMAGE,
1193 "pixel-size", HILDON_ICON_PIXEL_SIZE_NOTE,
1198 hildon_banner_ensure_child (self, NULL, 0, GTK_TYPE_IMAGE,
1199 "pixel-size", HILDON_ICON_PIXEL_SIZE_NOTE,
1200 "icon-name", HILDON_BANNER_DEFAULT_ICON,