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 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (data);
308 priv->timeout_id = 0;
309 gtk_widget_destroy (widget);
312 g_object_unref (widget);
314 GDK_THREADS_LEAVE ();
316 return continue_timeout;
320 hildon_banner_clear_timeout (HildonBanner *self)
322 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
325 if (priv->timeout_id != 0) {
326 g_source_remove (priv->timeout_id);
327 priv->timeout_id = 0;
335 hildon_banner_ensure_timeout (HildonBanner *self)
337 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
340 if (priv->timeout_id == 0 && priv->is_timed && priv->timeout > 0)
341 priv->timeout_id = g_timeout_add (priv->timeout,
342 hildon_banner_timeout, self);
346 hildon_banner_set_property (GObject *object,
353 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
359 priv->timeout = g_value_get_uint (value);
363 priv->is_timed = g_value_get_boolean (value);
365 /* Timed and progress notifications have different
366 pixel size values for text.
367 We force to use requisition size for timed banners
368 in order to avoid resize problems when reusing the
369 window (see bug #24339) */
370 geom.max_width = priv->is_timed ? -1
371 : HILDON_BANNER_LABEL_MAX_PROGRESS;
372 geom.max_height = -1;
373 gtk_window_set_geometry_hints (GTK_WINDOW (object),
374 priv->label, &geom, GDK_HINT_MAX_SIZE);
377 case PROP_PARENT_WINDOW:
378 window = g_value_get_object (value);
380 g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent);
383 gtk_window_set_transient_for (GTK_WINDOW (object), (GtkWindow *) window);
384 priv->parent = (GtkWindow *) window;
387 gtk_window_set_destroy_with_parent (GTK_WINDOW (object), TRUE);
388 g_object_add_weak_pointer(G_OBJECT (window), (gpointer) &priv->parent);
394 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
400 hildon_banner_get_property (GObject *object,
405 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
411 g_value_set_uint (value, priv->timeout);
415 g_value_set_boolean (value, priv->is_timed);
418 case PROP_PARENT_WINDOW:
419 g_value_set_object (value, gtk_window_get_transient_for (GTK_WINDOW (object)));
423 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
429 hildon_banner_destroy (GtkObject *object)
431 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
435 GObject *parent_window = (GObject *) priv->parent;
437 g_assert (HILDON_IS_BANNER (object));
438 self = HILDON_BANNER (object);
440 /* Drop possible global pointer. That can hold reference to us */
441 if ((gpointer) object == (gpointer) global_timed_banner) {
442 global_timed_banner = NULL;
443 g_object_unref (object);
446 /* Remove the data from parent window for timed banners. Those hold reference */
447 if (priv->is_timed && parent_window != NULL) {
448 g_object_set_qdata (parent_window, hildon_banner_timed_quark (), NULL);
451 (void) hildon_banner_clear_timeout (self);
453 if (GTK_OBJECT_CLASS (hildon_banner_parent_class)->destroy)
454 GTK_OBJECT_CLASS (hildon_banner_parent_class)->destroy (object);
457 /* Search a previous banner instance */
459 hildon_banner_real_get_instance (GObject *window,
463 /* If we have a parent window, the previous instance is stored there */
465 return g_object_get_qdata(window, hildon_banner_timed_quark ());
468 /* System notification instance is stored into global pointer */
469 return (GObject *) global_timed_banner;
472 /* Non-timed banners are normal (non-singleton) objects */
476 /* By overriding constructor we force timed banners to be
477 singletons for each window */
479 hildon_banner_constructor (GType type,
480 guint n_construct_params,
481 GObjectConstructParam *construct_params)
483 GObject *banner, *window = NULL;
484 gboolean timed = FALSE;
487 /* Search banner type information from parameters in order
488 to locate the possible previous banner instance. */
489 for (i = 0; i < n_construct_params; i++)
491 if (strcmp(construct_params[i].pspec->name, "parent-window") == 0)
492 window = g_value_get_object (construct_params[i].value);
493 else if (strcmp(construct_params[i].pspec->name, "is-timed") == 0)
494 timed = g_value_get_boolean (construct_params[i].value);
497 /* Try to get a previous instance if such exists */
498 banner = hildon_banner_real_get_instance (window, timed);
501 /* We have to create a new banner */
502 banner = G_OBJECT_CLASS (hildon_banner_parent_class)->constructor (type, n_construct_params, construct_params);
504 /* Store the newly created singleton instance either into parent
505 window data or into global variables. */
508 g_object_set_qdata_full (G_OBJECT (window), hildon_banner_timed_quark (),
509 g_object_ref (banner), g_object_unref);
511 g_assert (global_timed_banner == NULL);
512 global_timed_banner = g_object_ref (banner);
517 /* FIXME: This is a hack! We have to manually freeze
518 notifications. This is normally done by g_object_init, but we
519 are not going to call that. g_object_newv will otherwise give
520 a critical like this:
522 GLIB CRITICAL ** GLib-GObject - g_object_notify_queue_thaw:
523 assertion `nqueue->freeze_count > 0' failed */
525 g_object_freeze_notify (banner);
528 /* We restart possible timeouts for each new timed banner request */
529 if (timed && hildon_banner_clear_timeout (HILDON_BANNER (banner)))
530 hildon_banner_ensure_timeout (HILDON_BANNER(banner));
536 hildon_banner_finalize (GObject *object)
538 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
541 g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent);
544 G_OBJECT_CLASS (hildon_banner_parent_class)->finalize (object);
547 /* We start the timer for timed notifications after the window appears on screen */
549 hildon_banner_map_event (GtkWidget *widget,
552 gboolean result = FALSE;
554 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->map_event)
555 result = GTK_WIDGET_CLASS (hildon_banner_parent_class)->map_event (widget, event);
557 hildon_banner_ensure_timeout (HILDON_BANNER(widget));
562 #if defined(MAEMO_GTK)
564 static GdkAtom atom_temporaries = GDK_NONE;
566 /* Do nothing for _GTK_DELETE_TEMPORARIES */
568 hildon_banner_client_event (GtkWidget *widget,
569 GdkEventClient *event)
571 gboolean handled = FALSE;
573 if (atom_temporaries == GDK_NONE)
574 atom_temporaries = gdk_atom_intern_static_string ("_GTK_DELETE_TEMPORARIES");
576 if (event->message_type == atom_temporaries)
585 /* force to wrap truncated label by setting explicit size request
586 * see N#27000 and G#329646 */
588 force_to_wrap_truncated (HildonBanner *banner)
592 int width_text, width_max;
594 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (banner);
597 label = GTK_LABEL (priv->label);
599 layout = gtk_label_get_layout (label);
600 width_text = PANGO_PIXELS(pango_layout_get_width (layout));
601 /* = width to which the lines of the PangoLayout should be wrapped */
603 width_max = priv->is_timed ? HILDON_BANNER_LABEL_MAX_TIMED
604 : HILDON_BANNER_LABEL_MAX_PROGRESS;
606 if (width_text >= width_max) {
607 /* explicitly request maximum size to force wrapping */
608 PangoRectangle logical;
610 pango_layout_set_width (layout, width_max * PANGO_SCALE);
611 pango_layout_get_extents (layout, NULL, &logical);
613 width = PANGO_PIXELS (logical.width);
616 /* use fixed width when wrapping or natural one otherwise */
617 gtk_widget_set_size_request (GTK_WIDGET (label), width, -1);
622 hildon_banner_check_position (GtkWidget *widget)
627 force_to_wrap_truncated (HILDON_BANNER(widget)); /* see N#27000 and G#329646 */
629 gtk_widget_size_request (widget, &req);
636 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
637 x = HILDON_BANNER_WINDOW_X;
639 x = gdk_screen_width() - HILDON_BANNER_WINDOW_X - req.width;
641 y = check_fullscreen_state (get_current_app_window ()) ?
642 HILDON_BANNER_WINDOW_FULLSCREEN_Y : HILDON_BANNER_WINDOW_Y;
644 gtk_window_move (GTK_WINDOW (widget), x, y);
648 hildon_banner_realize (GtkWidget *widget)
650 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (widget);
653 /* We let the parent to init widget->window before we need it */
654 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->realize)
655 GTK_WIDGET_CLASS (hildon_banner_parent_class)->realize (widget);
657 /* We use special hint to turn the banner into information notification. */
658 gdk_window_set_type_hint (widget->window, GDK_WINDOW_TYPE_HINT_NOTIFICATION);
659 gtk_window_set_transient_for (GTK_WINDOW (widget), (GtkWindow *) priv->parent);
661 hildon_banner_check_position (widget);
665 hildon_banner_class_init (HildonBannerClass *klass)
667 GObjectClass *object_class;
668 GtkWidgetClass *widget_class;
670 object_class = G_OBJECT_CLASS (klass);
671 widget_class = GTK_WIDGET_CLASS (klass);
673 /* Append private structure to class. This is more elegant than
674 on g_new based approach */
675 g_type_class_add_private (klass, sizeof (HildonBannerPrivate));
677 /* Override virtual methods */
678 object_class->constructor = hildon_banner_constructor;
679 object_class->finalize = hildon_banner_finalize;
680 object_class->set_property = hildon_banner_set_property;
681 object_class->get_property = hildon_banner_get_property;
682 GTK_OBJECT_CLASS (klass)->destroy = hildon_banner_destroy;
683 widget_class->map_event = hildon_banner_map_event;
684 widget_class->realize = hildon_banner_realize;
685 #if defined(MAEMO_GTK)
686 widget_class->client_event = hildon_banner_client_event;
689 /* Install properties.
690 We need construct properties for singleton purposes */
693 * HildonBanner:parent-window:
695 * The window for which the banner will be singleton.
698 g_object_class_install_property (object_class, PROP_PARENT_WINDOW,
699 g_param_spec_object ("parent-window",
701 "The window for which the banner will be singleton",
702 GTK_TYPE_WINDOW, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
705 * HildonBanner:is-timed:
707 * Whether the banner is timed and goes away automatically.
710 g_object_class_install_property (object_class, PROP_IS_TIMED,
711 g_param_spec_boolean ("is-timed",
713 "Whether or not the notification goes away automatically "
714 "after the specified time has passed",
715 FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
718 * HildonBanner:timeout:
720 * The time before making the banner banner go away. This needs
721 * to be adjusted before the banner is mapped to the screen.
724 g_object_class_install_property (object_class, PROP_TIMEOUT,
725 g_param_spec_uint ("timeout",
727 "The time before making the banner banner go away",
730 HILDON_BANNER_DEFAULT_TIMEOUT,
731 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
735 hildon_banner_init (HildonBanner *self)
737 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
742 /* Initialize the common layout inside banner */
743 priv->layout = gtk_hbox_new (FALSE, HILDON_MARGIN_DEFAULT);
745 priv->label = g_object_new (GTK_TYPE_LABEL, NULL);
746 gtk_label_set_line_wrap (GTK_LABEL (priv->label), TRUE);
748 gtk_container_set_border_width (GTK_CONTAINER (priv->layout), HILDON_MARGIN_DEFAULT);
749 gtk_container_add (GTK_CONTAINER (self), priv->layout);
750 gtk_box_pack_start (GTK_BOX (priv->layout), priv->label, TRUE, TRUE, 0);
752 gtk_window_set_accept_focus (GTK_WINDOW (self), FALSE);
754 #if defined(MAEMO_GTK)
755 gtk_window_set_is_temporary (GTK_WINDOW (self), TRUE);
759 /* Makes sure that icon/progress item contains the desired type
760 of item. If possible, tries to avoid creating a new widget but
761 reuses the existing one */
763 hildon_banner_ensure_child (HildonBanner *self,
764 GtkWidget *user_widget,
767 const gchar *first_property,
772 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
776 widget = priv->main_item;
777 va_start (args, first_property);
779 /* Reuse existing widget if possible */
780 if (! user_widget && G_TYPE_CHECK_INSTANCE_TYPE (widget, type))
782 g_object_set_valist (G_OBJECT (widget), first_property, args);
786 /* We have to abandon old content widget */
788 gtk_container_remove (GTK_CONTAINER (priv->layout), widget);
790 /* Use user provided widget or create a new one */
791 priv->main_item = widget = user_widget ?
792 user_widget : GTK_WIDGET (g_object_new_valist(type, first_property, args));
793 gtk_box_pack_start (GTK_BOX (priv->layout), widget, TRUE, TRUE, 0);
796 /* We make sure that the widget exists in desired position. Different
797 banners place this child widget to different places */
798 gtk_box_reorder_child (GTK_BOX (priv->layout), widget, pos);
802 /* Creates a new banner instance or uses an existing one */
804 hildon_banner_get_instance_for_widget (GtkWidget *widget,
809 window = widget ? gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW) : NULL;
810 return g_object_new (HILDON_TYPE_BANNER, "parent-window", window, "is-timed", timed, NULL);
814 * hildon_banner_show_information:
815 * @widget: the #GtkWidget that is the owner of the banner
816 * @icon_name: the name of icon to use. Can be %NULL for default icon
817 * @text: Text to display
819 * This function creates and displays an information banner that
820 * automatically goes away after certain time period. For each window
821 * in your application there can only be one timed banner, so if you
822 * spawn a new banner before the earlier one has timed out, the
823 * previous one will be replaced.
825 * Returns: The newly created banner
829 hildon_banner_show_information (GtkWidget *widget,
830 const gchar *icon_name,
833 HildonBanner *banner;
835 g_return_val_if_fail (icon_name == NULL || icon_name[0] != 0, NULL);
836 g_return_val_if_fail (text != NULL, NULL);
839 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
840 hildon_banner_ensure_child (banner, NULL, 0, GTK_TYPE_IMAGE,
841 "pixel-size", HILDON_ICON_PIXEL_SIZE_NOTE,
842 "icon-name", icon_name ? icon_name : HILDON_BANNER_DEFAULT_ICON,
846 hildon_banner_set_text (banner, text);
847 hildon_banner_bind_label_style (banner, NULL);
849 /* Show the banner, since caller cannot do that */
850 gtk_widget_show_all (GTK_WIDGET (banner));
851 gtk_window_present (GTK_WINDOW (banner));
853 return (GtkWidget *) banner;
857 * hildon_banner_show_informationf:
858 * @widget: the #GtkWidget that is the owner of the banner
859 * @icon_name: the name of icon to use. Can be %NULL for default icon
860 * @format: a printf-like format string
861 * @Varargs: arguments for the format string
863 * A helper function for #hildon_banner_show_information with
866 * Returns: the newly created banner
869 hildon_banner_show_informationf (GtkWidget *widget,
870 const gchar *icon_name,
874 g_return_val_if_fail (format != NULL, NULL);
880 va_start (args, format);
881 message = g_strdup_vprintf (format, args);
884 banner = hildon_banner_show_information (widget, icon_name, message);
892 * hildon_banner_show_information_with_markup:
893 * @widget: the #GtkWidget that wants to display banner
894 * @icon_name: the name of icon to use. Can be %NULL for default icon.
895 * @markup: a markup string to display (see <link linkend="PangoMarkupFormat">Pango markup format</link>)
897 * This function creates and displays an information banner that
898 * automatically goes away after certain time period. For each window
899 * in your application there can only be one timed banner, so if you
900 * spawn a new banner before the earlier one has timed out, the
901 * previous one will be replaced.
903 * Returns: the newly created banner
907 hildon_banner_show_information_with_markup (GtkWidget *widget,
908 const gchar *icon_name,
911 HildonBanner *banner;
913 g_return_val_if_fail (icon_name == NULL || icon_name[0] != 0, NULL);
914 g_return_val_if_fail (markup != NULL, NULL);
917 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
919 hildon_banner_ensure_child (banner, NULL, 0, GTK_TYPE_IMAGE,
920 "pixel-size", HILDON_ICON_PIXEL_SIZE_NOTE,
921 "icon-name", icon_name ? icon_name : HILDON_BANNER_DEFAULT_ICON,
925 hildon_banner_set_markup (banner, markup);
926 hildon_banner_bind_label_style (banner, NULL);
928 /* Show the banner, since caller cannot do that */
929 gtk_widget_show_all (GTK_WIDGET (banner));
930 gtk_window_present (GTK_WINDOW (banner));
932 return (GtkWidget *) banner;
936 * hildon_banner_show_animation:
937 * @widget: the #GtkWidget that wants to display banner
938 * @animation_name: The progress animation to use. You usually can just
939 * pass %NULL for the default animation.
940 * @text: the text to display.
942 * Shows an animated progress notification. It's recommended not to try
943 * to show more than one progress notification at a time, since
944 * they will appear on top of each other. You can use progress
945 * notifications with timed banners. In this case the banners are
946 * located so that you can somehow see both.
948 * Please note that banners are destroyed automatically once the
949 * window they are attached to is closed. The pointer that you
950 * receive with this function do not contain additional references,
951 * so it can become invalid without warning (this is true for
952 * all toplevel windows in gtk). To make sure that the banner do not disapear
953 * automatically, you can separately ref the return value (this
954 * doesn't prevent the banner from disappearing, but the object it just
955 * not finalized). In this case you have to call both #gtk_widget_destroy
956 * followed by #g_object_unref (in this order).
958 * Returns: a #HildonBanner widget. You must call #gtk_widget_destroy
959 * once you are done with the banner.
963 hildon_banner_show_animation (GtkWidget *widget,
964 const gchar *animation_name,
967 HildonBanner *banner;
970 GtkWidget *image_widget;
971 const gchar *filename;
973 g_return_val_if_fail (animation_name == NULL || animation_name[0] != 0, NULL);
974 g_return_val_if_fail (text != NULL, NULL);
976 /* Find out which animation to use */
977 theme = gtk_icon_theme_get_default ();
978 info = gtk_icon_theme_lookup_icon (theme, animation_name ? /* FIXME: consider using: gtk_icon_theme_load_icon() */
979 animation_name : HILDON_BANNER_DEFAULT_PROGRESS_ANIMATION,
980 HILDON_ICON_SIZE_NOTE, 0);
982 /* Try to load animation. One could try to optimize this
983 to avoid loading the default animation during each call */
985 filename = gtk_icon_info_get_filename (info);
986 image_widget = gtk_image_new_from_file (filename);
987 gtk_icon_info_free (info);
989 g_warning ("Icon theme lookup for icon failed!");
994 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
995 hildon_banner_ensure_child (banner, image_widget, 0,
996 GTK_TYPE_IMAGE, "yalign", 0.0, NULL);
998 hildon_banner_set_text (banner, text);
999 hildon_banner_bind_label_style (banner, NULL);
1002 gtk_widget_show_all (GTK_WIDGET (banner));
1003 gtk_window_present (GTK_WINDOW (banner));
1005 return (GtkWidget *) banner;
1009 * hildon_banner_show_progress:
1010 * @widget: the #GtkWidget that wants to display banner
1011 * @bar: Progressbar to use. You usually can just pass %NULL, unless
1012 * you want somehow customized progress bar.
1013 * @text: text to display.
1015 * Shows progress notification. See #hildon_banner_show_animation
1016 * for more information.
1018 * Returns: a #HildonBanner widget. You must call #gtk_widget_destroy
1019 * once you are done with the banner.
1023 hildon_banner_show_progress (GtkWidget *widget,
1024 GtkProgressBar *bar,
1027 HildonBanner *banner;
1028 HildonBannerPrivate *priv;
1030 g_return_val_if_fail (bar == NULL || GTK_IS_PROGRESS_BAR (bar), NULL);
1031 g_return_val_if_fail (text != NULL, NULL);
1034 /* Prepare banner */
1035 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
1036 priv = HILDON_BANNER_GET_PRIVATE (banner);
1038 hildon_banner_ensure_child (banner, (GtkWidget *) bar, -1, GTK_TYPE_PROGRESS_BAR, NULL);
1040 gtk_widget_set_size_request (priv->main_item,
1041 HILDON_BANNER_PROGRESS_WIDTH, -1);
1043 hildon_banner_set_text (banner, text);
1044 hildon_banner_bind_label_style (banner, NULL);
1046 /* Show the banner */
1047 gtk_widget_show_all (GTK_WIDGET (banner));
1048 gtk_window_present (GTK_WINDOW (banner));
1050 return GTK_WIDGET (banner);
1054 * hildon_banner_set_text:
1055 * @self: a #HildonBanner widget
1056 * @text: a new text to display in banner
1058 * Sets the text that is displayed in the banner.
1062 hildon_banner_set_text (HildonBanner *self,
1066 HildonBannerPrivate *priv;
1067 const gchar *existing_text;
1069 g_return_if_fail (HILDON_IS_BANNER (self));
1071 priv = HILDON_BANNER_GET_PRIVATE (self);
1074 label = GTK_LABEL (priv->label);
1075 existing_text = gtk_label_get_text (label);
1077 if (existing_text != NULL &&
1079 strcmp (existing_text, text) != 0)
1080 gtk_label_set_text (label, text);
1082 hildon_banner_check_position (GTK_WIDGET (self));
1086 * hildon_banner_set_markup:
1087 * @self: a #HildonBanner widget
1088 * @markup: a new text with Pango markup to display in the banner
1090 * Sets the text with markup that is displayed in the banner.
1094 hildon_banner_set_markup (HildonBanner *self,
1095 const gchar *markup)
1098 HildonBannerPrivate *priv;
1100 g_return_if_fail (HILDON_IS_BANNER (self));
1102 priv = HILDON_BANNER_GET_PRIVATE (self);
1105 label = GTK_LABEL (priv->label);
1106 gtk_label_set_markup (label, markup);
1108 hildon_banner_check_position (GTK_WIDGET(self));
1112 * hildon_banner_set_fraction:
1113 * @self: a #HildonBanner widget
1114 * @fraction: #gdouble
1116 * The fraction is the completion of progressbar,
1117 * the scale is from 0.0 to 1.0.
1118 * Sets the amount of fraction the progressbar has.
1122 hildon_banner_set_fraction (HildonBanner *self,
1125 HildonBannerPrivate *priv;
1127 g_return_if_fail (HILDON_IS_BANNER (self));
1128 priv = HILDON_BANNER_GET_PRIVATE (self);
1131 g_return_if_fail (GTK_IS_PROGRESS_BAR (priv->main_item));
1132 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (priv->main_item), fraction);
1136 * hildon_banner_set_timeout:
1137 * @self: a #HildonBanner widget
1138 * @timeout: timeout to set in miliseconds.
1140 * Sets the timeout on the banner. After the given amount of miliseconds
1141 * has elapsed the banner will go away. Note that settings this only makes
1142 * sense on the banners that are timed and that have not been yet displayed
1147 hildon_banner_set_timeout (HildonBanner *self,
1150 HildonBannerPrivate *priv;
1152 g_return_if_fail (HILDON_IS_BANNER (self));
1153 priv = HILDON_BANNER_GET_PRIVATE (self);
1156 priv->timeout = timeout;
1160 * hildon_banner_set_icon:
1161 * @self: a #HildonBanner widget
1162 * @icon_name: the name of icon to use. Can be %NULL for default icon
1164 * Sets the icon to be used in the banner.
1168 hildon_banner_set_icon (HildonBanner *self,
1169 const gchar *icon_name)
1171 HildonBannerPrivate *priv;
1173 g_return_if_fail (HILDON_IS_BANNER (self));
1174 priv = HILDON_BANNER_GET_PRIVATE (self);
1177 hildon_banner_ensure_child (self, NULL, 0, GTK_TYPE_IMAGE,
1178 "pixel-size", HILDON_ICON_PIXEL_SIZE_NOTE,
1179 "icon-name", icon_name ? icon_name : HILDON_BANNER_DEFAULT_ICON,
1185 * hildon_banner_set_icon_from_file:
1186 * @self: a #HildonBanner widget
1187 * @icon_file: the filename of icon to use. Can be %NULL for default icon
1189 * Sets the icon from its filename to be used in the banner.
1193 hildon_banner_set_icon_from_file (HildonBanner *self,
1194 const gchar *icon_file)
1196 HildonBannerPrivate *priv;
1198 g_return_if_fail (HILDON_IS_BANNER (self));
1199 priv = HILDON_BANNER_GET_PRIVATE (self);
1202 if (icon_file != NULL) {
1203 hildon_banner_ensure_child (self, NULL, 0, GTK_TYPE_IMAGE,
1204 "pixel-size", HILDON_ICON_PIXEL_SIZE_NOTE,
1209 hildon_banner_ensure_child (self, NULL, 0, GTK_TYPE_IMAGE,
1210 "pixel-size", HILDON_ICON_PIXEL_SIZE_NOTE,
1211 "icon-name", HILDON_BANNER_DEFAULT_ICON,