2 * This file is a part of hildon
4 * Copyright (C) 2005, 2006, 2007 Nokia Corporation, all rights reserved.
6 * Contact: Rodrigo Novo <rodrigo.novo@nokia.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; version 2.1 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
26 * SECTION:hildon-banner
27 * @short_description: A widget used to display timed notifications.
29 * #HildonBanner is a small, pop-up window that can be used to display
30 * a short, timed notification or information to the user. It can
31 * communicate that a task has been finished or that the application
34 * Hildon provides convenient funtions to create and show banners. To
35 * create and show information banners you can use
36 * hildon_banner_show_information(), hildon_banner_show_informationf()
37 * or hildon_banner_show_information_with_markup().
39 * Two more kinds of banners are maintained for backward compatibility
40 * but are no longer recommended in Hildon 2.2. These are the animated
41 * banner (created with hildon_banner_show_animation()) and the
42 * progress banner (created with hildon_banner_show_progress()). See
43 * hildon_gtk_window_set_progress_indicator() for the preferred way of
44 * showing progress notifications in Hildon 2.2.
46 * Information banners dissapear automatically after a certain
47 * period. This is stored in the #HildonBanner:timeout property (in
48 * miliseconds), and can be changed using hildon_banner_set_timeout().
50 * Note that #HildonBanner<!-- -->s should only be used to display
51 * non-critical pieces of information.
59 #include <X11/Xatom.h>
63 #undef HILDON_DISABLE_DEPRECATED
65 #include "hildon-banner.h"
66 #include "hildon-banner-private.h"
67 #include "hildon-defines.h"
69 /* position relative to the screen */
71 #define HILDON_BANNER_WINDOW_X 0
73 #define HILDON_BANNER_WINDOW_Y 73
75 #define HILDON_BANNER_WINDOW_FULLSCREEN_Y 20
79 #define HILDON_BANNER_PROGRESS_WIDTH 104
81 #define HILDON_BANNER_LABEL_MAX_TIMED 375
83 #define HILDON_BANNER_LABEL_MAX_PROGRESS 375 /*265*/
87 #define HILDON_BANNER_DEFAULT_TIMEOUT 3000
91 #define HILDON_BANNER_DEFAULT_PROGRESS_ANIMATION "qgn_indi_pball_a"
101 static GtkWidget* global_timed_banner = NULL;
104 get_current_app_window (void);
107 check_fullscreen_state (Window window);
110 hildon_banner_timed_quark (void);
113 hildon_banner_bind_label_style (HildonBanner *self,
117 hildon_banner_timeout (gpointer data);
120 hildon_banner_clear_timeout (HildonBanner *self);
123 hildon_banner_ensure_timeout (HildonBanner *self);
126 hildon_banner_set_property (GObject *object,
132 hildon_banner_get_property (GObject *object,
138 hildon_banner_destroy (GtkObject *object);
141 hildon_banner_real_get_instance (GObject *window,
145 hildon_banner_constructor (GType type,
146 guint n_construct_params,
147 GObjectConstructParam *construct_params);
150 hildon_banner_finalize (GObject *object);
153 hildon_banner_button_press_event (GtkWidget* widget,
154 GdkEventButton* event);
157 hildon_banner_map_event (GtkWidget *widget,
160 hildon_banner_reset_wrap_state (HildonBanner *banner);
163 force_to_wrap_truncated (HildonBanner *banner);
166 hildon_banner_check_position (GtkWidget *widget);
169 hildon_banner_realize (GtkWidget *widget);
172 hildon_banner_class_init (HildonBannerClass *klass);
175 hildon_banner_init (HildonBanner *self);
178 hildon_banner_ensure_child (HildonBanner *self,
179 GtkWidget *user_widget,
182 const gchar *first_property,
186 hildon_banner_get_instance_for_widget (GtkWidget *widget,
189 G_DEFINE_TYPE (HildonBanner, hildon_banner, GTK_TYPE_WINDOW)
191 /* copy/paste from old infoprint implementation: Use matchbox
192 properties to find the topmost application window */
194 get_current_app_window (void)
201 Atom atom_current_app_window = gdk_x11_get_xatom_by_name ("_MB_CURRENT_APP_WINDOW");
203 Window win_result = None;
204 guchar *data_return = NULL;
206 status = XGetWindowProperty (GDK_DISPLAY(), GDK_ROOT_WINDOW (),
207 atom_current_app_window, 0L, 16L,
208 0, XA_WINDOW, &realType, &format,
212 if (status == Success && realType == XA_WINDOW && format == 32 && n == 1 && data_return != NULL)
214 win_result = ((Window*) data_return)[0];
223 /* Checks if a window is in fullscreen state or not. This
224 information is needed when banners are positioned on screen.
225 copy/paste from old infoprint implementation. */
227 check_fullscreen_state (Window window)
231 int format, status, i;
232 guchar *data_return = NULL;
235 Atom atom_window_state = gdk_x11_get_xatom_by_name ("_NET_WM_STATE");
236 Atom atom_fullscreen = gdk_x11_get_xatom_by_name ("_NET_WM_STATE_FULLSCREEN");
241 /* in some cases XGetWindowProperty seems to generate BadWindow,
242 so at the moment this function does not always work perfectly */
243 gdk_error_trap_push ();
244 status = XGetWindowProperty (GDK_DISPLAY (), window,
245 atom_window_state, 0L, 1000000L,
246 0, XA_ATOM, &realType, &format,
247 &n, &extra, &data_return);
251 if (gdk_error_trap_pop ())
254 if (status == Success && realType == XA_ATOM && format == 32 && n > 0)
256 for (i=0; i < n; i++)
257 if (((Atom*)data_return)[i] && ((Atom*)data_return)[i] == atom_fullscreen)
259 if (data_return) XFree (data_return);
271 hildon_banner_timed_quark (void)
273 static GQuark quark = 0;
275 if (G_UNLIKELY(quark == 0))
276 quark = g_quark_from_static_string ("hildon-banner-timed");
281 /* Set the label name to make the correct rc-style attached into it */
283 hildon_banner_bind_label_style (HildonBanner *self,
286 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
289 GtkWidget *label = priv->label;
291 /* Too bad that we cannot really reset the widget name */
292 gtk_widget_set_name (label, name ? name : g_type_name (GTK_WIDGET_TYPE (label)));
295 /* In timeout function we automatically destroy timed banners */
297 simulate_close (GtkWidget* widget)
299 gboolean result = FALSE;
301 /* If the banner is currently visible (it normally should),
302 we simulate clicking the close button of the window.
303 This allows applications to reuse the banner by prevent
305 if (GTK_WIDGET_DRAWABLE (widget))
307 GdkEvent *event = gdk_event_new (GDK_DELETE);
308 event->any.window = g_object_ref (widget->window);
309 event->any.send_event = FALSE;
310 result = gtk_widget_event (widget, event);
311 gdk_event_free (event);
318 hildon_banner_timeout (gpointer data)
321 gboolean continue_timeout = FALSE;
323 GDK_THREADS_ENTER ();
325 g_assert (HILDON_IS_BANNER (data));
327 widget = GTK_WIDGET (data);
328 g_object_ref (widget);
330 continue_timeout = simulate_close (widget);
332 if (! continue_timeout) {
333 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (data);
334 priv->timeout_id = 0;
335 gtk_widget_destroy (widget);
338 g_object_unref (widget);
340 GDK_THREADS_LEAVE ();
342 return continue_timeout;
346 hildon_banner_clear_timeout (HildonBanner *self)
348 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
351 if (priv->timeout_id != 0) {
352 g_source_remove (priv->timeout_id);
353 priv->timeout_id = 0;
361 hildon_banner_ensure_timeout (HildonBanner *self)
363 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
366 if (priv->timeout_id == 0 && priv->is_timed && priv->timeout > 0)
367 priv->timeout_id = g_timeout_add (priv->timeout,
368 hildon_banner_timeout, self);
372 hildon_banner_set_property (GObject *object,
378 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
384 priv->timeout = g_value_get_uint (value);
388 priv->is_timed = g_value_get_boolean (value);
391 case PROP_PARENT_WINDOW:
392 window = g_value_get_object (value);
394 g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent);
397 gtk_window_set_transient_for (GTK_WINDOW (object), (GtkWindow *) window);
398 priv->parent = (GtkWindow *) window;
401 gtk_window_set_destroy_with_parent (GTK_WINDOW (object), TRUE);
402 g_object_add_weak_pointer(G_OBJECT (window), (gpointer) &priv->parent);
408 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
414 hildon_banner_get_property (GObject *object,
419 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
425 g_value_set_uint (value, priv->timeout);
429 g_value_set_boolean (value, priv->is_timed);
432 case PROP_PARENT_WINDOW:
433 g_value_set_object (value, gtk_window_get_transient_for (GTK_WINDOW (object)));
437 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
443 hildon_banner_destroy (GtkObject *object)
445 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
449 GObject *parent_window = (GObject *) priv->parent;
451 g_assert (HILDON_IS_BANNER (object));
452 self = HILDON_BANNER (object);
454 /* Drop possible global pointer. That can hold reference to us */
455 if ((gpointer) object == (gpointer) global_timed_banner) {
456 global_timed_banner = NULL;
457 g_object_unref (object);
460 /* Remove the data from parent window for timed banners. Those hold reference */
461 if (priv->is_timed && parent_window != NULL) {
462 g_object_set_qdata (parent_window, hildon_banner_timed_quark (), NULL);
465 (void) hildon_banner_clear_timeout (self);
467 if (GTK_OBJECT_CLASS (hildon_banner_parent_class)->destroy)
468 GTK_OBJECT_CLASS (hildon_banner_parent_class)->destroy (object);
471 /* Search a previous banner instance */
473 hildon_banner_real_get_instance (GObject *window,
477 /* If we have a parent window, the previous instance is stored there */
479 return g_object_get_qdata(window, hildon_banner_timed_quark ());
482 /* System notification instance is stored into global pointer */
483 return (GObject *) global_timed_banner;
486 /* Non-timed banners are normal (non-singleton) objects */
490 /* By overriding constructor we force timed banners to be
491 singletons for each window */
493 hildon_banner_constructor (GType type,
494 guint n_construct_params,
495 GObjectConstructParam *construct_params)
497 GObject *banner, *window = NULL;
498 gboolean timed = FALSE;
501 /* Search banner type information from parameters in order
502 to locate the possible previous banner instance. */
503 for (i = 0; i < n_construct_params; i++)
505 if (strcmp(construct_params[i].pspec->name, "parent-window") == 0)
506 window = g_value_get_object (construct_params[i].value);
507 else if (strcmp(construct_params[i].pspec->name, "is-timed") == 0)
508 timed = g_value_get_boolean (construct_params[i].value);
511 /* Try to get a previous instance if such exists */
512 banner = hildon_banner_real_get_instance (window, timed);
515 /* We have to create a new banner */
516 banner = G_OBJECT_CLASS (hildon_banner_parent_class)->constructor (type, n_construct_params, construct_params);
518 /* Store the newly created singleton instance either into parent
519 window data or into global variables. */
522 g_object_set_qdata_full (G_OBJECT (window), hildon_banner_timed_quark (),
523 g_object_ref (banner), g_object_unref);
525 g_assert (global_timed_banner == NULL);
526 global_timed_banner = g_object_ref (banner);
531 /* FIXME: This is a hack! We have to manually freeze
532 notifications. This is normally done by g_object_init, but we
533 are not going to call that. g_object_newv will otherwise give
534 a critical like this:
536 GLIB CRITICAL ** GLib-GObject - g_object_notify_queue_thaw:
537 assertion `nqueue->freeze_count > 0' failed */
539 g_object_freeze_notify (banner);
540 hildon_banner_reset_wrap_state (HILDON_BANNER (banner));
543 /* We restart possible timeouts for each new timed banner request */
544 if (timed && hildon_banner_clear_timeout (HILDON_BANNER (banner)))
545 hildon_banner_ensure_timeout (HILDON_BANNER(banner));
551 hildon_banner_finalize (GObject *object)
553 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
556 g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent);
559 G_OBJECT_CLASS (hildon_banner_parent_class)->finalize (object);
563 hildon_banner_button_press_event (GtkWidget* widget,
564 GdkEventButton* event)
566 gboolean result = simulate_close (widget);
569 /* signal emission not stopped - basically behave like
570 * gtk_main_do_event() for a delete event, but just hide the
571 * banner instead of destroying it, as it is already meant to
572 * be destroyed by hildon_banner_timeout() (if it's timed) or
573 * the application (if it's not). */
574 gtk_widget_hide (widget);
580 #if defined(MAEMO_GTK)
582 hildon_banner_map (GtkWidget *widget)
584 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->map) {
585 /* Make the banner temporary _before_ mapping it, to avoid closing
586 * other temporary windows */
587 gtk_window_set_is_temporary (GTK_WINDOW (widget), TRUE);
589 GTK_WIDGET_CLASS (hildon_banner_parent_class)->map (widget);
591 /* Make the banner non-temporary _after_ mapping it, to avoid
592 * being closed by other non-temporary windows */
593 gtk_window_set_is_temporary (GTK_WINDOW (widget), FALSE);
598 /* We start the timer for timed notifications after the window appears on screen */
600 hildon_banner_map_event (GtkWidget *widget,
603 gboolean result = FALSE;
605 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->map_event)
606 result = GTK_WIDGET_CLASS (hildon_banner_parent_class)->map_event (widget, event);
608 hildon_banner_ensure_timeout (HILDON_BANNER(widget));
614 hildon_banner_reset_wrap_state (HildonBanner *banner)
617 HildonBannerPrivate *priv;
619 priv = HILDON_BANNER_GET_PRIVATE (banner);
622 layout = gtk_label_get_layout (GTK_LABEL (priv->label));
624 pango_layout_set_width (layout, -1);
625 priv->has_been_wrapped = FALSE;
626 priv->has_been_truncated = FALSE;
628 gtk_widget_set_size_request (priv->label, -1, -1);
629 gtk_widget_set_size_request (GTK_WIDGET (banner), -1, -1);
632 /* force to wrap truncated label by setting explicit size request
633 * see N#27000 and G#329646 */
635 force_to_wrap_truncated (HildonBanner *banner)
639 int width_text, width_max;
642 PangoRectangle logical;
643 GtkRequisition requisition;
644 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (banner);
646 g_return_if_fail (priv);
648 label = GTK_LABEL (priv->label);
650 layout = gtk_label_get_layout (label);
652 pango_layout_get_extents (layout, NULL, &logical);
653 width_text = PANGO_PIXELS (logical.width);
655 width_max = priv->is_timed ? HILDON_BANNER_LABEL_MAX_TIMED
656 : HILDON_BANNER_LABEL_MAX_PROGRESS;
658 /* If the width of the label is going to exceed the maximum allowed
659 * width, enforce the maximum allowed width now.
661 if (priv->has_been_wrapped
662 || width_text >= width_max) {
663 /* Force wrapping by setting the maximum size */
666 priv->has_been_wrapped = TRUE;
669 /* Make the label update its layout; and update our layout pointer
670 * because the layout will be cleared and refreshed.
672 gtk_widget_set_size_request (GTK_WIDGET (label), width, height);
673 gtk_widget_size_request (GTK_WIDGET (label), &requisition);
675 layout = gtk_label_get_layout (label);
677 /* If the layout has now been wrapped and exceeds 3 lines, we truncate
678 * the rest of the label according to spec.
680 if (priv->has_been_truncated
681 || (pango_layout_is_wrapped (layout)
682 && pango_layout_get_line_count (layout) > 3)) {
685 pango_layout_get_extents (layout, NULL, &logical);
686 lines = pango_layout_get_line_count (layout);
688 /* This calculation assumes that the same font is used
689 * throughout the banner -- this is usually the case on maemo
691 * FIXME: Pango >= 1.20 has pango_layout_set_height().
693 height = (PANGO_PIXELS (logical.height) * 3) / lines + 1;
694 priv->has_been_truncated = TRUE;
697 /* Set the new width/height if applicable */
698 gtk_widget_set_size_request (GTK_WIDGET (label), width, height);
703 hildon_banner_check_position (GtkWidget *widget)
708 gtk_widget_set_size_request (widget, gdk_screen_width (), -1);
710 force_to_wrap_truncated (HILDON_BANNER(widget)); /* see N#27000 and G#329646 */
712 gtk_widget_size_request (widget, &req);
719 x = HILDON_BANNER_WINDOW_X;
721 y = check_fullscreen_state (get_current_app_window ()) ?
722 HILDON_BANNER_WINDOW_FULLSCREEN_Y : HILDON_BANNER_WINDOW_Y;
724 gtk_window_move (GTK_WINDOW (widget), x, y);
728 hildon_banner_realize (GtkWidget *widget)
732 const gchar *notification_type = "_HILDON_NOTIFICATION_TYPE_BANNER";
733 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (widget);
736 /* We let the parent to init widget->window before we need it */
737 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->realize)
738 GTK_WIDGET_CLASS (hildon_banner_parent_class)->realize (widget);
740 /* We use special hint to turn the banner into information notification. */
741 gdk_window_set_type_hint (widget->window, GDK_WINDOW_TYPE_HINT_NOTIFICATION);
742 gtk_window_set_transient_for (GTK_WINDOW (widget), (GtkWindow *) priv->parent);
744 hildon_banner_check_position (widget);
746 /* Set the _HILDON_NOTIFICATION_TYPE property so Matchbox places the window correctly */
747 display = gdk_drawable_get_display (widget->window);
748 atom = gdk_x11_get_xatom_by_name_for_display (display, "_HILDON_NOTIFICATION_TYPE");
749 XChangeProperty (GDK_WINDOW_XDISPLAY (widget->window), GDK_WINDOW_XID (widget->window),
750 atom, XA_STRING, 8, PropModeReplace, (guchar *) notification_type,
751 strlen (notification_type));
755 hildon_banner_class_init (HildonBannerClass *klass)
757 GObjectClass *object_class;
758 GtkWidgetClass *widget_class;
760 object_class = G_OBJECT_CLASS (klass);
761 widget_class = GTK_WIDGET_CLASS (klass);
763 /* Append private structure to class. This is more elegant than
764 on g_new based approach */
765 g_type_class_add_private (klass, sizeof (HildonBannerPrivate));
767 /* Override virtual methods */
768 object_class->constructor = hildon_banner_constructor;
769 object_class->finalize = hildon_banner_finalize;
770 object_class->set_property = hildon_banner_set_property;
771 object_class->get_property = hildon_banner_get_property;
772 GTK_OBJECT_CLASS (klass)->destroy = hildon_banner_destroy;
773 widget_class->map_event = hildon_banner_map_event;
774 widget_class->realize = hildon_banner_realize;
775 widget_class->button_press_event = hildon_banner_button_press_event;
776 #if defined(MAEMO_GTK)
777 widget_class->map = hildon_banner_map;
780 /* Install properties.
781 We need construct properties for singleton purposes */
784 * HildonBanner:parent-window:
786 * The window for which the banner will be singleton.
789 g_object_class_install_property (object_class, PROP_PARENT_WINDOW,
790 g_param_spec_object ("parent-window",
792 "The window for which the banner will be singleton",
793 GTK_TYPE_WINDOW, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
796 * HildonBanner:is-timed:
798 * Whether the banner is timed and goes away automatically.
801 g_object_class_install_property (object_class, PROP_IS_TIMED,
802 g_param_spec_boolean ("is-timed",
804 "Whether or not the notification goes away automatically "
805 "after the specified time has passed",
806 FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
809 * HildonBanner:timeout:
811 * The time before making the banner banner go away. This needs
812 * to be adjusted before the banner is mapped to the screen.
815 g_object_class_install_property (object_class, PROP_TIMEOUT,
816 g_param_spec_uint ("timeout",
818 "The time before making the banner banner go away",
821 HILDON_BANNER_DEFAULT_TIMEOUT,
822 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
826 hildon_banner_init (HildonBanner *self)
828 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
833 /* Initialize the common layout inside banner */
834 priv->layout = gtk_hbox_new (FALSE, HILDON_MARGIN_DEFAULT);
836 priv->label = g_object_new (GTK_TYPE_LABEL, NULL);
837 gtk_label_set_line_wrap (GTK_LABEL (priv->label), TRUE);
838 gtk_label_set_line_wrap_mode (GTK_LABEL (priv->label), PANGO_WRAP_WORD_CHAR);
840 gtk_container_set_border_width (GTK_CONTAINER (priv->layout), HILDON_MARGIN_DEFAULT);
841 gtk_container_add (GTK_CONTAINER (self), priv->layout);
842 gtk_box_pack_start (GTK_BOX (priv->layout), priv->label, TRUE, TRUE, 0);
844 gtk_window_set_accept_focus (GTK_WINDOW (self), FALSE);
846 hildon_banner_reset_wrap_state (self);
848 gtk_widget_add_events (GTK_WIDGET (self), GDK_BUTTON_PRESS_MASK);
851 /* Makes sure that icon/progress item contains the desired type
852 of item. If possible, tries to avoid creating a new widget but
853 reuses the existing one */
855 hildon_banner_ensure_child (HildonBanner *self,
856 GtkWidget *user_widget,
859 const gchar *first_property,
864 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
868 widget = priv->main_item;
869 va_start (args, first_property);
871 /* Reuse existing widget if possible */
872 if (! user_widget && G_TYPE_CHECK_INSTANCE_TYPE (widget, type))
874 g_object_set_valist (G_OBJECT (widget), first_property, args);
878 /* We have to abandon old content widget */
880 gtk_container_remove (GTK_CONTAINER (priv->layout), widget);
882 /* Use user provided widget or create a new one */
883 priv->main_item = widget = user_widget ?
884 user_widget : GTK_WIDGET (g_object_new_valist(type, first_property, args));
885 gtk_box_pack_start (GTK_BOX (priv->layout), widget, TRUE, TRUE, 0);
888 /* We make sure that the widget exists in desired position. Different
889 banners place this child widget to different places */
890 gtk_box_reorder_child (GTK_BOX (priv->layout), widget, pos);
894 /* Creates a new banner instance or uses an existing one */
896 hildon_banner_get_instance_for_widget (GtkWidget *widget,
901 window = widget ? gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW) : NULL;
902 return g_object_new (HILDON_TYPE_BANNER, "parent-window", window, "is-timed", timed, NULL);
906 * hildon_banner_show_information:
907 * @widget: the #GtkWidget that is the owner of the banner
908 * @icon_name: since Hildon 2.2 this parameter is not used anymore and
909 * any value that you pass will be ignored
910 * @text: Text to display
912 * This function creates and displays an information banner that
913 * automatically goes away after certain time period. For each window
914 * in your application there can only be one timed banner, so if you
915 * spawn a new banner before the earlier one has timed out, the
916 * previous one will be replaced.
918 * Returns: The newly created banner
922 hildon_banner_show_information (GtkWidget *widget,
923 const gchar *icon_name,
926 HildonBanner *banner;
928 g_return_val_if_fail (text != NULL, NULL);
931 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
933 hildon_banner_set_text (banner, text);
934 hildon_banner_bind_label_style (banner, NULL);
936 /* Show the banner, since caller cannot do that */
937 gtk_widget_show_all (GTK_WIDGET (banner));
939 return (GtkWidget *) banner;
943 * hildon_banner_show_informationf:
944 * @widget: the #GtkWidget that is the owner of the banner
945 * @icon_name: since Hildon 2.2 this parameter is not used anymore and
946 * any value that you pass will be ignored
947 * @format: a printf-like format string
948 * @Varargs: arguments for the format string
950 * A helper function for #hildon_banner_show_information with
953 * Returns: the newly created banner
956 hildon_banner_show_informationf (GtkWidget *widget,
957 const gchar *icon_name,
961 g_return_val_if_fail (format != NULL, NULL);
967 va_start (args, format);
968 message = g_strdup_vprintf (format, args);
971 banner = hildon_banner_show_information (widget, icon_name, message);
979 * hildon_banner_show_information_with_markup:
980 * @widget: the #GtkWidget that wants to display banner
981 * @icon_name: since Hildon 2.2 this parameter is not used anymore and
982 * any value that you pass will be ignored
983 * @markup: a markup string to display (see <link linkend="PangoMarkupFormat">Pango markup format</link>)
985 * This function creates and displays an information banner that
986 * automatically goes away after certain time period. For each window
987 * in your application there can only be one timed banner, so if you
988 * spawn a new banner before the earlier one has timed out, the
989 * previous one will be replaced.
991 * Returns: the newly created banner
995 hildon_banner_show_information_with_markup (GtkWidget *widget,
996 const gchar *icon_name,
999 HildonBanner *banner;
1001 g_return_val_if_fail (icon_name == NULL || icon_name[0] != 0, NULL);
1002 g_return_val_if_fail (markup != NULL, NULL);
1004 /* Prepare banner */
1005 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
1007 hildon_banner_set_markup (banner, markup);
1008 hildon_banner_bind_label_style (banner, NULL);
1010 /* Show the banner, since caller cannot do that */
1011 gtk_widget_show_all (GTK_WIDGET (banner));
1013 return (GtkWidget *) banner;
1017 * hildon_banner_show_animation:
1018 * @widget: the #GtkWidget that wants to display banner
1019 * @animation_name: The progress animation to use. You usually can just
1020 * pass %NULL for the default animation.
1021 * @text: the text to display.
1023 * Shows an animated progress notification. It's recommended not to try
1024 * to show more than one progress notification at a time, since
1025 * they will appear on top of each other. You can use progress
1026 * notifications with timed banners. In this case the banners are
1027 * located so that you can somehow see both.
1029 * Please note that banners are destroyed automatically once the
1030 * window they are attached to is closed. The pointer that you receive
1031 * with this function does not contain additional references, so it
1032 * can become invalid without warning (this is true for all toplevel
1033 * windows in gtk). To make sure that the banner does not disappear
1034 * automatically, you can separately ref the return value (this
1035 * doesn't prevent the banner from disappearing, just the object from
1036 * being finalized). In this case you have to call both
1037 * gtk_widget_destroy() followed by g_object_unref() (in this order).
1039 * Returns: a #HildonBanner widget. You must call gtk_widget_destroy()
1040 * once you are done with the banner.
1042 * Deprecated: Hildon 2.2: use
1043 * hildon_gtk_window_set_progress_indicator() instead.
1046 hildon_banner_show_animation (GtkWidget *widget,
1047 const gchar *animation_name,
1050 HildonBanner *banner;
1051 GtkIconTheme *theme;
1053 GtkWidget *image_widget;
1054 const gchar *filename;
1056 g_return_val_if_fail (animation_name == NULL || animation_name[0] != 0, NULL);
1057 g_return_val_if_fail (text != NULL, NULL);
1059 /* Find out which animation to use */
1060 theme = gtk_icon_theme_get_default ();
1061 info = gtk_icon_theme_lookup_icon (theme, animation_name ? /* FIXME: consider using: gtk_icon_theme_load_icon() */
1062 animation_name : HILDON_BANNER_DEFAULT_PROGRESS_ANIMATION,
1063 HILDON_ICON_SIZE_STYLUS, 0);
1065 /* Try to load animation. One could try to optimize this
1066 to avoid loading the default animation during each call */
1068 filename = gtk_icon_info_get_filename (info);
1069 image_widget = gtk_image_new_from_file (filename);
1070 gtk_icon_info_free (info);
1072 g_warning ("Icon theme lookup for icon failed!");
1073 image_widget = NULL;
1076 /* Prepare banner */
1077 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
1078 hildon_banner_ensure_child (banner, image_widget, 0,
1079 GTK_TYPE_IMAGE, "yalign", 0.0, NULL);
1081 hildon_banner_set_text (banner, text);
1082 hildon_banner_bind_label_style (banner, NULL);
1085 gtk_widget_show_all (GTK_WIDGET (banner));
1087 return (GtkWidget *) banner;
1091 * hildon_banner_show_progress:
1092 * @widget: the #GtkWidget that wants to display banner
1093 * @bar: Progressbar to use. You usually can just pass %NULL, unless
1094 * you want somehow customized progress bar.
1095 * @text: text to display.
1097 * Shows progress notification. See #hildon_banner_show_animation
1098 * for more information.
1100 * Returns: a #HildonBanner widget. You must call #gtk_widget_destroy
1101 * once you are done with the banner.
1103 * Deprecated: Hildon 2.2: use hildon_gtk_window_set_progress_indicator() instead.
1106 hildon_banner_show_progress (GtkWidget *widget,
1107 GtkProgressBar *bar,
1110 HildonBanner *banner;
1111 HildonBannerPrivate *priv;
1113 g_return_val_if_fail (bar == NULL || GTK_IS_PROGRESS_BAR (bar), NULL);
1114 g_return_val_if_fail (text != NULL, NULL);
1117 /* Prepare banner */
1118 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
1119 priv = HILDON_BANNER_GET_PRIVATE (banner);
1121 hildon_banner_ensure_child (banner, (GtkWidget *) bar, -1, GTK_TYPE_PROGRESS_BAR, NULL);
1123 gtk_widget_set_size_request (priv->main_item,
1124 HILDON_BANNER_PROGRESS_WIDTH, -1);
1126 hildon_banner_set_text (banner, text);
1127 hildon_banner_bind_label_style (banner, NULL);
1129 /* Show the banner */
1130 gtk_widget_show_all (GTK_WIDGET (banner));
1132 return GTK_WIDGET (banner);
1136 * hildon_banner_set_text:
1137 * @self: a #HildonBanner widget
1138 * @text: a new text to display in banner
1140 * Sets the text that is displayed in the banner.
1144 hildon_banner_set_text (HildonBanner *self,
1148 HildonBannerPrivate *priv;
1149 const gchar *existing_text;
1151 g_return_if_fail (HILDON_IS_BANNER (self));
1153 priv = HILDON_BANNER_GET_PRIVATE (self);
1156 label = GTK_LABEL (priv->label);
1157 existing_text = gtk_label_get_text (label);
1159 if (existing_text != NULL &&
1161 strcmp (existing_text, text) != 0) {
1162 gtk_label_set_text (label, text);
1163 hildon_banner_reset_wrap_state (self);
1166 hildon_banner_check_position (GTK_WIDGET (self));
1170 * hildon_banner_set_markup:
1171 * @self: a #HildonBanner widget
1172 * @markup: a new text with Pango markup to display in the banner
1174 * Sets the text with markup that is displayed in the banner.
1178 hildon_banner_set_markup (HildonBanner *self,
1179 const gchar *markup)
1182 HildonBannerPrivate *priv;
1184 g_return_if_fail (HILDON_IS_BANNER (self));
1186 priv = HILDON_BANNER_GET_PRIVATE (self);
1189 label = GTK_LABEL (priv->label);
1190 gtk_label_set_markup (label, markup);
1192 hildon_banner_reset_wrap_state (self);
1194 hildon_banner_check_position (GTK_WIDGET(self));
1198 * hildon_banner_set_fraction:
1199 * @self: a #HildonBanner widget
1200 * @fraction: #gdouble
1202 * The fraction is the completion of progressbar,
1203 * the scale is from 0.0 to 1.0.
1204 * Sets the amount of fraction the progressbar has.
1206 * Note that this method only has effect if @self was created with
1207 * hildon_banner_show_progress()
1211 hildon_banner_set_fraction (HildonBanner *self,
1214 HildonBannerPrivate *priv;
1216 g_return_if_fail (HILDON_IS_BANNER (self));
1217 priv = HILDON_BANNER_GET_PRIVATE (self);
1220 g_return_if_fail (GTK_IS_PROGRESS_BAR (priv->main_item));
1221 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (priv->main_item), fraction);
1225 * hildon_banner_set_timeout:
1226 * @self: a #HildonBanner widget
1227 * @timeout: timeout to set in miliseconds.
1229 * Sets the timeout on the banner. After the given amount of miliseconds
1230 * has elapsed the banner will go away. Note that settings this only makes
1231 * sense on the banners that are timed and that have not been yet displayed
1234 * Note that this method only has effect if @self is an information
1235 * banner (created using hildon_banner_show_information() and
1239 hildon_banner_set_timeout (HildonBanner *self,
1242 HildonBannerPrivate *priv;
1244 g_return_if_fail (HILDON_IS_BANNER (self));
1245 priv = HILDON_BANNER_GET_PRIVATE (self);
1248 priv->timeout = timeout;
1252 * hildon_banner_set_icon:
1253 * @self: a #HildonBanner widget
1254 * @icon_name: the name of icon to use. Can be %NULL for default icon
1256 * Sets the icon to be used in the banner.
1258 * Deprecated: This function does nothing. As of hildon 2.2, hildon
1259 * banners don't allow changing their icons.
1262 hildon_banner_set_icon (HildonBanner *self,
1263 const gchar *icon_name)
1268 * hildon_banner_set_icon_from_file:
1269 * @self: a #HildonBanner widget
1270 * @icon_file: the filename of icon to use. Can be %NULL for default icon
1272 * Sets the icon from its filename to be used in the banner.
1274 * Deprecated: This function does nothing. As of hildon 2.2, hildon
1275 * banners don't allow changing their icons.
1278 hildon_banner_set_icon_from_file (HildonBanner *self,
1279 const gchar *icon_file)