Release 0.0.6
[conv-inbox] / src / el-home-applet.c
index b0e9efe..d871a5d 100644 (file)
@@ -33,7 +33,7 @@
                 EL_TYPE_HOME_APPLET, ELHomeAppletPrivate))
 
 #define BOX_WIDTH 352
-#define BOX_HEIGHT 256
+#define BOX_HEIGHT 266
 
 #define C_WIDTH (BOX_WIDTH - 2*HILDON_MARGIN_HALF)
 #define C_HEIGHT (BOX_HEIGHT - 2*HILDON_MARGIN_HALF)
@@ -46,6 +46,9 @@
 
 #define BOX_RADIOUS 10
 
+#define SCROLL_PERIOD 100 /* ms */
+#define SCROLL_STEP 1 /* pixel */
+
 struct _ELHomeAppletPrivate
 {
         RTComEl *eventlogger;
@@ -55,6 +58,7 @@ struct _ELHomeAppletPrivate
         GtkWidget *unread;
         GtkWidget *received;
         GtkWidget *empty;
+        GtkWidget *cut_message;
 
         gchar *message;
         gint event_id;
@@ -72,8 +76,11 @@ struct _ELHomeAppletPrivate
 
         guint idle_id;
 
+        cairo_surface_t *message_surface;
+
         gboolean scroll_on_click;
         gint scroll_offset;
+        gint hidden_message_height;
         guint scroll_anim_id;
 };
 
@@ -137,24 +144,18 @@ rounded_rectangle (cairo_t *cr,
                         x + r, y);
 }
 
-static gboolean
-draw_text (cairo_t *cr,
+static cairo_surface_t*
+draw_text (cairo_t              *cr,
            PangoFontDescription *desc,
-           const gchar *text,
-           double x,
-           double y,
-           int width,
-           int height,
-           int offset)
+           const gchar          *text,
+           gint                  width,
+           gint                 *height)
 {
         PangoLayout *layout;
-        gboolean result;
         PangoRectangle extent;
 
-        cairo_save (cr);
-        cairo_rectangle (cr,
-                         x, y, width, height);
-        cairo_clip (cr);
+        cairo_surface_t *gdk_surface, *result_surface;
+        cairo_t *msg_cr;
 
         /* Create a PangoLayout, set the font and text */
         layout = pango_cairo_create_layout (cr);
@@ -164,31 +165,34 @@ draw_text (cairo_t *cr,
         pango_layout_set_font_description (layout, desc);
 
         pango_layout_set_wrap (layout, PANGO_WRAP_WORD_CHAR);
-        if (!offset)
-                pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END);
         pango_layout_set_width (layout, PANGO_SCALE*width);
-        pango_layout_set_height (layout, PANGO_SCALE*height);
 
+        pango_layout_get_pixel_extents (layout, NULL, &extent);
+        *height = extent.height;
+
+        gdk_surface = cairo_get_target (cr);
+        result_surface = cairo_surface_create_similar
+                (gdk_surface,
+                 CAIRO_CONTENT_COLOR_ALPHA,
+                 width,
+                 extent.height);
+        msg_cr = cairo_create (result_surface);
+
+        pango_cairo_update_layout (msg_cr, layout);
         /* draw shadow */
-        cairo_move_to (cr, x + 1, y + 1 - offset);
-        cairo_set_source_rgba (cr, 0.2, 0.2, 0.2, 0.8);
-        pango_cairo_show_layout (cr, layout);
+        cairo_move_to (msg_cr, 1, 1);
+        cairo_set_source_rgba (msg_cr, 0.2, 0.2, 0.2, 0.8);
+        pango_cairo_show_layout (msg_cr, layout);
 
         /* draw fg */
-        cairo_move_to (cr, x, y - offset);
-        cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 1.0);
-        pango_cairo_show_layout (cr, layout);
-
-        pango_layout_get_pixel_extents (layout, NULL, &extent);
-        if (offset)
-                result = height < (extent.height - offset);
-        else
-                result = pango_layout_is_ellipsized (layout);
+        cairo_move_to (msg_cr, 0, 0);
+        cairo_set_source_rgba (msg_cr, 1.0, 1.0, 1.0, 1.0);
+        pango_cairo_show_layout (msg_cr, layout);
 
+        cairo_destroy (msg_cr);
         g_object_unref (layout);
-        cairo_restore (cr);
 
-        return result;
+        return result_surface;
 }
 
 static void
