Show prefixes on the right
authorEnrico Zini <enrico@enricozini.org>
Mon, 14 Dec 2009 17:34:39 +0000 (17:34 +0000)
committerEnrico Zini <enrico@enricozini.org>
Mon, 14 Dec 2009 17:34:39 +0000 (17:34 +0000)
gtkfisheyelist/gtkfisheyelistview.vala

index af2673ff509f31f336194adc3807112cc604fdac..dc49c73d365319faf4ef6f94bb9edaea17da63a6 100644 (file)
@@ -26,6 +26,41 @@ protected struct FocusInfo
        int renderer;
 }
 
+protected class PrefixInfo
+{
+       public string prefix;
+       public size_t pfx_len;
+       public int pos;
+       public int layout_pos;
+
+       public PrefixInfo(string prefix, int pos)
+       {
+               this.prefix = prefix;
+               this.pfx_len = prefix.size();
+               this.pos = pos;
+               this.layout_pos = 0;
+       }
+
+       /**
+        * If s and prefix share a prefix, set prefix to the common prefix, and
+        * return true.
+        * Else, return false.
+        */
+       public bool refine(string s)
+       {
+               size_t len;
+               for (len = 0; prefix[len] != 0 && s[len] != 0 && s[len] == prefix[len]; ++len)
+                       ;
+               if (len == 0) return false;
+               if (len != pfx_len)
+               {
+                       prefix = prefix.substring(0, (int)len);
+                       pfx_len = len;
+               }
+               return true;
+       }
+}
+
 public class FisheyeListView : Gtk.DrawingArea
 {
        protected Gtk.TreeModel model;
@@ -42,6 +77,9 @@ public class FisheyeListView : Gtk.DrawingArea
        protected string[] label_cache;
        protected bool base_layout_needed;
 
+       // Prefix information
+       protected List<PrefixInfo> prefixes;
+
        protected int cur_el;
 
        // Layout information
@@ -85,6 +123,7 @@ public class FisheyeListView : Gtk.DrawingArea
                backing_store = null;
 
                label_cache = null;
+               prefixes = null;
 
                renderers = new Gtk.CellRendererText[steps];
                renderer_sizes = new int[steps];
@@ -235,6 +274,7 @@ public class FisheyeListView : Gtk.DrawingArea
        protected void base_layout()
        {
                // Rebuild label cache
+               prefixes = new List<PrefixInfo>();
                if (model == null)
                {
                        label_cache = new string[0];
@@ -250,14 +290,23 @@ public class FisheyeListView : Gtk.DrawingArea
                                label_cache = new string[count];
 
                                int i = 0;
+                               PrefixInfo pi = null;
                                do {
                                        string val;
                                        model.get(iter, _label_column, out val, -1);
                                        label_cache[i] = val;
+                                       if (pi == null || !pi.refine(val))
+                                       {
+                                               if (pi != null) prefixes.append(pi);
+                                               pi = new PrefixInfo(val, i);
+                                       }
                                        ++i;
                                } while (model.iter_next(ref iter));
+                               prefixes.append(pi);
                        }
                }
+               for (weak List<PrefixInfo> i = prefixes; i != null; i = i.next)
+                       i.data.layout_pos = i.data.pos * allocation.height / (label_cache.length+1);
 
                background = new Gdk.Pixmap(window, allocation.width, allocation.height, -1);
                backing_store = new Gdk.Pixmap(window, allocation.width, allocation.height, -1);
@@ -386,6 +435,7 @@ public class FisheyeListView : Gtk.DrawingArea
                                allocation.width/2, allocation.height-y-30, allocation.width/2, 10);
                }
 
+               // Draw tiny labels
                Gdk.Rectangle expose_area = Gdk.Rectangle();
                expose_area.x = expose_area.y = 0;
                expose_area.width = allocation.width;
@@ -429,6 +479,32 @@ public class FisheyeListView : Gtk.DrawingArea
                                                0);
                        }
                }
+
+               // Draw prefix labels
+               Pango.Layout layout = create_pango_layout(null);
+               Pango.Rectangle lr;
+               layout.get_extents(null, out lr);
+               int label_height = lr.height / Pango.SCALE;
+               layout.set_alignment(Pango.Alignment.RIGHT);
+               layout.set_width(allocation.width*Pango.SCALE/3);
+               layout.set_height(0);
+//stderr.printf("HEIGHT %d+%d = %d\n", lr.y, lr.height, lr.y + lr.height);
+               //layout.set_wrap(Pango.WrapMode.
+               layout.set_ellipsize(Pango.EllipsizeMode.END);
+
+               int last_covered = 0;
+
+               for (weak List<PrefixInfo> i = prefixes; i != null; i = i.next)
+               {
+stderr.printf("DRAW %s at %d lc %d\n", i.data.prefix, i.data.layout_pos, last_covered);
+                       if (i.data.layout_pos < last_covered)
+                       {
+                               i.data.layout_pos = last_covered;
+                       }
+                       layout.set_text(i.data.prefix, int.max(10, (int)i.data.pfx_len));
+                       Gtk.paint_layout(style, (Gdk.Window*)drawable, Gtk.StateType.NORMAL, true, null, this, null, allocation.width*2/3, i.data.layout_pos, layout);
+                       last_covered = i.data.layout_pos + label_height;
+               }
        }
 
        protected void draw()