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_button_press_event (GtkWidget* widget,
138 GdkEventButton* event);
141 hildon_banner_map_event (GtkWidget *widget,
144 hildon_banner_reset_wrap_state (HildonBanner *banner);
147 force_to_wrap_truncated (HildonBanner *banner);
150 hildon_banner_check_position (GtkWidget *widget);
153 hildon_banner_realize (GtkWidget *widget);
156 hildon_banner_class_init (HildonBannerClass *klass);
159 hildon_banner_init (HildonBanner *self);
162 hildon_banner_ensure_child (HildonBanner *self,
163 GtkWidget *user_widget,
166 const gchar *first_property,
170 hildon_banner_get_instance_for_widget (GtkWidget *widget,
173 G_DEFINE_TYPE (HildonBanner, hildon_banner, GTK_TYPE_WINDOW)
175 /* copy/paste from old infoprint implementation: Use matchbox
176 properties to find the topmost application window */
178 get_current_app_window (void)
185 Atom atom_current_app_window = gdk_x11_get_xatom_by_name ("_MB_CURRENT_APP_WINDOW");
187 Window win_result = None;
188 guchar *data_return = NULL;
190 status = XGetWindowProperty (GDK_DISPLAY(), GDK_ROOT_WINDOW (),
191 atom_current_app_window, 0L, 16L,
192 0, XA_WINDOW, &realType, &format,
196 if (status == Success && realType == XA_WINDOW && format == 32 && n == 1 && data_return != NULL)
198 win_result = ((Window*) data_return)[0];
207 /* Checks if a window is in fullscreen state or not. This
208 information is needed when banners are positioned on screen.
209 copy/paste from old infoprint implementation. */
211 check_fullscreen_state (Window window)
215 int format, status, i;
216 guchar *data_return = NULL;
219 Atom atom_window_state = gdk_x11_get_xatom_by_name ("_NET_WM_STATE");
220 Atom atom_fullscreen = gdk_x11_get_xatom_by_name ("_NET_WM_STATE_FULLSCREEN");
225 /* in some cases XGetWindowProperty seems to generate BadWindow,
226 so at the moment this function does not always work perfectly */
227 gdk_error_trap_push ();
228 status = XGetWindowProperty (GDK_DISPLAY (), window,
229 atom_window_state, 0L, 1000000L,
230 0, XA_ATOM, &realType, &format,
231 &n, &extra, &data_return);
235 if (gdk_error_trap_pop ())
238 if (status == Success && realType == XA_ATOM && format == 32 && n > 0)
240 for (i=0; i < n; i++)
241 if (((Atom*)data_return)[i] && ((Atom*)data_return)[i] == atom_fullscreen)
243 if (data_return) XFree (data_return);
255 hildon_banner_timed_quark (void)
257 static GQuark quark = 0;
259 if (G_UNLIKELY(quark == 0))
260 quark = g_quark_from_static_string ("hildon-banner-timed");
265 /* Set the label name to make the correct rc-style attached into it */
267 hildon_banner_bind_label_style (HildonBanner *self,
270 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
273 GtkWidget *label = priv->label;
275 /* Too bad that we cannot really reset the widget name */
276 gtk_widget_set_name (label, name ? name : g_type_name (GTK_WIDGET_TYPE (label)));
279 /* In timeout function we automatically destroy timed banners */
281 simulate_close (GtkWidget* widget)
283 gboolean result = FALSE;
285 /* If the banner is currently visible (it normally should),
286 we simulate clicking the close button of the window.
287 This allows applications to reuse the banner by prevent
289 if (GTK_WIDGET_DRAWABLE (widget))
291 GdkEvent *event = gdk_event_new (GDK_DELETE);
292 event->any.window = g_object_ref (widget->window);
293 event->any.send_event = FALSE;
294 result = gtk_widget_event (widget, event);
295 gdk_event_free (event);
302 hildon_banner_timeout (gpointer data)
305 gboolean continue_timeout = FALSE;
307 GDK_THREADS_ENTER ();
309 g_assert (HILDON_IS_BANNER (data));
311 widget = GTK_WIDGET (data);
312 g_object_ref (widget);
314 continue_timeout = simulate_close (widget);
316 if (! continue_timeout) {
317 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (data);
318 priv->timeout_id = 0;
319 gtk_widget_destroy (widget);
322 g_object_unref (widget);
324 GDK_THREADS_LEAVE ();
326 return continue_timeout;
330 hildon_banner_clear_timeout (HildonBanner *self)
332 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
335 if (priv->timeout_id != 0) {
336 g_source_remove (priv->timeout_id);
337 priv->timeout_id = 0;
345 hildon_banner_ensure_timeout (HildonBanner *self)
347 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
350 if (priv->timeout_id == 0 && priv->is_timed && priv->timeout > 0)
351 priv->timeout_id = g_timeout_add (priv->timeout,
352 hildon_banner_timeout, self);
356 hildon_banner_set_property (GObject *object,
363 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
369 priv->timeout = g_value_get_uint (value);
373 priv->is_timed = g_value_get_boolean (value);
375 /* Timed and progress notifications have different
376 pixel size values for text.
377 We force to use requisition size for timed banners
378 in order to avoid resize problems when reusing the
379 window (see bug #24339) */
380 geom.max_width = priv->is_timed ? -1
381 : HILDON_BANNER_LABEL_MAX_PROGRESS;
382 geom.max_height = -1;
383 gtk_window_set_geometry_hints (GTK_WINDOW (object),
384 priv->label, &geom, GDK_HINT_MAX_SIZE);
387 case PROP_PARENT_WINDOW:
388 window = g_value_get_object (value);
390 g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent);
393 gtk_window_set_transient_for (GTK_WINDOW (object), (GtkWindow *) window);
394 priv->parent = (GtkWindow *) window;
397 gtk_window_set_destroy_with_parent (GTK_WINDOW (object), TRUE);
398 g_object_add_weak_pointer(G_OBJECT (window), (gpointer) &priv->parent);
404 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
410 hildon_banner_get_property (GObject *object,
415 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
421 g_value_set_uint (value, priv->timeout);
425 g_value_set_boolean (value, priv->is_timed);
428 case PROP_PARENT_WINDOW:
429 g_value_set_object (value, gtk_window_get_transient_for (GTK_WINDOW (object)));
433 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
439 hildon_banner_destroy (GtkObject *object)
441 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
445 GObject *parent_window = (GObject *) priv->parent;
447 g_assert (HILDON_IS_BANNER (object));
448 self = HILDON_BANNER (object);
450 /* Drop possible global pointer. That can hold reference to us */
451 if ((gpointer) object == (gpointer) global_timed_banner) {
452 global_timed_banner = NULL;
453 g_object_unref (object);
456 /* Remove the data from parent window for timed banners. Those hold reference */
457 if (priv->is_timed && parent_window != NULL) {
458 g_object_set_qdata (parent_window, hildon_banner_timed_quark (), NULL);
461 (void) hildon_banner_clear_timeout (self);
463 if (GTK_OBJECT_CLASS (hildon_banner_parent_class)->destroy)
464 GTK_OBJECT_CLASS (hildon_banner_parent_class)->destroy (object);
467 /* Search a previous banner instance */
469 hildon_banner_real_get_instance (GObject *window,
473 /* If we have a parent window, the previous instance is stored there */
475 return g_object_get_qdata(window, hildon_banner_timed_quark ());
478 /* System notification instance is stored into global pointer */
479 return (GObject *) global_timed_banner;
482 /* Non-timed banners are normal (non-singleton) objects */
486 /* By overriding constructor we force timed banners to be
487 singletons for each window */
489 hildon_banner_constructor (GType type,
490 guint n_construct_params,
491 GObjectConstructParam *construct_params)
493 GObject *banner, *window = NULL;
494 gboolean timed = FALSE;
497 /* Search banner type information from parameters in order
498 to locate the possible previous banner instance. */
499 for (i = 0; i < n_construct_params; i++)
501 if (strcmp(construct_params[i].pspec->name, "parent-window") == 0)
502 window = g_value_get_object (construct_params[i].value);
503 else if (strcmp(construct_params[i].pspec->name, "is-timed") == 0)
504 timed = g_value_get_boolean (construct_params[i].value);
507 /* Try to get a previous instance if such exists */
508 banner = hildon_banner_real_get_instance (window, timed);
511 /* We have to create a new banner */
512 banner = G_OBJECT_CLASS (hildon_banner_parent_class)->constructor (type, n_construct_params, construct_params);
514 /* Store the newly created singleton instance either into parent
515 window data or into global variables. */
518 g_object_set_qdata_full (G_OBJECT (window), hildon_banner_timed_quark (),
519 g_object_ref (banner), g_object_unref);
521 g_assert (global_timed_banner == NULL);
522 global_timed_banner = g_object_ref (banner);
527 /* FIXME: This is a hack! We have to manually freeze
528 notifications. This is normally done by g_object_init, but we
529 are not going to call that. g_object_newv will otherwise give
530 a critical like this:
532 GLIB CRITICAL ** GLib-GObject - g_object_notify_queue_thaw:
533 assertion `nqueue->freeze_count > 0' failed */
535 g_object_freeze_notify (banner);
536 hildon_banner_reset_wrap_state (HILDON_BANNER (banner));
539 /* We restart possible timeouts for each new timed banner request */
540 if (timed && hildon_banner_clear_timeout (HILDON_BANNER (banner)))
541 hildon_banner_ensure_timeout (HILDON_BANNER(banner));
547 hildon_banner_finalize (GObject *object)
549 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
552 g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent);
555 G_OBJECT_CLASS (hildon_banner_parent_class)->finalize (object);
559 hildon_banner_button_press_event (GtkWidget* widget,
560 GdkEventButton* event)
562 gboolean result = simulate_close (widget);
565 /* signal emission not stopped - basically behave like
566 * gtk_main_do_event() for a delete event */
567 gtk_widget_destroy (widget);
573 /* We start the timer for timed notifications after the window appears on screen */
575 hildon_banner_map_event (GtkWidget *widget,
578 gboolean result = FALSE;
580 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->map_event)
581 result = GTK_WIDGET_CLASS (hildon_banner_parent_class)->map_event (widget, event);
583 hildon_banner_ensure_timeout (HILDON_BANNER(widget));
588 #if defined(MAEMO_GTK)
590 static GdkAtom atom_temporaries = GDK_NONE;
592 /* Do nothing for _GTK_DELETE_TEMPORARIES */
594 hildon_banner_client_event (GtkWidget *widget,
595 GdkEventClient *event)
597 gboolean handled = FALSE;
599 if (atom_temporaries == GDK_NONE)
600 atom_temporaries = gdk_atom_intern_static_string ("_GTK_DELETE_TEMPORARIES");
602 if (event->message_type == atom_temporaries)
612 hildon_banner_reset_wrap_state (HildonBanner *banner)
615 HildonBannerPrivate *priv;
617 priv = HILDON_BANNER_GET_PRIVATE (banner);
620 layout = gtk_label_get_layout (GTK_LABEL (priv->label));
622 pango_layout_set_width (layout, -1);
623 priv->has_been_wrapped = FALSE;
624 priv->has_been_truncated = FALSE;
626 gtk_widget_set_size_request (priv->label, -1, -1);
627 gtk_widget_set_size_request (GTK_WIDGET (banner), -1, -1);
630 /* force to wrap truncated label by setting explicit size request
631 * see N#27000 and G#329646 */
633 force_to_wrap_truncated (HildonBanner *banner)
637 int width_text, width_max;
640 PangoRectangle logical;
641 GtkRequisition requisition;
642 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (banner);
644 g_return_if_fail (priv);
646 label = GTK_LABEL (priv->label);
648 if (!GTK_WIDGET_REALIZED (banner) || !GTK_WIDGET_REALIZED (label))
651 layout = gtk_label_get_layout (label);
653 pango_layout_get_extents (layout, NULL, &logical);
654 width_text = PANGO_PIXELS (logical.width);
656 width_max = priv->is_timed ? HILDON_BANNER_LABEL_MAX_TIMED
657 : HILDON_BANNER_LABEL_MAX_PROGRESS;
659 /* If the width of the label is going to exceed the maximum allowed
660 * width, enforce the maximum allowed width now.
662 if (priv->has_been_wrapped
663 || width_text >= width_max) {
664 /* Force wrapping by setting the maximum size */
667 priv->has_been_wrapped = TRUE;
670 /* Make the label update its layout */
671 gtk_widget_set_size_request (GTK_WIDGET (label), width, height);
672 gtk_widget_size_request (GTK_WIDGET (label), &requisition);
674 /* If the layout has now been wrapped and exceeds 3 lines, we truncate
675 * the rest of the label according to spec.
677 if (priv->has_been_truncated
678 || (pango_layout_is_wrapped (layout)
679 && pango_layout_get_line_count (layout) > 3)) {
682 pango_layout_get_extents (layout, NULL, &logical);
683 lines = pango_layout_get_line_count (layout);
685 /* This calculation assumes that the same font is used
686 * throughout the banner -- this is usually the case on maemo
688 * FIXME: Pango >= 1.20 has pango_layout_set_height().
690 height = (PANGO_PIXELS (logical.height) * 3) / lines + 1;
691 priv->has_been_truncated = TRUE;
694 /* Set the new width/height if applicable */
695 gtk_widget_set_size_request (GTK_WIDGET (label), width, height);
700 hildon_banner_check_position (GtkWidget *widget)
705 force_to_wrap_truncated (HILDON_BANNER(widget)); /* see N#27000 and G#329646 */
707 gtk_widget_size_request (widget, &req);
714 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
715 x = HILDON_BANNER_WINDOW_X;
717 x = gdk_screen_width() - HILDON_BANNER_WINDOW_X - req.width;
719 y = check_fullscreen_state (get_current_app_window ()) ?
720 HILDON_BANNER_WINDOW_FULLSCREEN_Y : HILDON_BANNER_WINDOW_Y;
722 gtk_window_move (GTK_WINDOW (widget), x, y);
726 hildon_banner_realize (GtkWidget *widget)
728 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (widget);
731 /* We let the parent to init widget->window before we need it */
732 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->realize)
733 GTK_WIDGET_CLASS (hildon_banner_parent_class)->realize (widget);
735 /* We use special hint to turn the banner into information notification. */
736 gdk_window_set_type_hint (widget->window, GDK_WINDOW_TYPE_HINT_NOTIFICATION);
737 gtk_window_set_transient_for (GTK_WINDOW (widget), (GtkWindow *) priv->parent);
739 hildon_banner_check_position (widget);
743 hildon_banner_class_init (HildonBannerClass *klass)
745 GObjectClass *object_class;
746 GtkWidgetClass *widget_class;
748 object_class = G_OBJECT_CLASS (klass);
749 widget_class = GTK_WIDGET_CLASS (klass);
751 /* Append private structure to class. This is more elegant than
752 on g_new based approach */
753 g_type_class_add_private (klass, sizeof (HildonBannerPrivate));
755 /* Override virtual methods */
756 object_class->constructor = hildon_banner_constructor;
757 object_class->finalize = hildon_banner_finalize;
758 object_class->set_property = hildon_banner_set_property;
759 object_class->get_property = hildon_banner_get_property;
760 GTK_OBJECT_CLASS (klass)->destroy = hildon_banner_destroy;
761 widget_class->map_event = hildon_banner_map_event;
762 widget_class->realize = hildon_banner_realize;
763 widget_class->button_press_event = hildon_banner_button_press_event;
764 #if defined(MAEMO_GTK)
765 widget_class->client_event = hildon_banner_client_event;
768 /* Install properties.
769 We need construct properties for singleton purposes */
772 * HildonBanner:parent-window:
774 * The window for which the banner will be singleton.
777 g_object_class_install_property (object_class, PROP_PARENT_WINDOW,
778 g_param_spec_object ("parent-window",
780 "The window for which the banner will be singleton",
781 GTK_TYPE_WINDOW, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
784 * HildonBanner:is-timed:
786 * Whether the banner is timed and goes away automatically.
789 g_object_class_install_property (object_class, PROP_IS_TIMED,
790 g_param_spec_boolean ("is-timed",
792 "Whether or not the notification goes away automatically "
793 "after the specified time has passed",
794 FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
797 * HildonBanner:timeout:
799 * The time before making the banner banner go away. This needs
800 * to be adjusted before the banner is mapped to the screen.
803 g_object_class_install_property (object_class, PROP_TIMEOUT,
804 g_param_spec_uint ("timeout",
806 "The time before making the banner banner go away",
809 HILDON_BANNER_DEFAULT_TIMEOUT,
810 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
814 hildon_banner_init (HildonBanner *self)
816 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
821 /* Initialize the common layout inside banner */
822 priv->layout = gtk_hbox_new (FALSE, HILDON_MARGIN_DEFAULT);
824 priv->label = g_object_new (GTK_TYPE_LABEL, NULL);
825 gtk_label_set_line_wrap (GTK_LABEL (priv->label), TRUE);
826 gtk_label_set_line_wrap_mode (GTK_LABEL (priv->label), PANGO_WRAP_WORD_CHAR);
828 gtk_container_set_border_width (GTK_CONTAINER (priv->layout), HILDON_MARGIN_DEFAULT);
829 gtk_container_add (GTK_CONTAINER (self), priv->layout);
830 gtk_box_pack_start (GTK_BOX (priv->layout), priv->label, TRUE, TRUE, 0);
832 gtk_window_set_accept_focus (GTK_WINDOW (self), FALSE);
834 #if defined(MAEMO_GTK)
835 gtk_window_set_is_temporary (GTK_WINDOW (self), TRUE);
838 hildon_banner_reset_wrap_state (self);
840 gtk_widget_add_events (GTK_WIDGET (self), GDK_BUTTON_PRESS_MASK);
843 /* Makes sure that icon/progress item contains the desired type
844 of item. If possible, tries to avoid creating a new widget but
845 reuses the existing one */
847 hildon_banner_ensure_child (HildonBanner *self,
848 GtkWidget *user_widget,
851 const gchar *first_property,
856 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
860 widget = priv->main_item;
861 va_start (args, first_property);
863 /* Reuse existing widget if possible */
864 if (! user_widget && G_TYPE_CHECK_INSTANCE_TYPE (widget, type))
866 g_object_set_valist (G_OBJECT (widget), first_property, args);
870 /* We have to abandon old content widget */
872 gtk_container_remove (GTK_CONTAINER (priv->layout), widget);
874 /* Use user provided widget or create a new one */
875 priv->main_item = widget = user_widget ?
876 user_widget : GTK_WIDGET (g_object_new_valist(type, first_property, args));
877 gtk_box_pack_start (GTK_BOX (priv->layout), widget, TRUE, TRUE, 0);
880 /* We make sure that the widget exists in desired position. Different
881 banners place this child widget to different places */
882 gtk_box_reorder_child (GTK_BOX (priv->layout), widget, pos);
886 /* Creates a new banner instance or uses an existing one */
888 hildon_banner_get_instance_for_widget (GtkWidget *widget,
893 window = widget ? gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW) : NULL;
894 return g_object_new (HILDON_TYPE_BANNER, "parent-window", window, "is-timed", timed, NULL);
898 * hildon_banner_show_information:
899 * @widget: the #GtkWidget that is the owner of the banner
900 * @icon_name: the name of icon to use. Can be %NULL for default icon
901 * @text: Text to display
903 * This function creates and displays an information banner that
904 * automatically goes away after certain time period. For each window
905 * in your application there can only be one timed banner, so if you
906 * spawn a new banner before the earlier one has timed out, the
907 * previous one will be replaced.
909 * Returns: The newly created banner
913 hildon_banner_show_information (GtkWidget *widget,
914 const gchar *icon_name,
917 HildonBanner *banner;
919 g_return_val_if_fail (icon_name == NULL || icon_name[0] != 0, NULL);
920 g_return_val_if_fail (text != NULL, NULL);
923 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
924 hildon_banner_ensure_child (banner, NULL, 0, GTK_TYPE_IMAGE,
925 "pixel-size", HILDON_ICON_PIXEL_SIZE_NOTE,
926 "icon-name", icon_name ? icon_name : HILDON_BANNER_DEFAULT_ICON,
930 hildon_banner_set_text (banner, text);
931 hildon_banner_bind_label_style (banner, NULL);
933 /* Show the banner, since caller cannot do that */
934 gtk_widget_show_all (GTK_WIDGET (banner));
935 gtk_window_present (GTK_WINDOW (banner));
937 return (GtkWidget *) banner;
941 * hildon_banner_show_informationf:
942 * @widget: the #GtkWidget that is the owner of the banner
943 * @icon_name: the name of icon to use. Can be %NULL for default icon
944 * @format: a printf-like format string
945 * @Varargs: arguments for the format string
947 * A helper function for #hildon_banner_show_information with
950 * Returns: the newly created banner
953 hildon_banner_show_informationf (GtkWidget *widget,
954 const gchar *icon_name,
958 g_return_val_if_fail (format != NULL, NULL);
964 va_start (args, format);
965 message = g_strdup_vprintf (format, args);
968 banner = hildon_banner_show_information (widget, icon_name, message);
976 * hildon_banner_show_information_with_markup:
977 * @widget: the #GtkWidget that wants to display banner
978 * @icon_name: the name of icon to use. Can be %NULL for default icon.
979 * @markup: a markup string to display (see <link linkend="PangoMarkupFormat">Pango markup format</link>)
981 * This function creates and displays an information banner that
982 * automatically goes away after certain time period. For each window
983 * in your application there can only be one timed banner, so if you
984 * spawn a new banner before the earlier one has timed out, the
985 * previous one will be replaced.
987 * Returns: the newly created banner
991 hildon_banner_show_information_with_markup (GtkWidget *widget,
992 const gchar *icon_name,
995 HildonBanner *banner;
997 g_return_val_if_fail (icon_name == NULL || icon_name[0] != 0, NULL);
998 g_return_val_if_fail (markup != NULL, NULL);
1000 /* Prepare banner */
1001 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
1003 hildon_banner_ensure_child (banner, NULL, 0, GTK_TYPE_IMAGE,
1004 "pixel-size", HILDON_ICON_PIXEL_SIZE_NOTE,
1005 "icon-name", icon_name ? icon_name : HILDON_BANNER_DEFAULT_ICON,
1009 hildon_banner_set_markup (banner, markup);
1010 hildon_banner_bind_label_style (banner, NULL);
1012 /* Show the banner, since caller cannot do that */
1013 gtk_widget_show_all (GTK_WIDGET (banner));
1014 gtk_window_present (GTK_WINDOW (banner));
1016 return (GtkWidget *) banner;
1020 * hildon_banner_show_animation:
1021 * @widget: the #GtkWidget that wants to display banner
1022 * @animation_name: The progress animation to use. You usually can just
1023 * pass %NULL for the default animation.
1024 * @text: the text to display.
1026 * Shows an animated progress notification. It's recommended not to try
1027 * to show more than one progress notification at a time, since
1028 * they will appear on top of each other. You can use progress
1029 * notifications with timed banners. In this case the banners are
1030 * located so that you can somehow see both.
1032 * Please note that banners are destroyed automatically once the
1033 * window they are attached to is closed. The pointer that you
1034 * receive with this function do not contain additional references,
1035 * so it can become invalid without warning (this is true for
1036 * all toplevel windows in gtk). To make sure that the banner do not disapear
1037 * automatically, you can separately ref the return value (this
1038 * doesn't prevent the banner from disappearing, but the object it just
1039 * not finalized). In this case you have to call both #gtk_widget_destroy
1040 * followed by #g_object_unref (in this order).
1042 * Returns: a #HildonBanner widget. You must call #gtk_widget_destroy
1043 * once you are done with the banner.
1047 hildon_banner_show_animation (GtkWidget *widget,
1048 const gchar *animation_name,
1051 HildonBanner *banner;
1052 GtkIconTheme *theme;
1054 GtkWidget *image_widget;
1055 const gchar *filename;
1057 g_return_val_if_fail (animation_name == NULL || animation_name[0] != 0, NULL);
1058 g_return_val_if_fail (text != NULL, NULL);
1060 /* Find out which animation to use */
1061 theme = gtk_icon_theme_get_default ();
1062 info = gtk_icon_theme_lookup_icon (theme, animation_name ? /* FIXME: consider using: gtk_icon_theme_load_icon() */
1063 animation_name : HILDON_BANNER_DEFAULT_PROGRESS_ANIMATION,
1064 HILDON_ICON_SIZE_NOTE, 0);
1066 /* Try to load animation. One could try to optimize this
1067 to avoid loading the default animation during each call */
1069 filename = gtk_icon_info_get_filename (info);
1070 image_widget = gtk_image_new_from_file (filename);
1071 gtk_icon_info_free (info);
1073 g_warning ("Icon theme lookup for icon failed!");
1074 image_widget = NULL;
1077 /* Prepare banner */
1078 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
1079 hildon_banner_ensure_child (banner, image_widget, 0,
1080 GTK_TYPE_IMAGE, "yalign", 0.0, NULL);
1082 hildon_banner_set_text (banner, text);
1083 hildon_banner_bind_label_style (banner, NULL);
1086 gtk_widget_show_all (GTK_WIDGET (banner));
1087 gtk_window_present (GTK_WINDOW (banner));
1089 return (GtkWidget *) banner;
1093 * hildon_banner_show_progress:
1094 * @widget: the #GtkWidget that wants to display banner
1095 * @bar: Progressbar to use. You usually can just pass %NULL, unless
1096 * you want somehow customized progress bar.
1097 * @text: text to display.
1099 * Shows progress notification. See #hildon_banner_show_animation
1100 * for more information.
1102 * Returns: a #HildonBanner widget. You must call #gtk_widget_destroy
1103 * once you are done with the banner.
1107 hildon_banner_show_progress (GtkWidget *widget,
1108 GtkProgressBar *bar,
1111 HildonBanner *banner;
1112 HildonBannerPrivate *priv;
1114 g_return_val_if_fail (bar == NULL || GTK_IS_PROGRESS_BAR (bar), NULL);
1115 g_return_val_if_fail (text != NULL, NULL);
1118 /* Prepare banner */
1119 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
1120 priv = HILDON_BANNER_GET_PRIVATE (banner);
1122 hildon_banner_ensure_child (banner, (GtkWidget *) bar, -1, GTK_TYPE_PROGRESS_BAR, NULL);
1124 gtk_widget_set_size_request (priv->main_item,
1125 HILDON_BANNER_PROGRESS_WIDTH, -1);
1127 hildon_banner_set_text (banner, text);
1128 hildon_banner_bind_label_style (banner, NULL);
1130 /* Show the banner */
1131 gtk_widget_show_all (GTK_WIDGET (banner));
1132 gtk_window_present (GTK_WINDOW (banner));
1134 return GTK_WIDGET (banner);
1138 * hildon_banner_set_text:
1139 * @self: a #HildonBanner widget
1140 * @text: a new text to display in banner
1142 * Sets the text that is displayed in the banner.
1146 hildon_banner_set_text (HildonBanner *self,
1150 HildonBannerPrivate *priv;
1151 const gchar *existing_text;
1153 g_return_if_fail (HILDON_IS_BANNER (self));
1155 priv = HILDON_BANNER_GET_PRIVATE (self);
1158 label = GTK_LABEL (priv->label);
1159 existing_text = gtk_label_get_text (label);
1161 if (existing_text != NULL &&
1163 strcmp (existing_text, text) != 0) {
1164 gtk_label_set_text (label, text);
1165 hildon_banner_reset_wrap_state (self);
1168 hildon_banner_check_position (GTK_WIDGET (self));
1172 * hildon_banner_set_markup:
1173 * @self: a #HildonBanner widget
1174 * @markup: a new text with Pango markup to display in the banner
1176 * Sets the text with markup that is displayed in the banner.
1180 hildon_banner_set_markup (HildonBanner *self,
1181 const gchar *markup)
1184 HildonBannerPrivate *priv;
1186 g_return_if_fail (HILDON_IS_BANNER (self));
1188 priv = HILDON_BANNER_GET_PRIVATE (self);
1191 label = GTK_LABEL (priv->label);
1192 gtk_label_set_markup (label, markup);
1194 hildon_banner_reset_wrap_state (self);
1196 hildon_banner_check_position (GTK_WIDGET(self));
1200 * hildon_banner_set_fraction:
1201 * @self: a #HildonBanner widget
1202 * @fraction: #gdouble
1204 * The fraction is the completion of progressbar,
1205 * the scale is from 0.0 to 1.0.
1206 * Sets the amount of fraction the progressbar has.
1210 hildon_banner_set_fraction (HildonBanner *self,
1213 HildonBannerPrivate *priv;
1215 g_return_if_fail (HILDON_IS_BANNER (self));
1216 priv = HILDON_BANNER_GET_PRIVATE (self);
1219 g_return_if_fail (GTK_IS_PROGRESS_BAR (priv->main_item));
1220 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (priv->main_item), fraction);
1224 * hildon_banner_set_timeout:
1225 * @self: a #HildonBanner widget
1226 * @timeout: timeout to set in miliseconds.
1228 * Sets the timeout on the banner. After the given amount of miliseconds
1229 * has elapsed the banner will go away. Note that settings this only makes
1230 * sense on the banners that are timed and that have not been yet displayed
1235 hildon_banner_set_timeout (HildonBanner *self,
1238 HildonBannerPrivate *priv;
1240 g_return_if_fail (HILDON_IS_BANNER (self));
1241 priv = HILDON_BANNER_GET_PRIVATE (self);
1244 priv->timeout = timeout;
1248 * hildon_banner_set_icon:
1249 * @self: a #HildonBanner widget
1250 * @icon_name: the name of icon to use. Can be %NULL for default icon
1252 * Sets the icon to be used in the banner.
1256 hildon_banner_set_icon (HildonBanner *self,
1257 const gchar *icon_name)
1259 HildonBannerPrivate *priv;
1261 g_return_if_fail (HILDON_IS_BANNER (self));
1262 priv = HILDON_BANNER_GET_PRIVATE (self);
1265 hildon_banner_ensure_child (self, NULL, 0, GTK_TYPE_IMAGE,
1266 "pixel-size", HILDON_ICON_PIXEL_SIZE_NOTE,
1267 "icon-name", icon_name ? icon_name : HILDON_BANNER_DEFAULT_ICON,
1273 * hildon_banner_set_icon_from_file:
1274 * @self: a #HildonBanner widget
1275 * @icon_file: the filename of icon to use. Can be %NULL for default icon
1277 * Sets the icon from its filename to be used in the banner.
1281 hildon_banner_set_icon_from_file (HildonBanner *self,
1282 const gchar *icon_file)
1284 HildonBannerPrivate *priv;
1286 g_return_if_fail (HILDON_IS_BANNER (self));
1287 priv = HILDON_BANNER_GET_PRIVATE (self);
1290 if (icon_file != NULL) {
1291 hildon_banner_ensure_child (self, NULL, 0, GTK_TYPE_IMAGE,
1292 "pixel-size", HILDON_ICON_PIXEL_SIZE_NOTE,
1297 hildon_banner_ensure_child (self, NULL, 0, GTK_TYPE_IMAGE,
1298 "pixel-size", HILDON_ICON_PIXEL_SIZE_NOTE,
1299 "icon-name", HILDON_BANNER_DEFAULT_ICON,