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
42 #include <X11/Xatom.h>
46 #include "hildon-banner.h"
47 #include "hildon-banner-private.h"
48 #include "hildon-defines.h"
50 /* position relative to the screen */
52 #define HILDON_BANNER_WINDOW_X 0
54 #define HILDON_BANNER_WINDOW_Y 73
56 #define HILDON_BANNER_WINDOW_FULLSCREEN_Y 20
60 #define HILDON_BANNER_PROGRESS_WIDTH 104
62 #define HILDON_BANNER_LABEL_MAX_TIMED 375
64 #define HILDON_BANNER_LABEL_MAX_PROGRESS 375 /*265*/
68 #define HILDON_BANNER_DEFAULT_TIMEOUT 3000
72 #define HILDON_BANNER_DEFAULT_ICON "qgn_note_infoprint"
74 #define HILDON_BANNER_DEFAULT_PROGRESS_ANIMATION "qgn_indi_pball_a"
84 static GtkWidget* global_timed_banner = NULL;
87 get_current_app_window (void);
90 check_fullscreen_state (Window window);
93 hildon_banner_timed_quark (void);
96 hildon_banner_bind_label_style (HildonBanner *self,
100 hildon_banner_timeout (gpointer data);
103 hildon_banner_clear_timeout (HildonBanner *self);
106 hildon_banner_ensure_timeout (HildonBanner *self);
109 hildon_banner_set_property (GObject *object,
115 hildon_banner_get_property (GObject *object,
121 hildon_banner_destroy (GtkObject *object);
124 hildon_banner_real_get_instance (GObject *window,
128 hildon_banner_constructor (GType type,
129 guint n_construct_params,
130 GObjectConstructParam *construct_params);
133 hildon_banner_finalize (GObject *object);
136 hildon_banner_button_press_event (GtkWidget* widget,
137 GdkEventButton* event);
140 hildon_banner_map_event (GtkWidget *widget,
143 hildon_banner_reset_wrap_state (HildonBanner *banner);
146 force_to_wrap_truncated (HildonBanner *banner);
149 hildon_banner_check_position (GtkWidget *widget);
152 hildon_banner_realize (GtkWidget *widget);
155 hildon_banner_class_init (HildonBannerClass *klass);
158 hildon_banner_init (HildonBanner *self);
161 hildon_banner_ensure_child (HildonBanner *self,
162 GtkWidget *user_widget,
165 const gchar *first_property,
169 hildon_banner_get_instance_for_widget (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 simulate_close (GtkWidget* widget)
282 gboolean result = FALSE;
284 /* If the banner is currently visible (it normally should),
285 we simulate clicking the close button of the window.
286 This allows applications to reuse the banner by prevent
288 if (GTK_WIDGET_DRAWABLE (widget))
290 GdkEvent *event = gdk_event_new (GDK_DELETE);
291 event->any.window = g_object_ref (widget->window);
292 event->any.send_event = FALSE;
293 result = gtk_widget_event (widget, event);
294 gdk_event_free (event);
301 hildon_banner_timeout (gpointer data)
304 gboolean continue_timeout = FALSE;
306 GDK_THREADS_ENTER ();
308 g_assert (HILDON_IS_BANNER (data));
310 widget = GTK_WIDGET (data);
311 g_object_ref (widget);
313 continue_timeout = simulate_close (widget);
315 if (! continue_timeout) {
316 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (data);
317 priv->timeout_id = 0;
318 gtk_widget_destroy (widget);
321 g_object_unref (widget);
323 GDK_THREADS_LEAVE ();
325 return continue_timeout;
329 hildon_banner_clear_timeout (HildonBanner *self)
331 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
334 if (priv->timeout_id != 0) {
335 g_source_remove (priv->timeout_id);
336 priv->timeout_id = 0;
344 hildon_banner_ensure_timeout (HildonBanner *self)
346 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
349 if (priv->timeout_id == 0 && priv->is_timed && priv->timeout > 0)
350 priv->timeout_id = g_timeout_add (priv->timeout,
351 hildon_banner_timeout, self);
355 hildon_banner_set_property (GObject *object,
361 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
367 priv->timeout = g_value_get_uint (value);
371 priv->is_timed = g_value_get_boolean (value);
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);
523 hildon_banner_reset_wrap_state (HILDON_BANNER (banner));
526 /* We restart possible timeouts for each new timed banner request */
527 if (timed && hildon_banner_clear_timeout (HILDON_BANNER (banner)))
528 hildon_banner_ensure_timeout (HILDON_BANNER(banner));
534 hildon_banner_finalize (GObject *object)
536 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
539 g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent);
542 G_OBJECT_CLASS (hildon_banner_parent_class)->finalize (object);
546 hildon_banner_button_press_event (GtkWidget* widget,
547 GdkEventButton* event)
549 gboolean result = simulate_close (widget);
552 /* signal emission not stopped - basically behave like
553 * gtk_main_do_event() for a delete event */
554 gtk_widget_destroy (widget);
560 /* We start the timer for timed notifications after the window appears on screen */
562 hildon_banner_map_event (GtkWidget *widget,
565 gboolean result = FALSE;
567 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->map_event)
568 result = GTK_WIDGET_CLASS (hildon_banner_parent_class)->map_event (widget, event);
570 hildon_banner_ensure_timeout (HILDON_BANNER(widget));
575 #if defined(MAEMO_GTK)
577 static GdkAtom atom_temporaries = GDK_NONE;
579 /* Do nothing for _GTK_DELETE_TEMPORARIES */
581 hildon_banner_client_event (GtkWidget *widget,
582 GdkEventClient *event)
584 gboolean handled = FALSE;
586 if (atom_temporaries == GDK_NONE)
587 atom_temporaries = gdk_atom_intern_static_string ("_GTK_DELETE_TEMPORARIES");
589 if (event->message_type == atom_temporaries)
599 hildon_banner_reset_wrap_state (HildonBanner *banner)
602 HildonBannerPrivate *priv;
604 priv = HILDON_BANNER_GET_PRIVATE (banner);
607 layout = gtk_label_get_layout (GTK_LABEL (priv->label));
609 pango_layout_set_width (layout, -1);
610 priv->has_been_wrapped = FALSE;
611 priv->has_been_truncated = FALSE;
613 gtk_widget_set_size_request (priv->label, -1, -1);
614 gtk_widget_set_size_request (GTK_WIDGET (banner), -1, -1);
617 /* force to wrap truncated label by setting explicit size request
618 * see N#27000 and G#329646 */
620 force_to_wrap_truncated (HildonBanner *banner)
624 int width_text, width_max;
627 PangoRectangle logical;
628 GtkRequisition requisition;
629 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (banner);
631 g_return_if_fail (priv);
633 label = GTK_LABEL (priv->label);
635 layout = gtk_label_get_layout (label);
637 pango_layout_get_extents (layout, NULL, &logical);
638 width_text = PANGO_PIXELS (logical.width);
640 width_max = priv->is_timed ? HILDON_BANNER_LABEL_MAX_TIMED
641 : HILDON_BANNER_LABEL_MAX_PROGRESS;
643 /* If the width of the label is going to exceed the maximum allowed
644 * width, enforce the maximum allowed width now.
646 if (priv->has_been_wrapped
647 || width_text >= width_max) {
648 /* Force wrapping by setting the maximum size */
651 priv->has_been_wrapped = TRUE;
654 /* Make the label update its layout; and update our layout pointer
655 * because the layout will be cleared and refreshed.
657 gtk_widget_set_size_request (GTK_WIDGET (label), width, height);
658 gtk_widget_size_request (GTK_WIDGET (label), &requisition);
660 layout = gtk_label_get_layout (label);
662 /* If the layout has now been wrapped and exceeds 3 lines, we truncate
663 * the rest of the label according to spec.
665 if (priv->has_been_truncated
666 || (pango_layout_is_wrapped (layout)
667 && pango_layout_get_line_count (layout) > 3)) {
670 pango_layout_get_extents (layout, NULL, &logical);
671 lines = pango_layout_get_line_count (layout);
673 /* This calculation assumes that the same font is used
674 * throughout the banner -- this is usually the case on maemo
676 * FIXME: Pango >= 1.20 has pango_layout_set_height().
678 height = (PANGO_PIXELS (logical.height) * 3) / lines + 1;
679 priv->has_been_truncated = TRUE;
682 /* Set the new width/height if applicable */
683 gtk_widget_set_size_request (GTK_WIDGET (label), width, height);
688 hildon_banner_check_position (GtkWidget *widget)
693 gtk_widget_set_size_request (widget, gdk_screen_width (), -1);
695 force_to_wrap_truncated (HILDON_BANNER(widget)); /* see N#27000 and G#329646 */
697 gtk_widget_size_request (widget, &req);
704 x = HILDON_BANNER_WINDOW_X;
706 y = check_fullscreen_state (get_current_app_window ()) ?
707 HILDON_BANNER_WINDOW_FULLSCREEN_Y : HILDON_BANNER_WINDOW_Y;
709 gtk_window_move (GTK_WINDOW (widget), x, y);
713 hildon_banner_realize (GtkWidget *widget)
717 const gchar *notification_type = "_HILDON_NOTIFICATION_TYPE_BANNER";
718 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (widget);
721 /* We let the parent to init widget->window before we need it */
722 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->realize)
723 GTK_WIDGET_CLASS (hildon_banner_parent_class)->realize (widget);
725 /* We use special hint to turn the banner into information notification. */
726 gdk_window_set_type_hint (widget->window, GDK_WINDOW_TYPE_HINT_NOTIFICATION);
727 gtk_window_set_transient_for (GTK_WINDOW (widget), (GtkWindow *) priv->parent);
729 hildon_banner_check_position (widget);
731 /* Set the _HILDON_NOTIFICATION_TYPE property so Matchbox places the window correctly */
732 display = gdk_drawable_get_display (widget->window);
733 atom = gdk_x11_get_xatom_by_name_for_display (display, "_HILDON_NOTIFICATION_TYPE");
734 XChangeProperty (GDK_WINDOW_XDISPLAY (widget->window), GDK_WINDOW_XID (widget->window),
735 atom, XA_STRING, 8, PropModeReplace, (guchar *) notification_type,
736 strlen (notification_type));
740 hildon_banner_class_init (HildonBannerClass *klass)
742 GObjectClass *object_class;
743 GtkWidgetClass *widget_class;
745 object_class = G_OBJECT_CLASS (klass);
746 widget_class = GTK_WIDGET_CLASS (klass);
748 /* Append private structure to class. This is more elegant than
749 on g_new based approach */
750 g_type_class_add_private (klass, sizeof (HildonBannerPrivate));
752 /* Override virtual methods */
753 object_class->constructor = hildon_banner_constructor;
754 object_class->finalize = hildon_banner_finalize;
755 object_class->set_property = hildon_banner_set_property;
756 object_class->get_property = hildon_banner_get_property;
757 GTK_OBJECT_CLASS (klass)->destroy = hildon_banner_destroy;
758 widget_class->map_event = hildon_banner_map_event;
759 widget_class->realize = hildon_banner_realize;
760 widget_class->button_press_event = hildon_banner_button_press_event;
761 #if defined(MAEMO_GTK)
762 widget_class->client_event = hildon_banner_client_event;
765 /* Install properties.
766 We need construct properties for singleton purposes */
769 * HildonBanner:parent-window:
771 * The window for which the banner will be singleton.
774 g_object_class_install_property (object_class, PROP_PARENT_WINDOW,
775 g_param_spec_object ("parent-window",
777 "The window for which the banner will be singleton",
778 GTK_TYPE_WINDOW, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
781 * HildonBanner:is-timed:
783 * Whether the banner is timed and goes away automatically.
786 g_object_class_install_property (object_class, PROP_IS_TIMED,
787 g_param_spec_boolean ("is-timed",
789 "Whether or not the notification goes away automatically "
790 "after the specified time has passed",
791 FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
794 * HildonBanner:timeout:
796 * The time before making the banner banner go away. This needs
797 * to be adjusted before the banner is mapped to the screen.
800 g_object_class_install_property (object_class, PROP_TIMEOUT,
801 g_param_spec_uint ("timeout",
803 "The time before making the banner banner go away",
806 HILDON_BANNER_DEFAULT_TIMEOUT,
807 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
811 hildon_banner_init (HildonBanner *self)
813 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
818 /* Initialize the common layout inside banner */
819 priv->layout = gtk_hbox_new (FALSE, HILDON_MARGIN_DEFAULT);
821 priv->label = g_object_new (GTK_TYPE_LABEL, NULL);
822 gtk_label_set_line_wrap (GTK_LABEL (priv->label), TRUE);
823 gtk_label_set_line_wrap_mode (GTK_LABEL (priv->label), PANGO_WRAP_WORD_CHAR);
825 gtk_container_set_border_width (GTK_CONTAINER (priv->layout), HILDON_MARGIN_DEFAULT);
826 gtk_container_add (GTK_CONTAINER (self), priv->layout);
827 gtk_box_pack_start (GTK_BOX (priv->layout), priv->label, TRUE, TRUE, 0);
829 gtk_window_set_accept_focus (GTK_WINDOW (self), FALSE);
831 #if defined(MAEMO_GTK)
832 gtk_window_set_is_temporary (GTK_WINDOW (self), TRUE);
835 hildon_banner_reset_wrap_state (self);
837 gtk_widget_add_events (GTK_WIDGET (self), GDK_BUTTON_PRESS_MASK);
840 /* Makes sure that icon/progress item contains the desired type
841 of item. If possible, tries to avoid creating a new widget but
842 reuses the existing one */
844 hildon_banner_ensure_child (HildonBanner *self,
845 GtkWidget *user_widget,
848 const gchar *first_property,
853 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
857 widget = priv->main_item;
858 va_start (args, first_property);
860 /* Reuse existing widget if possible */
861 if (! user_widget && G_TYPE_CHECK_INSTANCE_TYPE (widget, type))
863 g_object_set_valist (G_OBJECT (widget), first_property, args);
867 /* We have to abandon old content widget */
869 gtk_container_remove (GTK_CONTAINER (priv->layout), widget);
871 /* Use user provided widget or create a new one */
872 priv->main_item = widget = user_widget ?
873 user_widget : GTK_WIDGET (g_object_new_valist(type, first_property, args));
874 gtk_box_pack_start (GTK_BOX (priv->layout), widget, TRUE, TRUE, 0);
877 /* We make sure that the widget exists in desired position. Different
878 banners place this child widget to different places */
879 gtk_box_reorder_child (GTK_BOX (priv->layout), widget, pos);
883 /* Creates a new banner instance or uses an existing one */
885 hildon_banner_get_instance_for_widget (GtkWidget *widget,
890 window = widget ? gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW) : NULL;
891 return g_object_new (HILDON_TYPE_BANNER, "parent-window", window, "is-timed", timed, NULL);
895 * hildon_banner_show_information:
896 * @widget: the #GtkWidget that is the owner of the banner
897 * @icon_name: the name of icon to use. Can be %NULL for default icon
898 * @text: Text to display
900 * This function creates and displays an information banner that
901 * automatically goes away after certain time period. For each window
902 * in your application there can only be one timed banner, so if you
903 * spawn a new banner before the earlier one has timed out, the
904 * previous one will be replaced.
906 * Returns: The newly created banner
910 hildon_banner_show_information (GtkWidget *widget,
911 const gchar *icon_name,
914 HildonBanner *banner;
916 g_return_val_if_fail (icon_name == NULL || icon_name[0] != 0, NULL);
917 g_return_val_if_fail (text != NULL, NULL);
920 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
922 hildon_banner_set_text (banner, text);
923 hildon_banner_bind_label_style (banner, NULL);
925 /* Show the banner, since caller cannot do that */
926 gtk_widget_show_all (GTK_WIDGET (banner));
928 return (GtkWidget *) banner;
932 * hildon_banner_show_informationf:
933 * @widget: the #GtkWidget that is the owner of the banner
934 * @icon_name: the name of icon to use. Can be %NULL for default icon
935 * @format: a printf-like format string
936 * @Varargs: arguments for the format string
938 * A helper function for #hildon_banner_show_information with
941 * Returns: the newly created banner
944 hildon_banner_show_informationf (GtkWidget *widget,
945 const gchar *icon_name,
949 g_return_val_if_fail (format != NULL, NULL);
955 va_start (args, format);
956 message = g_strdup_vprintf (format, args);
959 banner = hildon_banner_show_information (widget, icon_name, message);
967 * hildon_banner_show_information_with_markup:
968 * @widget: the #GtkWidget that wants to display banner
969 * @icon_name: the name of icon to use. Can be %NULL for default icon.
970 * @markup: a markup string to display (see <link linkend="PangoMarkupFormat">Pango markup format</link>)
972 * This function creates and displays an information banner that
973 * automatically goes away after certain time period. For each window
974 * in your application there can only be one timed banner, so if you
975 * spawn a new banner before the earlier one has timed out, the
976 * previous one will be replaced.
978 * Returns: the newly created banner
982 hildon_banner_show_information_with_markup (GtkWidget *widget,
983 const gchar *icon_name,
986 HildonBanner *banner;
988 g_return_val_if_fail (icon_name == NULL || icon_name[0] != 0, NULL);
989 g_return_val_if_fail (markup != NULL, NULL);
992 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
994 hildon_banner_set_markup (banner, markup);
995 hildon_banner_bind_label_style (banner, NULL);
997 /* Show the banner, since caller cannot do that */
998 gtk_widget_show_all (GTK_WIDGET (banner));
1000 return (GtkWidget *) banner;
1004 * hildon_banner_show_animation:
1005 * @widget: the #GtkWidget that wants to display banner
1006 * @animation_name: The progress animation to use. You usually can just
1007 * pass %NULL for the default animation.
1008 * @text: the text to display.
1010 * Shows an animated progress notification. It's recommended not to try
1011 * to show more than one progress notification at a time, since
1012 * they will appear on top of each other. You can use progress
1013 * notifications with timed banners. In this case the banners are
1014 * located so that you can somehow see both.
1016 * Please note that banners are destroyed automatically once the
1017 * window they are attached to is closed. The pointer that you
1018 * receive with this function do not contain additional references,
1019 * so it can become invalid without warning (this is true for
1020 * all toplevel windows in gtk). To make sure that the banner do not disapear
1021 * automatically, you can separately ref the return value (this
1022 * doesn't prevent the banner from disappearing, but the object it just
1023 * not finalized). In this case you have to call both #gtk_widget_destroy
1024 * followed by #g_object_unref (in this order).
1026 * Returns: a #HildonBanner widget. You must call #gtk_widget_destroy
1027 * once you are done with the banner.
1031 hildon_banner_show_animation (GtkWidget *widget,
1032 const gchar *animation_name,
1035 HildonBanner *banner;
1036 GtkIconTheme *theme;
1038 GtkWidget *image_widget;
1039 const gchar *filename;
1041 g_return_val_if_fail (animation_name == NULL || animation_name[0] != 0, NULL);
1042 g_return_val_if_fail (text != NULL, NULL);
1044 /* Find out which animation to use */
1045 theme = gtk_icon_theme_get_default ();
1046 info = gtk_icon_theme_lookup_icon (theme, animation_name ? /* FIXME: consider using: gtk_icon_theme_load_icon() */
1047 animation_name : HILDON_BANNER_DEFAULT_PROGRESS_ANIMATION,
1048 HILDON_ICON_SIZE_NOTE, 0);
1050 /* Try to load animation. One could try to optimize this
1051 to avoid loading the default animation during each call */
1053 filename = gtk_icon_info_get_filename (info);
1054 image_widget = gtk_image_new_from_file (filename);
1055 gtk_icon_info_free (info);
1057 g_warning ("Icon theme lookup for icon failed!");
1058 image_widget = NULL;
1061 /* Prepare banner */
1062 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
1063 hildon_banner_ensure_child (banner, image_widget, 0,
1064 GTK_TYPE_IMAGE, "yalign", 0.0, NULL);
1066 hildon_banner_set_text (banner, text);
1067 hildon_banner_bind_label_style (banner, NULL);
1070 gtk_widget_show_all (GTK_WIDGET (banner));
1072 return (GtkWidget *) banner;
1076 * hildon_banner_show_progress:
1077 * @widget: the #GtkWidget that wants to display banner
1078 * @bar: Progressbar to use. You usually can just pass %NULL, unless
1079 * you want somehow customized progress bar.
1080 * @text: text to display.
1082 * Shows progress notification. See #hildon_banner_show_animation
1083 * for more information.
1085 * Returns: a #HildonBanner widget. You must call #gtk_widget_destroy
1086 * once you are done with the banner.
1090 hildon_banner_show_progress (GtkWidget *widget,
1091 GtkProgressBar *bar,
1094 HildonBanner *banner;
1095 HildonBannerPrivate *priv;
1097 g_return_val_if_fail (bar == NULL || GTK_IS_PROGRESS_BAR (bar), NULL);
1098 g_return_val_if_fail (text != NULL, NULL);
1101 /* Prepare banner */
1102 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
1103 priv = HILDON_BANNER_GET_PRIVATE (banner);
1105 hildon_banner_ensure_child (banner, (GtkWidget *) bar, -1, GTK_TYPE_PROGRESS_BAR, NULL);
1107 gtk_widget_set_size_request (priv->main_item,
1108 HILDON_BANNER_PROGRESS_WIDTH, -1);
1110 hildon_banner_set_text (banner, text);
1111 hildon_banner_bind_label_style (banner, NULL);
1113 /* Show the banner */
1114 gtk_widget_show_all (GTK_WIDGET (banner));
1116 return GTK_WIDGET (banner);
1120 * hildon_banner_set_text:
1121 * @self: a #HildonBanner widget
1122 * @text: a new text to display in banner
1124 * Sets the text that is displayed in the banner.
1128 hildon_banner_set_text (HildonBanner *self,
1132 HildonBannerPrivate *priv;
1133 const gchar *existing_text;
1135 g_return_if_fail (HILDON_IS_BANNER (self));
1137 priv = HILDON_BANNER_GET_PRIVATE (self);
1140 label = GTK_LABEL (priv->label);
1141 existing_text = gtk_label_get_text (label);
1143 if (existing_text != NULL &&
1145 strcmp (existing_text, text) != 0) {
1146 gtk_label_set_text (label, text);
1147 hildon_banner_reset_wrap_state (self);
1150 hildon_banner_check_position (GTK_WIDGET (self));
1154 * hildon_banner_set_markup:
1155 * @self: a #HildonBanner widget
1156 * @markup: a new text with Pango markup to display in the banner
1158 * Sets the text with markup that is displayed in the banner.
1162 hildon_banner_set_markup (HildonBanner *self,
1163 const gchar *markup)
1166 HildonBannerPrivate *priv;
1168 g_return_if_fail (HILDON_IS_BANNER (self));
1170 priv = HILDON_BANNER_GET_PRIVATE (self);
1173 label = GTK_LABEL (priv->label);
1174 gtk_label_set_markup (label, markup);
1176 hildon_banner_reset_wrap_state (self);
1178 hildon_banner_check_position (GTK_WIDGET(self));
1182 * hildon_banner_set_fraction:
1183 * @self: a #HildonBanner widget
1184 * @fraction: #gdouble
1186 * The fraction is the completion of progressbar,
1187 * the scale is from 0.0 to 1.0.
1188 * Sets the amount of fraction the progressbar has.
1192 hildon_banner_set_fraction (HildonBanner *self,
1195 HildonBannerPrivate *priv;
1197 g_return_if_fail (HILDON_IS_BANNER (self));
1198 priv = HILDON_BANNER_GET_PRIVATE (self);
1201 g_return_if_fail (GTK_IS_PROGRESS_BAR (priv->main_item));
1202 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (priv->main_item), fraction);
1206 * hildon_banner_set_timeout:
1207 * @self: a #HildonBanner widget
1208 * @timeout: timeout to set in miliseconds.
1210 * Sets the timeout on the banner. After the given amount of miliseconds
1211 * has elapsed the banner will go away. Note that settings this only makes
1212 * sense on the banners that are timed and that have not been yet displayed
1217 hildon_banner_set_timeout (HildonBanner *self,
1220 HildonBannerPrivate *priv;
1222 g_return_if_fail (HILDON_IS_BANNER (self));
1223 priv = HILDON_BANNER_GET_PRIVATE (self);
1226 priv->timeout = timeout;
1230 * hildon_banner_set_icon:
1231 * @self: a #HildonBanner widget
1232 * @icon_name: the name of icon to use. Can be %NULL for default icon
1234 * Sets the icon to be used in the banner.
1238 hildon_banner_set_icon (HildonBanner *self,
1239 const gchar *icon_name)
1241 HildonBannerPrivate *priv;
1243 g_return_if_fail (HILDON_IS_BANNER (self));
1244 priv = HILDON_BANNER_GET_PRIVATE (self);
1247 hildon_banner_ensure_child (self, NULL, 0, GTK_TYPE_IMAGE,
1248 "pixel-size", HILDON_ICON_PIXEL_SIZE_NOTE,
1249 "icon-name", icon_name ? icon_name : HILDON_BANNER_DEFAULT_ICON,
1255 * hildon_banner_set_icon_from_file:
1256 * @self: a #HildonBanner widget
1257 * @icon_file: the filename of icon to use. Can be %NULL for default icon
1259 * Sets the icon from its filename to be used in the banner.
1263 hildon_banner_set_icon_from_file (HildonBanner *self,
1264 const gchar *icon_file)
1266 HildonBannerPrivate *priv;
1268 g_return_if_fail (HILDON_IS_BANNER (self));
1269 priv = HILDON_BANNER_GET_PRIVATE (self);
1272 if (icon_file != NULL) {
1273 hildon_banner_ensure_child (self, NULL, 0, GTK_TYPE_IMAGE,
1274 "pixel-size", HILDON_ICON_PIXEL_SIZE_NOTE,
1279 hildon_banner_ensure_child (self, NULL, 0, GTK_TYPE_IMAGE,
1280 "pixel-size", HILDON_ICON_PIXEL_SIZE_NOTE,
1281 "icon-name", HILDON_BANNER_DEFAULT_ICON,