Don't hide and show HildonBanner when the screen size changes
[hildon] / hildon / hildon-banner.c
index aeaac58..cbfb263 100644 (file)
@@ -23,8 +23,8 @@
  */
 
 /**
- * SECTION:hildon-banner 
- * @short_description: A widget used to display timed notifications. 
+ * SECTION:hildon-banner
+ * @short_description: A widget used to display timed notifications.
  *
  * #HildonBanner is a small, pop-up window that can be used to display
  * a short, timed notification or information to the user. It can
  * hildon_banner_show_information(), hildon_banner_show_informationf()
  * or hildon_banner_show_information_with_markup().
  *
+ * If the application window has set the _HILDON_DO_NOT_DISTURB flag (using
+ * hildon_gtk_window_set_do_not_disturb() for example), the banner will not
+ * be shown. If you need to override this flag for important information,
+ * you can use the method hildon_banner_show_information_override_dnd().
+ * Please, take into account that this is only for important information.
+ *
+ *
  * Two more kinds of banners are maintained for backward compatibility
  * but are no longer recommended in Hildon 2.2. These are the animated
  * banner (created with hildon_banner_show_animation()) and the
  * hildon_gtk_window_set_progress_indicator() for the preferred way of
  * showing progress notifications in Hildon 2.2.
  *
- * Information banners dissapear automatically after a certain
+ * Information banners are automatically destroyed after a certain
  * period. This is stored in the #HildonBanner:timeout property (in
  * miliseconds), and can be changed using hildon_banner_set_timeout().
  *
  * Note that #HildonBanner<!-- -->s should only be used to display
  * non-critical pieces of information.
+ *
+ * <example>
+ * <title>Using the HildonBanner widget</title>
+ * <programlisting>
+ * void show_info_banner (GtkWidget *parent)
+ * {
+ *   GtkWidget *banner;
+ * <!-- -->
+ *   banner = hildon_banner_show_information (widget, NULL, "Information banner");
+ *   hildon_banner_set_timeout (HILDON_BANNER (banner), 9000);
+ * <!-- -->
+ *   return;
+ * }
+ * </programlisting>
+ * </example>
  */
 
 #ifdef                                          HAVE_CONFIG_H
 #undef                                          HILDON_DISABLE_DEPRECATED
 
 #include                                        "hildon-banner.h"
-#include                                        "hildon-banner-private.h"
+#include                                        "hildon-private.h"
 #include                                        "hildon-defines.h"
 #include                                        "hildon-gtk.h"
 
-/* position relative to the screen */
-
-#define                                         HILDON_BANNER_WINDOW_X 0
-
-#define                                         HILDON_BANNER_WINDOW_Y HILDON_WINDOW_TITLEBAR_HEIGHT
-
 /* max widths */
 
-#define                                         HILDON_BANNER_PROGRESS_WIDTH 104
-
 #define                                         HILDON_BANNER_LABEL_MAX_TIMED \
                                                 (gdk_screen_width() - ((HILDON_MARGIN_TRIPLE) * 2))
 
@@ -111,8 +125,7 @@ static GQuark
 hildon_banner_timed_quark                       (void);
 
 static void 
-hildon_banner_bind_style                        (HildonBanner *self,
-                                                const gchar *name);
+hildon_banner_bind_style                        (HildonBanner *self);
 
 static gboolean 
 hildon_banner_timeout                           (gpointer data);
