Set position of HildonBanner after mapping
[hildon] / hildon / hildon-banner.c
index 9cfc7e8..c570e16 100644 (file)
 #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_LABEL_MAX_TIMED \
@@ -131,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);
@@ -177,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 
@@ -225,18 +213,17 @@ typedef struct                                  _HildonBannerPrivate HildonBanne
 
 struct                                          _HildonBannerPrivate
 {
-    GtkWidget *main_item;
-    GtkWidget *alignment;
-    GtkWidget *label;
-    GtkWidget *layout;
-    GtkWindow *parent;
-    guint      timeout;
-    guint      timeout_id;
-    guint      is_timed             : 1;
-    guint      has_been_wrapped     : 1;
-    guint      has_been_truncated   : 1;
-    guint      require_override_dnd : 1;
-    guint      overrides_dnd        : 1;
+    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 
@@ -252,19 +239,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);
 }
@@ -291,6 +280,14 @@ 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)
 {
@@ -518,7 +515,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 */
@@ -573,7 +569,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
@@ -594,22 +590,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
@@ -619,7 +617,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;
@@ -633,7 +631,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;
@@ -641,13 +639,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
@@ -661,9 +654,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);
@@ -675,44 +666,20 @@ 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;
-
-    gtk_window_move (GTK_WINDOW (widget), x, y);
-}
-
 static void
 screen_size_changed                            (GdkScreen *screen,
                                                 GtkWindow *banner)
 
 {
+    hildon_banner_bind_style (HILDON_BANNER (banner));
     gtk_window_reshow_with_initial_size (banner);
+    force_to_wrap_truncated (HILDON_BANNER (banner));
 }
 
 static void
@@ -734,8 +701,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 */
@@ -786,6 +751,7 @@ 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;
@@ -848,6 +814,7 @@ hildon_banner_init                              (HildonBanner *self)
     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);
@@ -856,6 +823,7 @@ hildon_banner_init                              (HildonBanner *self)
     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->alignment);
@@ -864,8 +832,6 @@ hildon_banner_init                              (HildonBanner *self)
 
     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);
 }
 
@@ -982,6 +948,16 @@ hildon_banner_set_override_flag                 (HildonBanner *banner)
                          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,
@@ -997,8 +973,9 @@ hildon_banner_real_show_information             (GtkWidget *widget,
     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 */
@@ -1006,7 +983,7 @@ hildon_banner_real_show_information             (GtkWidget *widget,
     }
 
     /* Show the banner, since caller cannot do that */
-    gtk_widget_show_all (GTK_WIDGET (banner));
+    reshow_banner (banner);
 
     return GTK_WIDGET (banner);
 }
@@ -1070,18 +1047,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;
 }
@@ -1128,6 +1108,7 @@ hildon_banner_show_animation                    (GtkWidget *widget,
 {
     HildonBanner *banner;
     GtkWidget *image_widget;
+    HildonBannerPrivate *priv;
 
     g_return_val_if_fail (text != NULL, NULL);
 
@@ -1141,11 +1122,13 @@ hildon_banner_show_animation                    (GtkWidget *widget,
     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;
 }
@@ -1180,14 +1163,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);   
 }
@@ -1204,26 +1188,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);
-
-    if (existing_text != NULL && 
-        text != NULL          &&
-        strcmp (existing_text, text) != 0) {
-            gtk_label_set_text (label, text);
-            hildon_banner_reset_wrap_state (self);
-    }
+    banner_do_set_text (self, text, FALSE);
 
-    hildon_banner_check_position (GTK_WIDGET (self));
+    if (GTK_WIDGET_VISIBLE (self))
+        reshow_banner (self);
 }
 
 /**
@@ -1238,20 +1208,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);
 }
 
 /**