@@ -198,6 +202,7 @@ stop_scroll_anim (ELHomeAppletPrivate *priv)
                 g_source_remove (priv->scroll_anim_id);
                 priv->scroll_anim_id = 0;
                 priv->scroll_on_click = FALSE;
+                gtk_widget_hide (priv->cut_message);
         }
 }
 
@@ -229,6 +234,25 @@ style_set_cb (GtkWidget *widget,
         }
 }
 
+static void
+notify_on_current_desktop (GObject      *object,
+                           GParamSpec   *unused G_GNUC_UNUSED,
+                           ELHomeApplet *self)
+{
+        ELHomeAppletPrivate *priv = self->priv;
+        gboolean on;
+
+        g_object_get (object, "is-on-current-desktop", &on, NULL);
+        if (!on) {
+                stop_scroll_anim (self->priv);
+                priv->scroll_on_click = priv->scroll_offset;
+                priv->scroll_offset = 0;
+                if (priv->scroll_on_click)
+                        gtk_widget_show (priv->cut_message);
+                gtk_widget_queue_draw (GTK_WIDGET (self));
+        }
+}
+
 static gboolean
 expose_event (GtkWidget *self, GdkEventExpose *event)
 {
@@ -331,23 +355,38 @@ expose_event (GtkWidget *self, GdkEventExpose *event)
         /* cairo_stroke (cr); */
 
         /* draw message */
-        gboolean ellipsized;
-        ellipsized = draw_text (cr,
-                                priv->font_desc,
-                                priv->message,
-                                2*C_X, HEADER_HEIGHT,
-                                MESSAGE_WIDTH,
-                                message_height,
-                                priv->scroll_offset);
-        if (!priv->scroll_anim_id && !priv->scroll_offset)
-                priv->scroll_on_click = ellipsized;
+        if (!priv->message_surface) {
+                gint height;
+
+                priv->message_surface = draw_text (cr,
+                                                   priv->font_desc,
+                                                   priv->message,
+                                                   MESSAGE_WIDTH,
+                                                   &height);
+
+                priv->hidden_message_height = height - message_height;
+                priv->scroll_on_click = priv->hidden_message_height > 0;
+                if (priv->scroll_on_click)
+                        gtk_widget_show (priv->cut_message);
+        }
+
+        cairo_rectangle (cr,
+                         2*C_X,
+                         HEADER_HEIGHT,
+                         MESSAGE_WIDTH,
+                         message_height);
+        cairo_clip (cr);
+
+        cairo_set_source_surface (cr,
+                                  priv->message_surface,
+                                  2*C_X,
+                                  HEADER_HEIGHT - priv->scroll_offset);
+        cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+        cairo_paint (cr);
 
         cairo_pattern_destroy (grad);
         cairo_destroy (cr);
 
-        if (!priv->scroll_on_click && !ellipsized && priv->scroll_offset)
-                stop_scroll_anim (priv);
-
         return GTK_WIDGET_CLASS (el_home_applet_parent_class)->expose_event (self, event);
 }
 
@@ -469,8 +508,14 @@ show_event (ELHomeApplet *self, RTComElIter *it)
 
         g_free (remote);
 
-        stop_scroll_anim (self->priv);
+        stop_scroll_anim (priv);
         priv->scroll_offset = 0;
+        if (priv->message_surface) {
+                cairo_surface_destroy (priv->message_surface);
+                priv->message_surface = NULL;
+        }
+
+        gtk_widget_hide (priv->cut_message);
         gtk_widget_queue_draw (GTK_WIDGET (self));
 }
 
@@ -627,11 +672,22 @@ static gboolean
 scroll_anim_cb (ELHomeApplet *self)
 {
         ELHomeAppletPrivate *priv = self->priv;
+        gboolean to_continue;
 
-        priv->scroll_offset += 1;
-        gtk_widget_queue_draw (GTK_WIDGET (self));
+        priv->scroll_offset += SCROLL_STEP;
+        gtk_widget_queue_draw_area (GTK_WIDGET (self),
+                                    3*C_X,
+                                    HEADER_HEIGHT + C_Y,
+                                    MESSAGE_WIDTH,
+                                    C_HEIGHT - priv->received->allocation.height - HEADER_HEIGHT);
 
-        return TRUE;
+        to_continue = priv->scroll_offset <= priv->hidden_message_height;
+        if (!to_continue) {
+                priv->scroll_anim_id = 0;
+                gtk_widget_hide (priv->cut_message);
+        }
+
+        return to_continue;
 }
 
 static gboolean
