From 0373ef13952db1b55f37578994da69f92326bf10 Mon Sep 17 00:00:00 2001 From: Enrico Zini Date: Mon, 14 Dec 2009 17:34:39 +0000 Subject: [PATCH] Show prefixes on the right --- gtkfisheyelist/gtkfisheyelistview.vala | 76 ++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/gtkfisheyelist/gtkfisheyelistview.vala b/gtkfisheyelist/gtkfisheyelistview.vala index af2673f..dc49c73 100644 --- a/gtkfisheyelist/gtkfisheyelistview.vala +++ b/gtkfisheyelist/gtkfisheyelistview.vala @@ -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 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(); 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 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 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() -- 2.39.5