@@ -157,16 +170,11 @@ hildon_banner_button_press_event                (GtkWidget* widget,
 static gboolean 
 hildon_banner_map_event                         (GtkWidget *widget, 
                                                  GdkEventAny *event);
-static void
-hildon_banner_reset_wrap_state                  (HildonBanner *banner);
 
 static void 
 force_to_wrap_truncated                         (HildonBanner *banner);
 
 static void
-hildon_banner_check_position                    (GtkWidget *widget);
-
-static void
 hildon_banner_realize                           (GtkWidget *widget);
 
 static void 
@@ -187,8 +195,40 @@ static HildonBanner*
 hildon_banner_get_instance_for_widget           (GtkWidget *widget, 
                                                  gboolean timed);
 
+static void
+hildon_banner_set_override_flag                 (HildonBanner *banner);
+
+static void
+reshow_banner                                   (HildonBanner *banner);
+
+static GtkWidget*
+hildon_banner_real_show_information             (GtkWidget *widget,
+                                                 const gchar *text,
+                                                 gboolean override_dnd);
+
 G_DEFINE_TYPE (HildonBanner, hildon_banner, GTK_TYPE_WINDOW)
 
+typedef struct                                  _HildonBannerPrivate HildonBannerPrivate;
+
+#define                                         HILDON_BANNER_GET_PRIVATE(obj) \
+                                                (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
+                                                HILDON_TYPE_BANNER, HildonBannerPrivate));
+
+struct                                          _HildonBannerPrivate
+{
+    GtkWidget   *main_item;
+    GtkWidget   *alignment;
+    GtkWidget   *label;
+    GtkWidget   *layout;
+    GtkWindow   *parent;
+    const gchar *name_suffix;
+    guint        timeout;
+    guint        timeout_id;
+    guint        is_timed             : 1;
+    guint        require_override_dnd : 1;
+    guint        overrides_dnd        : 1;
+};
+
 static GQuark 
 hildon_banner_timed_quark                       (void)
 {
@@ -202,19 +242,21 @@ hildon_banner_timed_quark                       (void)
 
 /* Set the widget and label name to make the correct rc-style attached into them */
 static void 
-hildon_banner_bind_style                  (HildonBanner *self,
-                                          const gchar *name_sufix)
+hildon_banner_bind_style                  (HildonBanner *self)
 {
     HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
+    GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (self));
+    gboolean portrait = gdk_screen_get_width (screen) < gdk_screen_get_height (screen);
+    const gchar *portrait_suffix = portrait ? "-portrait" : NULL;
     gchar *name;
 
     g_assert (priv);
 
-    name = g_strconcat ("HildonBannerLabel-", name_sufix, NULL);
+    name = g_strconcat ("HildonBannerLabel-", priv->name_suffix, NULL);
     gtk_widget_set_name (priv->label, name);
     g_free (name);
 
-    name = g_strconcat ("HildonBanner-", name_sufix, NULL);
+    name = g_strconcat ("HildonBanner-", priv->name_suffix, portrait_suffix, NULL);
     gtk_widget_set_name (GTK_WIDGET (self), name);
     g_free (name);
 }
@@ -241,14 +283,20 @@ simulate_close (GtkWidget* widget)
     return result;
 }
 
+static void
+hildon_banner_size_request                      (GtkWidget      *self,
+                                                 GtkRequisition *req)
+{
+    GTK_WIDGET_CLASS (hildon_banner_parent_class)->size_request (self, req);
+    req->width = gdk_screen_get_width (gtk_widget_get_screen (self));
+}
+
 static gboolean 
 hildon_banner_timeout                           (gpointer data)
 {
     GtkWidget *widget;
     gboolean continue_timeout = FALSE;
 
-    GDK_THREADS_ENTER ();
-
     g_assert (HILDON_IS_BANNER (data));
 
     widget = GTK_WIDGET (data);
@@ -264,8 +312,6 @@ hildon_banner_timeout                           (gpointer data)
 
     g_object_unref (widget);
 
-    GDK_THREADS_LEAVE ();
-
     return continue_timeout;
 }
 
@@ -291,7 +337,7 @@ hildon_banner_ensure_timeout                    (HildonBanner *self)
     g_assert (priv);
 
     if (priv->timeout_id == 0 && priv->is_timed && priv->timeout > 0)
-        priv->timeout_id = g_timeout_add (priv->timeout, 
+        priv->timeout_id = gdk_threads_add_timeout (priv->timeout,
                 hildon_banner_timeout, self);
 }
 