@@ -661,14 +717,16 @@ button_release_event_cb (GtkWidget      *widget,
                 stop_scroll_anim (priv);
                 if (priv->scroll_on_click) {
                         priv->scroll_on_click = FALSE;
-                        priv->scroll_anim_id = g_timeout_add (100,
+                        priv->scroll_anim_id = g_timeout_add (SCROLL_PERIOD,
                                                               (GSourceFunc)scroll_anim_cb,
                                                               self);
                 }
-                else
+                else {
 #ifndef DEBUG_LAYOUT
                         mark_as_read (self);
 #endif
+                }
+
                 gtk_widget_queue_draw (widget);
         }
 
@@ -696,7 +754,7 @@ el_home_applet_init (ELHomeApplet *self)
 {
         ELHomeAppletPrivate *priv;
         GtkWidget *event_box;
-        GtkWidget *hbox, *vbox, *align;
+        GtkWidget *hbox, *vbox, *align, *footer;
 
         self->priv = EL_HOME_APPLET_GET_PRIVATE (self);
         priv = self->priv;
@@ -741,21 +799,31 @@ el_home_applet_init (ELHomeApplet *self)
         gtk_misc_set_alignment (GTK_MISC (priv->received),
                                 1.0f,
                                 0.5f);
-        gtk_widget_set_size_request (priv->received,
-                                     MESSAGE_WIDTH,
-                                     -1);
         hildon_helper_set_logical_font (priv->received, "SmallSystemFont");
         gtk_widget_set_name (priv->received, "hildon-shadow-label");
 
+
+        priv->cut_message = gtk_label_new ("...");
+        gtk_misc_set_alignment (GTK_MISC (priv->cut_message),
+                                0.5f,
+                                0.0f);
+        hildon_helper_set_logical_font (priv->cut_message, "SmallSystemFont");
+        gtk_widget_set_name (priv->cut_message, "hildon-shadow-label");
+        GTK_WIDGET_SET_FLAGS (priv->cut_message, GTK_NO_SHOW_ALL);
+
         hbox = gtk_hbox_new (FALSE, 0);
         gtk_box_pack_start (GTK_BOX (hbox), priv->unread, FALSE, FALSE, 0);
         gtk_box_pack_start (GTK_BOX (hbox), priv->icon, FALSE, FALSE, 0);
         gtk_box_pack_start (GTK_BOX (hbox), priv->sender, TRUE, TRUE, 0);
 
+        footer = gtk_hbox_new (FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (footer), priv->cut_message, TRUE, TRUE, 0);
+        gtk_box_pack_end (GTK_BOX (footer), priv->received, FALSE, FALSE, 0);
+
         vbox = gtk_vbox_new (FALSE, 0);
         gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
         gtk_box_pack_start (GTK_BOX (vbox), priv->empty, TRUE, TRUE, 0);
-        gtk_box_pack_end (GTK_BOX (vbox), priv->received, FALSE, FALSE, 0);
+        gtk_box_pack_end (GTK_BOX (vbox), footer, FALSE, FALSE, 0);
 
         align = gtk_alignment_new (0.5f, 0.0f, 1.0f, 1.0f);
         gtk_alignment_set_padding (GTK_ALIGNMENT (align),
@@ -771,14 +839,27 @@ el_home_applet_init (ELHomeApplet *self)
         gtk_container_add (GTK_CONTAINER (event_box), align);
         gtk_container_add (GTK_CONTAINER (self), event_box);
 
-        g_signal_connect (event_box, "button-press-event",
-                G_CALLBACK (button_press_event_cb), self);
-        g_signal_connect (event_box, "button-release-event",
-                G_CALLBACK (button_release_event_cb), self);
-        g_signal_connect (event_box, "leave-notify-event",
-                G_CALLBACK (leave_notify_event_cb), self);
+        g_signal_connect (event_box,
+                          "button-press-event",
+                          G_CALLBACK (button_press_event_cb),
+                          self);
+        g_signal_connect (event_box,
+                          "button-release-event",
+                          G_CALLBACK (button_release_event_cb),
+                          self);
+        g_signal_connect (event_box,
+                          "leave-notify-event",
+                          G_CALLBACK (leave_notify_event_cb),
+                          self);
 
-        g_signal_connect (event_box, "style-set", G_CALLBACK (style_set_cb), self);
+        g_signal_connect (event_box,
+                          "style-set",
+                          G_CALLBACK (style_set_cb),
+                          self);
+        g_signal_connect (self,
+                          "notify::is-on-current-desktop",
+                          G_CALLBACK (notify_on_current_desktop),
+                          self);
 
         gtk_widget_show_all (GTK_WIDGET (event_box));