[Xfce4-commits] <postler:master> Message list improvements, implement CellRendererConvo

Christian Dywan noreply at xfce.org
Wed Jul 6 21:12:01 CEST 2011


Updating branch refs/heads/master
         to 7ed2f88d54b62d74dad68e0a0e8c75ca98ca0de1 (commit)
       from b8a9cb8a1c656f2da0effb7cc7c131efa4e853c6 (commit)

commit 7ed2f88d54b62d74dad68e0a0e8c75ca98ca0de1
Author: Lucas Baudin <xapantu at gmail.com>
Date:   Wed Jul 6 15:55:48 2011 +0200

    Message list improvements, implement CellRendererConvo
    
    Fixes: https://bugs.launchpad.net/postler/+bug/806391

 postler/postler-cellrendererconvo.vala |  280 ++++++++++++++++++++++++++++++++
 postler/postler-messages.vala          |   41 ++----
 2 files changed, 291 insertions(+), 30 deletions(-)

diff --git a/postler/postler-cellrendererconvo.vala b/postler/postler-cellrendererconvo.vala
new file mode 100644
index 0000000..e636f26
--- /dev/null
+++ b/postler/postler-cellrendererconvo.vala
@@ -0,0 +1,280 @@
+/*
+ Copyright (C) 2011 Lucas Baudin <xapantu at gmail.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ See the file COPYING for the full license text.
+*/
+
+#if !HAVE_GTK3
+public struct Gdk.RGBA {
+    double red;
+    double green;
+    double blue;
+    double alpha;
+}
+namespace Gdk {
+    static void cairo_set_source_rgba (Cairo.Context cr, Gdk.RGBA color) {
+        cr.set_source_rgba (color.red, color.green, color.blue, color.alpha);
+    }
+}
+#endif
+
+public class Postler.CellRendererConvo : Gtk.CellRenderer {
+
+    public string subject { set; get; }
+    public string date { set; get; }
+    public string sender { set; get; }
+    public string text { set; get; }
+    public int unread { set; get; }
+    public bool message_unread = false;
+    public bool flagged = false;
+
+    double sender_height = 0.0;
+    double subject_height = 0.0;
+
+    public CellRendererConvo () {
+    }
+
+    /**
+     * Draw a rounded rectangle.
+     *
+     * This function only draws the shape, it doesn't fill or stroke it. It is
+     * a copy paste from the Cairo website.
+     *
+     * @param cr a valid Cairo context
+     * @param x x coord
+     * @param y y coord
+     * @param w the width of the rounded rectangle
+     * @param h the height of the rounded rectangle
+     **/
+    static void rounded (Cairo.Context cr, double x, double y, double w, double h) {
+        double r = 5;
+        cr.move_to (x + r, y);                                     // Move to A
+        cr.line_to (x + w - r, y);                                 // Straight line to B
+        cr.curve_to (x + w, y, x + w, y, x + w, y + r);            // Curve to C, Control points are both at Q
+        cr.line_to (x + w, y + h - r);                             // Move to D
+        cr.curve_to (x + w, y + h, x + w, y + h, x + w - r,y + h); // Curve to E
+        cr.line_to (x + r, y + h);                                 // Line to F
+        cr.curve_to (x, y + h, x, y + h, x, y + h - r);            // Curve to G
+        cr.line_to (x, y + r);                                     // Line to H
+        cr.curve_to (x, y, x, y, x + r, y);                        // Curve to A   double a = x;
+        cr.close_path ();
+    }
+
+    /**
+     * Get the width of the layout, in pixel.
+     *
+     * @param layout a valid pango layout
+     * @return the width of the layout.
+     **/
+    static double get_layout_width (Pango.Layout layout) {
+        Pango.Rectangle rect = Pango.Rectangle ();
+        layout.get_extents (out rect, null);
+        return Pango.units_to_double (rect.width);
+    }
+
+    /**
+     * Get the height of the layout, in pixel.
+     *
+     * @param layout a valid pango layout
+     * @return the height of the layout.
+     **/
+    static double get_layout_height (Pango.Layout layout) {
+        Pango.Rectangle rect = Pango.Rectangle();
+        layout.get_extents(out rect, null);
+        return Pango.units_to_double(rect.height);
+    }
+
+    /**
+     * Function called by gtk to determine the size request of the cell.
+     **/
+    public override void get_size (Gtk.Widget widget, Gdk.Rectangle? cell_area,
+                                   out int x_offset, out int y_offset,
+                                   out int width, out int height) {
+        height = (int)get_height (widget);
+        width = 250; /* Hardcoded, maybe it should be configurable */
+    }
+
+    /**
+     * Utility function to get the system link color, which is a Gdk.Color,
+     * we convert it to Gdk.RGBA to use it easily with cairo.
+     *
+     * @param style a valid StyleContext, we'll extract the Gdk.Color of the
+     * link from it.
+     *
+     * @return a Gdk.RGBA, which contains the link color
+     **/
+#if HAVE_GTK3
+    static Gdk.RGBA get_link_color (Gtk.StyleContext style) {
+#else
+    static Gdk.RGBA get_link_color (Gtk.Style style) {
+#endif
+        Gdk.Color? link_color_ = Gdk.Color();
+#if HAVE_GTK3
+        Value g_value = Value (typeof (Gdk.Color));
+        style.get_style_property ("link-color", g_value);
+        link_color_ = (Gdk.Color?)g_value.get_boxed ();
+#else
+        style.lookup_color ("link_color", out link_color_);
+#endif
+        Gdk.RGBA link_color = gdk_color_to_rgba (link_color_);
+        return link_color;
+    }
+
+    static Gdk.RGBA gdk_color_to_rgba (Gdk.Color color)
+    {
+        Gdk.RGBA link_color = Gdk.RGBA ();
+        link_color.red = ((double)color.red) / 0xFFFF;
+        link_color.green = ((double)color.green) / 0xFFFF;
+        link_color.blue = ((double)color.blue) / 0xFFFF;
+        link_color.alpha = 1.0;
+        return link_color;
+    }
+
+    /**
+     * Function called by gtk to draw the cell content.
+     **/
+#if HAVE_GTK3
+    public override void render (Cairo.Context cr, Gtk.Widget widget,
+                                 Gdk.Rectangle background_area, Gdk.Rectangle area,
+                                 Gtk.CellRendererState flags) {
+#else
+    public override void render (Gdk.Window draw, Gtk.Widget widget,
+                                 Gdk.Rectangle background_area, Gdk.Rectangle area,
+                                 Gdk.Rectangle expose_area, Gtk.CellRendererState flags) {
+#endif
+        Pango.Layout? layout = null;
+#if HAVE_GTK3
+        Gtk.StyleContext style = widget.get_style_context();
+#else
+        Gtk.Style style = widget.get_style();
+#endif
+        Gdk.RGBA link_color = get_link_color(style);
+#if HAVE_GTK3
+        Gdk.RGBA color_normal = style.get_color((flags & Gtk.CellRendererState.FOCUSED) > 0 ? Gtk.StateFlags.SELECTED : Gtk.StateFlags.NORMAL);
+        Gdk.RGBA color_insensitive = style.get_color(Gtk.StateFlags.INSENSITIVE);
+#else
+        Gdk.RGBA color_normal = gdk_color_to_rgba(style.fg[(flags & Gtk.CellRendererState.FOCUSED) > 0 ? Gtk.StateType.SELECTED : Gtk.StateType.NORMAL]);
+        Gdk.RGBA color_insensitive = gdk_color_to_rgba(style.fg[Gtk.StateType.INSENSITIVE]);
+
+        Cairo.Context cr = Gdk.cairo_create(draw);
+#endif
+
+        /* Compute font size */
+        Pango.FontDescription font_medium = widget.get_pango_context ().get_font_description ();
+        Pango.FontDescription old_desc = font_medium;
+        font_medium.set_size(Pango.units_from_double (Pango.units_to_double (font_medium.get_size()) - 2));
+
+        Pango.FontDescription font_small = widget.get_pango_context().get_font_description ();
+        font_small.set_size(Pango.units_from_double (Pango.units_to_double (old_desc.get_size ()) - 3));
+
+        /* Important */
+        if (flagged) {
+            color_normal.red += 0.5;
+            color_normal.green -= 0.2;
+            color_normal.blue -= 0.2;
+            color_insensitive = color_normal;
+            color_insensitive.alpha -= 0.4;
+        }
+
+        /* Unread */
+        if (message_unread) {
+            color_normal.blue += 0.5;
+            color_normal.green -= 0.2;
+            color_normal.red -= 0.2;
+            color_insensitive = color_normal;
+            color_insensitive.alpha -= 0.4;
+        }
+
+        /* Show date */
+        Gdk.cairo_set_source_rgba (cr,
+            (flags & Gtk.CellRendererState.FOCUSED) > 0 ? color_normal  : link_color);
+        layout = widget.create_pango_layout (date);
+        layout.set_font_description (font_small);
+        double date_width = get_layout_width (layout);
+        cr.move_to (area.x + area.width - get_layout_width (layout) - 5, area.y);
+        Pango.cairo_show_layout (cr, layout);
+
+        /* Show unread count */
+        double unread_width = 0.0;
+        if (unread > 0) { /* Don't show [0] */
+            layout = widget.create_pango_layout (unread.to_string ());
+            double margin = 5;
+            double rect_width = get_layout_width (layout) + margin * 2;
+            double rect_height = get_layout_height (layout) + margin * 2;
+            unread_width = rect_width + 5;
+            /* Background */
+            rounded (cr, area.x + area.width - rect_width - 5,
+                         area.y + area.height / 2 - rect_height / 2 + margin,
+                         rect_width, rect_height);
+            Gdk.cairo_set_source_rgba (cr, link_color);
+            cr.fill ();
+            /* Real text */
+            cr.move_to (area.x + area.width - get_layout_width (layout) - margin - 5,
+                        area.y + area.height / 2 - get_layout_height (layout) / 2);
+            Gdk.cairo_set_source_rgba (cr, {1, 1, 1, 1});
+            Pango.cairo_show_layout (cr, layout);
+        }
+
+        /* Sender */
+        layout = widget.create_pango_layout (sender);
+        layout.set_ellipsize (Pango.EllipsizeMode.END);
+        layout.set_width (Pango.units_from_double (area.width - date_width - 5));
+        cr.move_to (area.x, area.y);
+        Gdk.cairo_set_source_rgba (cr, color_normal);
+        Pango.cairo_show_layout (cr, layout);
+        double y = sender_height;
+
+        /* Subject */
+        layout = widget.create_pango_layout (subject);
+        layout.set_font_description (font_medium);
+        layout.set_ellipsize (Pango.EllipsizeMode.END);
+        layout.set_width (Pango.units_from_double (area.width - unread_width));
+        cr.move_to (area.x, area.y + y);
+        Gdk.cairo_set_source_rgba (cr, color_normal);
+        Pango.cairo_show_layout (cr, layout);
+
+        y += subject_height;
+
+        /* The beginning of the message */
+        layout = widget.create_pango_layout (text);
+        layout.set_ellipsize (Pango.EllipsizeMode.END);
+        layout.set_width (Pango.units_from_double (area.width - unread_width));
+        cr.move_to (area.x, area.y + y);
+        Gdk.cairo_set_source_rgba (cr, color_insensitive);
+        layout.set_font_description (font_medium);
+        Pango.cairo_show_layout (cr, layout);
+
+        layout.set_font_description (old_desc); /* Restore the old font, it could
+                                                * cause some strange behavior */
+    }
+
+    double get_height (Gtk.Widget widget) {
+        /* Why "|" ? Because it is the highest char I found… */
+        Pango.Layout layout = widget.create_pango_layout ("|");
+        double y = get_layout_height (layout) + 5;
+        sender_height = y;
+
+        layout = widget.create_pango_layout ("|");
+        Pango.FontDescription font_medium = widget.get_pango_context ().get_font_description ();
+        Pango.FontDescription old_desc = font_medium;
+        font_medium.set_size (Pango.units_from_double (
+                              Pango.units_to_double (font_medium.get_size ()) - 2));
+        layout.set_font_description (font_medium);
+
+        y += get_layout_height (layout) + 5;
+        subject_height = get_layout_height (layout) + 5;
+
+        layout = widget.create_pango_layout ("|");
+        layout.set_font_description (font_medium);
+        y += get_layout_height (layout) + 5;
+        layout.set_font_description (old_desc);
+
+        return y;
+    }
+}
+
diff --git a/postler/postler-messages.vala b/postler/postler-messages.vala
index 079c0c0..7cf16f2 100644
--- a/postler/postler-messages.vala
+++ b/postler/postler-messages.vala
@@ -128,41 +128,24 @@ public class Postler.Messages : Gtk.TreeView {
         Gtk.TreeModel model, Gtk.TreeIter iter) {
 
         Message message;
-        var renderer = cell as Gtk.CellRendererText;
+        var renderer = cell as Postler.CellRendererConvo;
 
         model.get (iter, Columns.MESSAGE, out message);
 
-        if (message.uri == "error:") {
-            renderer.markup = message.subject;
-            renderer.xpad = renderer.ypad = 8;
-            renderer.xalign = renderer.yalign = 0.5f;
-            return;
-        }
-
-        renderer.xpad = renderer.ypad = 0;
-        renderer.xalign = renderer.yalign = 0.0f;
-
         if (message.uri == null) {
             new Client ().get_message.begin (message, MessageFlags.NONE,
                 new Gtk.TreeRowReference (model, model.get_path (iter)));
-            renderer.markup = "...";
+            renderer.subject = "...";
             return;
         }
 
-        string subject = escape_text (message.subject ?? _("No subject"));
-        string date = Postler.Content.format_date (message.date);
-        long size = date.length;
-        for (int j = 0; j < 20 - size; j++)
-            date = date + " ";
-
-        string from = escape_text (Postler.Contact.name_from_string (message.sender));
-        int weight = message.unread ? Pango.Weight.BOLD : Pango.Weight.NORMAL;
-
-        renderer.ellipsize = Pango.EllipsizeMode.MIDDLE;
-        renderer.markup = ("<span weight=\"%d\">%s</span>\n" +
-                           "<small><tt>%s      </tt></small> %s <b>%s</b>").printf (
-            weight, from, date, subject,
-            message.replies > 1 ? message.replies.to_string () : "");
+        renderer.subject = escape_text (message.subject ?? _("No subject"));
+        renderer.date = Postler.Content.format_date (message.date);
+        renderer.sender = escape_text (Postler.Contact.name_from_string (message.sender));
+        renderer.unread = (int)message.replies;
+        renderer.message_unread = message.unread;
+        renderer.flagged = message.flagged;
+        renderer.text = message.excerpt + "…";
     }
 
     void renderer_flag_toggled (Gtk.CellRendererToggle renderer,
@@ -238,12 +221,10 @@ public class Postler.Messages : Gtk.TreeView {
         Gtk.cell_renderer_get_padding (renderer_flag, out xpad, null);
         column.set_fixed_width (cell_width + xpad * 4);
 
-        column = new Gtk.TreeViewColumn ();
+        var renderer_text = new Postler.CellRendererConvo ();
+        column = new Gtk.TreeViewColumn.with_attributes ("Messages", renderer_text, null);;
         column.set_sizing (Gtk.TreeViewColumnSizing.FIXED);
         column.set_title (_("Subject"));
-        var renderer_text = new Gtk.CellRendererText ();
-        renderer_text.set_fixed_height_from_font (2);
-        column.pack_start (renderer_text, true);
         column.set_cell_data_func (renderer_text, render_subject);
         insert_column (column, -1);
 



More information about the Xfce4-commits mailing list