@@ -468,7 +514,6 @@ hildon_banner_constructor                       (GType type,
            assertion `nqueue->freeze_count > 0' failed */
 
         g_object_freeze_notify (banner);
-        hildon_banner_reset_wrap_state (HILDON_BANNER (banner));
     }
 
     /* We restart possible timeouts for each new timed banner request */
@@ -523,7 +568,7 @@ hildon_banner_map                               (GtkWidget *widget)
          * being closed by other non-temporary windows */
         gtk_window_set_is_temporary (GTK_WINDOW (widget), FALSE);
 
-        hildon_banner_check_position (widget);
+        gtk_window_move (GTK_WINDOW (widget), 0, HILDON_WINDOW_TITLEBAR_HEIGHT);
     }
 }
 #endif
@@ -544,22 +589,24 @@ hildon_banner_map_event                         (GtkWidget *widget,
 }  
 
 static void
-hildon_banner_reset_wrap_state (HildonBanner *banner)
+banner_do_set_text                              (HildonBanner *banner,
+                                                 const gchar  *text,
+                                                 gboolean      is_markup)
 {
-    PangoLayout *layout;
     HildonBannerPrivate *priv;
+    GtkRequisition req;
 
     priv = HILDON_BANNER_GET_PRIVATE (banner);
-    g_assert (priv);
-
-    layout = gtk_label_get_layout (GTK_LABEL (priv->label));
-
-    pango_layout_set_width (layout, -1);
-    priv->has_been_wrapped = FALSE;
-    priv->has_been_truncated = FALSE;
 
+    if (is_markup) {
+        gtk_label_set_markup (GTK_LABEL (priv->label), text);
+    } else {
+        gtk_label_set_text (GTK_LABEL (priv->label), text);
+    }
     gtk_widget_set_size_request (priv->label, -1, -1);
-    gtk_widget_set_size_request (GTK_WIDGET (banner), -1, -1);
+    gtk_widget_size_request (priv->label, &req);
+
+    force_to_wrap_truncated (banner);
 }
 
 /* force to wrap truncated label by setting explicit size request
@@ -569,7 +616,7 @@ force_to_wrap_truncated                         (HildonBanner *banner)
 {
     GtkLabel *label;
     PangoLayout *layout;
-    int width_text, width_max;
+    int width_max;
     int width = -1;
     int height = -1;
     PangoRectangle logical;
@@ -583,7 +630,7 @@ force_to_wrap_truncated                         (HildonBanner *banner)
     layout = gtk_label_get_layout (label);
 
     pango_layout_get_extents (layout, NULL, &logical);
-    width_text = PANGO_PIXELS (logical.width);
+    width = PANGO_PIXELS (logical.width);
 
     width_max = priv->is_timed ? HILDON_BANNER_LABEL_MAX_TIMED
         : HILDON_BANNER_LABEL_MAX_PROGRESS;
@@ -591,13 +638,8 @@ force_to_wrap_truncated                         (HildonBanner *banner)
     /* If the width of the label is going to exceed the maximum allowed
      * width, enforce the maximum allowed width now.
      */
-    if (priv->has_been_wrapped
-        || width_text >= width_max
-        || pango_layout_is_wrapped (layout)) {
-        /* Force wrapping by setting the maximum size */
+    if (width >= width_max || pango_layout_is_wrapped (layout)) {
         width = width_max;
-
-        priv->has_been_wrapped = TRUE;
     }
 
     /* Make the label update its layout; and update our layout pointer
@@ -611,9 +653,7 @@ force_to_wrap_truncated                         (HildonBanner *banner)
     /* If the layout has now been wrapped and exceeds 3 lines, we truncate
      * the rest of the label according to spec.
      */
-    if (priv->has_been_truncated
-        || (pango_layout_is_wrapped (layout)
-            && pango_layout_get_line_count (layout) > 3)) {
+    if (pango_layout_is_wrapped (layout) && pango_layout_get_line_count (layout) > 3) {
         int lines;
 
         pango_layout_get_extents (layout, NULL, &logical);
@@ -625,42 +665,27 @@ force_to_wrap_truncated                         (HildonBanner *banner)
          * FIXME: Pango >= 1.20 has pango_layout_set_height().
          */
         height = (PANGO_PIXELS (logical.height) * 3) / lines + 1;
-        priv->has_been_truncated = TRUE;
     }
 
     /* Set the new width/height if applicable */
     gtk_widget_set_size_request (GTK_WIDGET (label), width, height);
 }
 
-
 static void
-hildon_banner_check_position                    (GtkWidget *widget)
-{
-    gint x, y;
-    GtkRequisition req;
-
-    gtk_widget_set_size_request (widget, gdk_screen_width (), -1);
-
-    force_to_wrap_truncated (HILDON_BANNER(widget)); /* see N#27000 and G#329646 */
-
-    gtk_widget_size_request (widget, &req);
-
-    if (req.width == 0)
-    {
-        return;
-    }
-
-    x = HILDON_BANNER_WINDOW_X;
-
-    y = HILDON_BANNER_WINDOW_Y;
+screen_size_changed                            (GdkScreen *screen,
+                                                GtkWindow *banner)
 
-    gtk_window_move (GTK_WINDOW (widget), x, y);
+{
+    HildonBanner *hbanner = HILDON_BANNER (banner);
+    hildon_banner_bind_style (hbanner);
+    reshow_banner (hbanner);
 }
 
 static void
 hildon_banner_realize                           (GtkWidget *widget)
 {
     GdkWindow *gdkwin;
+    GdkScreen *screen;
     GdkAtom atom;
     guint32 portrait = 1;
     const gchar *notification_type = "_HILDON_NOTIFICATION_TYPE_BANNER";
@@ -675,8 +700,6 @@ hildon_banner_realize                           (GtkWidget *widget)
     gdk_window_set_type_hint (widget->window, GDK_WINDOW_TYPE_HINT_NOTIFICATION);
     gtk_window_set_transient_for (GTK_WINDOW (widget), (GtkWindow *) priv->parent);
 
-    hildon_banner_check_position (widget);
-
     gdkwin = widget->window;
 
     /* Set the _HILDON_NOTIFICATION_TYPE property so Matchbox places the window correctly */
@@ -688,6 +711,24 @@ hildon_banner_realize                           (GtkWidget *widget)
     atom = gdk_atom_intern ("_HILDON_PORTRAIT_MODE_SUPPORT", FALSE);
     gdk_property_change (gdkwin, atom, gdk_x11_xatom_to_atom (XA_CARDINAL), 32,
                          GDK_PROP_MODE_REPLACE, (gpointer) &portrait, 1);
+
+    /* Manage override flag */
+    if ((priv->require_override_dnd)&&(!priv->overrides_dnd)) {
+      hildon_banner_set_override_flag (HILDON_BANNER (widget));
+        priv->overrides_dnd = TRUE;
+    }
+
+    screen = gtk_widget_get_screen (widget);
+    g_signal_connect (screen, "size-changed", G_CALLBACK (screen_size_changed), widget);
+}
+
+static void
+hildon_banner_unrealize                         (GtkWidget *widget)
+{
+    GdkScreen *screen = gtk_widget_get_screen (widget);
+    g_signal_handlers_disconnect_by_func (screen, G_CALLBACK (screen_size_changed), widget);
+
+    GTK_WIDGET_CLASS (hildon_banner_parent_class)->unrealize (widget);
 }
 
 static void 
@@ -709,8 +750,10 @@ hildon_banner_class_init                        (HildonBannerClass *klass)
     object_class->set_property = hildon_banner_set_property;
     object_class->get_property = hildon_banner_get_property;
     GTK_OBJECT_CLASS (klass)->destroy = hildon_banner_destroy;
+    widget_class->size_request = hildon_banner_size_request;
     widget_class->map_event = hildon_banner_map_event;
     widget_class->realize = hildon_banner_realize;
+    widget_class->unrealize = hildon_banner_unrealize;
     widget_class->button_press_event = hildon_banner_button_press_event;
 #if defined(MAEMO_GTK)
     widget_class->map = hildon_banner_map;
@@ -747,7 +790,7 @@ hildon_banner_class_init                        (HildonBannerClass *klass)
     /**
      * HildonBanner:timeout:
      *
-     * The time before making the banner banner go away. This needs 
+     * The time before destroying the banner. This needs
      * to be adjusted before the banner is mapped to the screen.
      *                      
      */
@@ -768,22 +811,26 @@ hildon_banner_init                              (HildonBanner *self)
     g_assert (priv);
 
     priv->parent = NULL;
+    priv->overrides_dnd = FALSE;
+    priv->require_override_dnd = FALSE;
+    priv->name_suffix = NULL;
 
     /* Initialize the common layout inside banner */
+    priv->alignment = gtk_alignment_new (0.5, 0.5, 0, 0);
     priv->layout = gtk_hbox_new (FALSE, HILDON_MARGIN_DEFAULT);
 
     priv->label = g_object_new (GTK_TYPE_LABEL, NULL);
     gtk_label_set_line_wrap (GTK_LABEL (priv->label), TRUE);
     gtk_label_set_line_wrap_mode (GTK_LABEL (priv->label), PANGO_WRAP_WORD_CHAR);
+    gtk_label_set_justify (GTK_LABEL (priv->label), GTK_JUSTIFY_CENTER);
 
     gtk_container_set_border_width (GTK_CONTAINER (priv->layout), HILDON_MARGIN_DEFAULT);
-    gtk_container_add (GTK_CONTAINER (self), priv->layout);
-    gtk_box_pack_start (GTK_BOX (priv->layout), priv->label, TRUE, TRUE, 0);
+    gtk_container_add (GTK_CONTAINER (self), priv->alignment);
+    gtk_container_add (GTK_CONTAINER (priv->alignment), priv->layout);
+    gtk_box_pack_start (GTK_BOX (priv->layout), priv->label, FALSE, FALSE, 0);
 
     gtk_window_set_accept_focus (GTK_WINDOW (self), FALSE);
 
-    hildon_banner_reset_wrap_state (self);
-
     gtk_widget_add_events (GTK_WIDGET (self), GDK_BUTTON_PRESS_MASK);
 }
 
@@ -821,7 +868,7 @@ hildon_banner_ensure_child                      (HildonBanner *self,
         /* Use user provided widget or create a new one */
         priv->main_item = widget = user_widget ? 
             user_widget : GTK_WIDGET (g_object_new_valist(type, first_property, args));
-        gtk_box_pack_start (GTK_BOX (priv->layout), widget, TRUE, TRUE, 0);
+        gtk_box_pack_start (GTK_BOX (priv->layout), widget, FALSE, FALSE, 0);
     }
 
     /* We make sure that the widget exists in desired position. Different
@@ -841,47 +888,6 @@ hildon_banner_get_instance_for_widget           (GtkWidget *widget,
     return g_object_new (HILDON_TYPE_BANNER, "parent-window", window, "is-timed", timed, NULL);
 }
 
-static GtkWidget *
-hildon_banner_create_animation (void)
-{
-    GtkWidget *image;
-    GdkPixbufSimpleAnim *anim;
-    GdkPixbuf *frame;
-    GtkIconTheme *theme;
-    GError *error = NULL;
-    gchar *icon_name;
-    gint i;
-
-    anim = gdk_pixbuf_simple_anim_new (HILDON_ICON_PIXEL_SIZE_STYLUS,
-                                      HILDON_ICON_PIXEL_SIZE_STYLUS,
-                                      HILDON_BANNER_ANIMATION_FRAMERATE);
-    gdk_pixbuf_simple_anim_set_loop (anim, TRUE);
-    theme = gtk_icon_theme_get_default ();
-
-    for (i = 1; i <= HILDON_BANNER_ANIMATION_NFRAMES; i++) {
-       icon_name = g_strdup_printf (HILDON_BANNER_ANIMATION_TMPL, i);
-       frame = gtk_icon_theme_load_icon (theme, icon_name, HILDON_ICON_PIXEL_SIZE_STYLUS,
-                                         0, &error);
-
-       if (error) {
-           g_warning ("Icon theme lookup for icon `%s' failed: %s",
-                      icon_name, error->message);
-           g_error_free (error);
-           error = NULL;
-       } else {
-               gdk_pixbuf_simple_anim_add_frame (anim, frame);
-       }
-
-       g_object_unref (frame);
-       g_free (icon_name);
-    }
-
-    image = gtk_image_new_from_animation (GDK_PIXBUF_ANIMATION (anim));
-    g_object_unref (anim);
-
-    return image;
-}
-
 /**
  * hildon_banner_show_information:
  * @widget: the #GtkWidget that is the owner of the banner
@@ -889,11 +895,12 @@ hildon_banner_create_animation (void)
  * any value that you pass will be ignored
  * @text: Text to display
  *
- * This function creates and displays an information banner that
- * automatically goes away after certain time period. For each window
- * in your application there can only be one timed banner, so if you
- * spawn a new banner before the earlier one has timed out, the
- * previous one will be replaced.
+ * This function creates and displays an information banner that is
+ * automatically destroyed after a certain time period (see
+ * hildon_banner_set_timeout()). For each window in your application
+ * there can only be one timed banner, so if you spawn a new banner
+ * before the earlier one has timed out, the previous one will be
+ * replaced.
  *
  * Returns: The newly created banner
  *
@@ -903,20 +910,81 @@ hildon_banner_show_information                  (GtkWidget *widget,
                                                  const gchar *icon_name,
                                                  const gchar *text)
 {
+    return hildon_banner_real_show_information (widget, text, FALSE);
+}
+
+/**
+ * hildon_banner_show_information_override_dnd:
+ * @widget: the #GtkWidget that is the owner of the banner
+ * @text: Text to display
+ *
+ * Equivalent to hildon_banner_show_information(), but overriding the
+ * "do not disturb" flag.
+ *
+ * Returns: The newly created banner
+ *
+ * Since: 2.2
+ *
+ */
+GtkWidget*
+hildon_banner_show_information_override_dnd     (GtkWidget *widget,
+                                                 const gchar *text)
+{
+    return hildon_banner_real_show_information (widget, text, TRUE);
+}
+
+static void
+hildon_banner_set_override_flag                 (HildonBanner *banner)
+{
+    guint32 state = 1;
+
+    gdk_property_change (GTK_WIDGET (banner)->window,
+                         gdk_atom_intern_static_string ("_HILDON_DO_NOT_DISTURB_OVERRIDE"),
+                         gdk_x11_xatom_to_atom (XA_INTEGER),
+                         32,
+                         GDK_PROP_MODE_REPLACE,
+                         (const guchar*) &state,
+                         1);
+}
+
+static void
+reshow_banner                                   (HildonBanner *banner)
+{
+    if (GTK_WIDGET_VISIBLE (banner)) {
+        gint width = gdk_screen_get_width (gtk_widget_get_screen (GTK_WIDGET (banner)));
+        gtk_window_resize (GTK_WINDOW (banner), width, 1);
+    }
+    force_to_wrap_truncated (banner);
+    gtk_widget_show_all (GTK_WIDGET (banner));
+}
+
+static GtkWidget*
+hildon_banner_real_show_information             (GtkWidget *widget,
+                                                 const gchar *text,
+                                                 gboolean override_dnd)
+{
     HildonBanner *banner;
+    HildonBannerPrivate *priv = NULL;
 
     g_return_val_if_fail (text != NULL, NULL);
 
     /* Prepare banner */
     banner = hildon_banner_get_instance_for_widget (widget, TRUE);
+    priv = HILDON_BANNER_GET_PRIVATE (banner);
 
-    hildon_banner_set_text (banner, text);
-    hildon_banner_bind_style (banner, "information");
+    priv->name_suffix = "information";
+    banner_do_set_text (banner, text, FALSE);
+    hildon_banner_bind_style (banner);
+
+    if (override_dnd) {
+      /* so on the realize it will set the property */
+      priv->require_override_dnd = TRUE;
+    }
 
     /* Show the banner, since caller cannot do that */
-    gtk_widget_show_all (GTK_WIDGET (banner));
+    reshow_banner (banner);
 
-    return (GtkWidget *) banner;
+    return GTK_WIDGET (banner);
 }
 
 /**
@@ -927,7 +995,7 @@ hildon_banner_show_information                  (GtkWidget *widget,
  * @format: a printf-like format string
  * @Varargs: arguments for the format string
  *
- * A helper function for #hildon_banner_show_information with
+ * A helper function for hildon_banner_show_information() with
  * string formatting.
  *
  * Returns: the newly created banner
@@ -962,11 +1030,12 @@ hildon_banner_show_informationf                 (GtkWidget *widget,
  * any value that you pass will be ignored
  * @markup: a markup string to display (see <link linkend="PangoMarkupFormat">Pango markup format</link>)
  *
- * This function creates and displays an information banner that
- * automatically goes away after certain time period. For each window
- * in your application there can only be one timed banner, so if you
- * spawn a new banner before the earlier one has timed out, the
- * previous one will be replaced.
+ * This function creates and displays an information banner that is
+ * automatically destroyed after certain time period (see
+ * hildon_banner_set_timeout()). For each window in your application
+ * there can only be one timed banner, so if you spawn a new banner
+ * before the earlier one has timed out, the previous one will be
+ * replaced.
  *
  * Returns: the newly created banner
  *
@@ -977,18 +1046,21 @@ hildon_banner_show_information_with_markup      (GtkWidget *widget,
                                                  const gchar *markup)
 {
     HildonBanner *banner;
+    HildonBannerPrivate *priv;
 
     g_return_val_if_fail (icon_name == NULL || icon_name[0] != 0, NULL);
     g_return_val_if_fail (markup != NULL, NULL);
 
     /* Prepare banner */
     banner = hildon_banner_get_instance_for_widget (widget, TRUE);
