1 <!-- Copyleft 2004 - see COPYING for details [LGPL] -->
5 Author: Charles Goodwin
7 See ibex.theme.selectable for documentation
10 1..n selection model with rolling selection
15 var groups = {}; // the groups of selectables
17 static.toGroup = function(v, oldg, g) {
19 // no group given, create group
20 if (3 > arguments.length) {
21 g = { members : (ibex..ibex.util.vector..newVector(v)),
22 selected : null, selection : [] };
27 else if (g and groups[g] != g) {
28 ibex.log.warn("Invalid group passed to toGroup: " + g + " " + groups[g]);
33 if (oldg and g != oldg) {
34 oldg.members.remove(v);
36 // clean up group info
37 if (oldg.selection[v]) v.selected = false;
39 // clean up groups list
40 if (!oldg.members.length) groups[oldg] = null;
45 if (g != oldg) g.members.push(v);
51 // end of static content
55 thisbox.mixed; // mixed status
56 thisbox.nextselect; // next group member to select
57 thisbox.prevselect; // previous group member to select
58 thisbox.selected; // selection status
60 var groupref; // internal reference to group
63 thisbox.group ++= function() {
64 // if no group, get one
65 if (!groupref) groupref = static.toGroup(thisbox);
70 thisbox.group ++= function(v) {
72 groupref = static.toGroup(thisbox, groupref, v);
76 thisbox.selected ++= function() {
77 if (mixed) return true;
81 // selected write trap
82 thisbox.selected ++= function(v) {
85 if (groupref.selected != thisbox) {
86 if (groupref.selected) groupref.selected.selected = false;
87 groupref.selected = thisbox;
90 else if (groupref.selected == thisbox) groupref.selected = null;
94 // find the next selectable member
95 thisbox.nextselect ++= function() {
98 ns = groupref.members.after(ns);
99 if (!ns) ns = groupref.members.first;
100 } while (!ns.enabled and ns != thisbox);
102 return ns.enabled ? ns : null;
105 // find the previous selectable member
106 thisbox.prevselect ++= function() {
109 ps = groupref.members.before(ps);
110 if (!ps) ps = groupref.members.last;
111 } while (!ps.enabled and ps != thisbox);
113 return ps.enabled ? ps : null;
116 // integration with clickable
117 action ++= function(v) { selected = true; }
119 // integration with clickable and focusable
120 focusable ++= function() { return cascade and (primed or selected); }
122 // integration with focusable
123 nextfocus ++= function() {
125 while (nf.group == groupref and nf != thisbox) nf = cascade;
129 // integration with focusable
130 prevfocus ++= function() {
132 while (pf.group == groupref and pf != thisbox) pf = cascade;