protected Gtk.TreeModel model;
protected Gdk.Pixmap backing_store;
- private string[] list;
- protected int cur_el;
-
- protected int _distortion_factor;
- public int distortion_factor {
- get { return _distortion_factor; }
- set {
- _distortion_factor = value;
- focus_layout_needed = true;
- }
- }
-
-
// Pango layouts cached for speed
// TODO: If you create and keep a PangoLayout using this context, you
// must deal with changes to the context by calling
// "style-set" and "direction-changed" signals for the widget.
protected Pango.Layout[] pango_cache;
+ // Labels to show, extracted from the model
+ protected string[] label_cache;
+ protected bool build_label_cache_needed;
+
+ protected int cur_el;
+
// Layout information
protected int focus_first;
protected int focus_end;
_focus_size = value;
focus_starts = new int[value+1];
focus_layout_needed = true;
+ queue_draw();
+ }
+ }
+
+ protected int _distortion_factor;
+ public int distortion_factor {
+ get { return _distortion_factor; }
+ set {
+ _distortion_factor = value;
+ focus_layout_needed = true;
+ queue_draw();
}
}
model = null;
backing_store = null;
- list = new string[300];
- for (int i = 0; i < 300; ++i)
- list[i] = "Lorem Ipsum %d".printf(i);
+ label_cache = null;
+ build_label_cache_needed = true;
pango_cache = new Pango.Layout[30];
for (int i = 0; i < 30; ++i)
public void set_model (Gtk.TreeModel? model)
{
this.model = model;
+ build_label_cache_needed = true;
+ queue_draw();
}
/* Mouse button got pressed over widget */
public override bool button_press_event(Gdk.EventButton event)
{
- stderr.printf("Mouse pressed on %d %s\n", cur_el, list[cur_el]);
+ stderr.printf("Mouse pressed on %d %s\n", cur_el, label_cache[cur_el]);
return false;
}
/* Mouse button got released */
public override bool button_release_event(Gdk.EventButton event)
{
- stderr.printf("Mouse released on %d %s\n", cur_el, list[cur_el]);
+ stderr.printf("Mouse released on %d %s\n", cur_el, label_cache[cur_el]);
// ...
return false;
}
}
} else {
- cur_el = y * list.length / allocation.height;
+ cur_el = y * label_cache.length / allocation.height;
if (old_cur_el != cur_el)
focus_layout_needed = true;
}
protected int el_y(int idx)
{
// Undistorted Y
- int undy = idx * allocation.height / list.length;
+ int undy = idx * allocation.height / label_cache.length;
// Distorted position
int pos = fisheye(undy, focus_centre, distortion_factor, 0, allocation.height);
//stderr.printf("%d %f %f\n", idx, undy, pos);
return pos;
}
- protected void focus_layout()
+ protected void build_label_cache()
{
- // Anchor point
- focus_centre = cur_el*allocation.height/list.length;
+ if (model == null)
+ {
+ label_cache = new string[0];
+ } else {
+ Gtk.TreeIter iter;
+ if (!model.get_iter_first(out iter))
+ {
+ label_cache = new string[0];
+ }
+ else
+ {
+ int count = model.iter_n_children(null);
+ label_cache = new string[count];
+
+ int i = 0;
+ do {
+ string val;
+ model.get(iter, 0, out val, -1);
+ label_cache[i] = val;
+ ++i;
+ } while (model.iter_next(ref iter));
+ }
+ }
- focus_first = cur_el > focus_size/2 ? cur_el-focus_size/2 : 0;
- focus_end = focus_first + focus_size;
- if (focus_end >= list.length) focus_end = list.length;
+ build_label_cache_needed = false;
+ focus_layout_needed = true;
+ }
- // Compute starting positions for all items in focus
- for (int idx = focus_first; idx < focus_end; ++idx)
+ protected void focus_layout()
+ {
+ if (label_cache.length == 0)
{
- int posprev = idx == 0 ? 0 : el_y(idx-1);
- int pos = el_y(idx);
- int posnext = idx == list.length-1 ? 1 : el_y(idx+1);
- int y0 = (pos+posprev)/2;
- int y1 = (pos+posnext)/2;
-
- focus_starts[idx - focus_first] = y0;
- focus_starts[idx - focus_first + 1] = y1;
+ focus_centre = 0;
+ focus_first = 0;
+ focus_end = 0;
+ focus_starts[0] = 0;
+ } else {
+ // Anchor point
+ focus_centre = cur_el*allocation.height/label_cache.length;
+
+ focus_first = cur_el > focus_size/2 ? cur_el-focus_size/2 : 0;
+ focus_end = focus_first + focus_size;
+ if (focus_end >= label_cache.length) focus_end = label_cache.length;
+
+ // Compute starting positions for all items in focus
+ for (int idx = focus_first; idx < focus_end; ++idx)
+ {
+ int posprev = idx == 0 ? 0 : el_y(idx-1);
+ int pos = el_y(idx);
+ int posnext = idx == label_cache.length-1 ? 1 : el_y(idx+1);
+ int y0 = (pos+posprev)/2;
+ int y1 = (pos+posnext)/2;
+
+ focus_starts[idx - focus_first] = y0;
+ focus_starts[idx - focus_first + 1] = y1;
+ }
}
focus_layout_needed = false;
}
protected void draw(Gdk.Drawable drawable)
{
+ if (build_label_cache_needed)
+ build_label_cache();
if (focus_layout_needed)
focus_layout();
pc.set_font_description(fd);
pango_cache[size] = new Pango.Layout(pc);
}
- pango_cache[size].set_text(list[idx], -1);
+ pango_cache[size].set_text(label_cache[idx], -1);
var layout = pango_cache[size];
//stderr.printf("AZAZA %p\n", layout.get_attributes());
//var attrlist = layout.get_attributes().copy();
var list = new FisheyeList();
add(list);
+
+ var store = new Gtk.ListStore(1, typeof(string));
+ Gtk.TreeIter iter;
+ for (int i = 0; i < 300; ++i)
+ {
+ store.append(out iter);
+ store.set(iter, 0, "Antani %d".printf(i), -1);
+ }
+
+ list.set_model(store);
}
}