+    priv = HILDON_BANNER_GET_PRIVATE (banner);
 
-    hildon_banner_set_markup (banner, markup);
-    hildon_banner_bind_style (banner, "information");
+    priv->name_suffix = "information";
+    banner_do_set_text (banner, markup, TRUE);
+    hildon_banner_bind_style (banner);
 
     /* Show the banner, since caller cannot do that */
-    gtk_widget_show_all (GTK_WIDGET (banner));
+    reshow_banner (banner);
 
     return (GtkWidget *) banner;
 }
@@ -1007,15 +1079,20 @@ hildon_banner_show_information_with_markup      (GtkWidget *widget,
  * notifications with timed banners. In this case the banners are
  * located so that you can somehow see both.
  *
- * Please note that banners are destroyed automatically once the
+ * Unlike information banners (created with
+ * hildon_banner_show_information()), animation banners are not
+ * destroyed automatically using a timeout. You have to destroy them
+ * yourself.
+ *
+ * Please note also that these banners are destroyed automatically if the
  * window they are attached to is closed. The pointer that you receive
  * with this function does not contain additional references, so it
  * can become invalid without warning (this is true for all toplevel
  * windows in gtk). To make sure that the banner does not disappear
  * automatically, you can separately ref the return value (this
  * doesn't prevent the banner from disappearing, just the object from
- * being finalized). In this case you have to call both
- * gtk_widget_destroy() followed by g_object_unref() (in this order).
+ * being finalized). In this case you have to call
+ * gtk_widget_destroy() followed by g_object_unref().
  *
  * Returns: a #HildonBanner widget. You must call gtk_widget_destroy()
  *          once you are done with the banner.
@@ -1030,21 +1107,27 @@ hildon_banner_show_animation                    (GtkWidget *widget,
 {
     HildonBanner *banner;
     GtkWidget *image_widget;
+    HildonBannerPrivate *priv;
 
     g_return_val_if_fail (text != NULL, NULL);
 
-    image_widget = hildon_banner_create_animation ();
+    image_widget = hildon_private_create_animation (
+        HILDON_BANNER_ANIMATION_FRAMERATE,
+        HILDON_BANNER_ANIMATION_TMPL,
+        HILDON_BANNER_ANIMATION_NFRAMES);
 
     /* Prepare banner */
     banner = hildon_banner_get_instance_for_widget (widget, FALSE);
     hildon_banner_ensure_child (banner, image_widget, 0,
             GTK_TYPE_IMAGE, "yalign", 0.0, NULL);
 
-    hildon_banner_set_text (banner, text);
-    hildon_banner_bind_style (banner, "animation");
+    priv = HILDON_BANNER_GET_PRIVATE (banner);
+    priv->name_suffix = "animation";
+    banner_do_set_text (banner, text, FALSE);
+    hildon_banner_bind_style (banner);
 
     /* And show it */
-    gtk_widget_show_all (GTK_WIDGET (banner));
+    reshow_banner (banner);
 
     return (GtkWidget *) banner;
 }
@@ -1056,7 +1139,7 @@ hildon_banner_show_animation                    (GtkWidget *widget,
  * any value that you pass will be ignored
  * @text: text to display.
  *
- * Shows progress notification. See #hildon_banner_show_animation
+ * Shows progress notification. See hildon_banner_show_animation()
  * for more information.
  * 
  * Returns: a #HildonBanner widget. You must call #gtk_widget_destroy
@@ -1079,14 +1162,15 @@ hildon_banner_show_progress                     (GtkWidget *widget,
     priv = HILDON_BANNER_GET_PRIVATE (banner);
     g_assert (priv);
 
-    hildon_banner_set_text (banner, text);
-    hildon_banner_bind_style (banner, "progress");
+    priv->name_suffix = "progress";
+    banner_do_set_text (banner, text, FALSE);
+    hildon_banner_bind_style (banner);
 
     if (priv->parent)
         hildon_gtk_window_set_progress_indicator (priv->parent, 1);
 
     /* Show the banner */
-    gtk_widget_show_all (GTK_WIDGET (banner));
+    reshow_banner (banner);
 
     return GTK_WIDGET (banner);   
 }
@@ -1103,26 +1187,12 @@ void
 hildon_banner_set_text                          (HildonBanner *self, 
                                                  const gchar *text)
 {
-    GtkLabel *label;
-    HildonBannerPrivate *priv;
-    const gchar *existing_text;
-
     g_return_if_fail (HILDON_IS_BANNER (self));
 
-    priv = HILDON_BANNER_GET_PRIVATE (self);
-    g_assert (priv);
-
-    label = GTK_LABEL (priv->label);
-    existing_text = gtk_label_get_text (label);
+    banner_do_set_text (self, text, FALSE);
 
-    if (existing_text != NULL && 
-        text != NULL          &&
-        strcmp (existing_text, text) != 0) {
-            gtk_label_set_text (label, text);
-            hildon_banner_reset_wrap_state (self);
-    }
-
-    hildon_banner_check_position (GTK_WIDGET (self));
+    if (GTK_WIDGET_VISIBLE (self))
+        reshow_banner (self);
 }
 
 /**
@@ -1137,20 +1207,12 @@ void
 hildon_banner_set_markup                        (HildonBanner *self, 
                                                  const gchar *markup)
 {
-    GtkLabel *label;
-    HildonBannerPrivate *priv;
-
     g_return_if_fail (HILDON_IS_BANNER (self));
 
-    priv = HILDON_BANNER_GET_PRIVATE (self);
-    g_assert (priv);
-
-    label = GTK_LABEL (priv->label);
-    gtk_label_set_markup (label, markup);
-
-    hildon_banner_reset_wrap_state (self);
+    banner_do_set_text (self, markup, TRUE);
 
-    hildon_banner_check_position (GTK_WIDGET(self));
+    if (GTK_WIDGET_VISIBLE (self))
+        reshow_banner (self);
 }
 
 /**
@@ -1180,8 +1242,8 @@ hildon_banner_set_fraction                      (HildonBanner *self,
  * @timeout: timeout to set in miliseconds.
  *
  * Sets the timeout on the banner. After the given amount of miliseconds
- * has elapsed the banner will go away. Note that settings this only makes
- * sense on the banners that are timed and that have not been yet displayed
+ * has elapsed the banner will be destroyed. Setting this only makes
+ * sense on banners that are timed and that have not been yet displayed
  * on the screen.
  *
  * Note that this method only has effect if @self is an information