2 <org.ibex.theme.win2k.focusable /> // HACK: should be in a better place
3 <ui:box align="topleft" fill="green" packed="false">
4 <ui:box id="content" rows="0" cols="1" shrink="true" align="topleft" fill="yellow" />
8 SizeChange ++= function(v) {
9 ibex.thread = function() { $content.maxwidth = thisbox.width; }
12 // TODO: align ++= function(a) { for (var i=0; $content.numchildren > i; i++) $content[i].align = a; }
15 var currentfocus = null; // HACK: for subfocus model
16 thisbox._KeyPressed ++= function(v) {
17 if (currentfocus) currentfocus.KeyPressed = v;
21 // creates an empty row, ready for insertion into $content
22 thisbox.row = function() {
25 //b.align = thisbox.align;
28 var packtrap = function(v) { pack($content.indexof(b)); }
29 b.SizeChange ++= packtrap;
31 // ------------------------------------------------------
32 // HACK: quick and dirty subfocusing for text
34 var block_prevfocus = function() {
35 // find prev focusable in current row
36 var index = b.indexof(trapee);
37 if (index > 0) return b[index - 1];
40 var r = $content.indexof(b);
41 if (r > 0 and $content[r - 1].numchildren > 0) return $content[r - 1][($content[r - 1].numchildren)];
43 var block_nextfocus = function() {
44 ibex.log.info("block_nextfocus: finding next focus");
45 // find next focusable in current row
46 var index = b.indexof(trapee);
47 if (b.numchildren - 1 > index) return b[index + 1];
50 var r = $content.indexof(b);
51 if ($content.numchildren - 1 > r and $content[r + 1].numchildren > 0) return $content[r + 1][0];
53 var block_curpos = function(v) {
55 var movefocus = trapee.parent.prevfocus; // usage of HACK mentioned below
57 trapee.parent.focused = false; movefocus.cur.pos = movefocus.text.length;
58 movefocus.focused = true; currentfocus = movefocus;
60 } else if (v > trapee.parent.text.length) {
61 ibex.log.info("stepped over right-hand block boundry");
62 var movefocus = trapee.parent.nextfocus;
64 ibex.log.info("changing focus");
65 trapee.parent.focused = false; movefocus.cur.pos = 0;
66 movefocus.focused = true; currentfocus = movefocus;
70 var block_press1 = function(c) {
71 if (currentfocus != trapee) {
72 if (currentfocus) currentfocus.focused = false;
73 trapee.focused = true;
74 currentfocus = trapee;
77 b.childadded ++= function(c) {
78 c.prevfocus ++= block_prevfocus;
79 c.nextfocus ++= block_nextfocus;
80 c.cur.pos ++= block_curpos;
81 c.Press1 ++= block_press1;
82 c.cur.parent = c; // HACK: need for block_curpos above
84 b.childremoved ++= function(c) {
85 c.prevfocus --= block_prevfocus;
86 c.nextfocus --= block_nextfocus;
87 c.cur.pos --= block_curpos;
88 c.Press1 --= block_press1;
90 // ------------------------------------------------------
95 // HACK: clean this up conceptually
96 childadded ++= function(newc) { if (thisbox.indexof(newc) >= 0) add(newc); }
98 // add a block of text to the flow element
99 thisbox.add = function(b) {
100 if (1 > $content.numchildren) $content[0] = row();
101 var r = $content[$content.numchildren -1];
103 // HACK: for subfocus model
104 if (currentfocus) b.focused = false;
105 else { b.focused = true; currentfocus = b; }
107 r[r.numchildren] = b;
110 // launch the packNow function in a background thread
111 var pack = function(ind) {
114 ibex.thread = packNow;
115 } else if (packing > ind) {
116 // background thread already queued, so just
117 // update location from which to start
122 // pack the contents of this flow starting at row matching value of packing
123 var packNow = function() {
127 // work through each row, packing them
128 ROW: for (; $content.numchildren > ind; ind++) {
129 ibex.log.debug("tag 2, ind="+ind);
130 var r = $content[ind];
132 // calculate excess width of row contents (negative to represent free space)
134 for (var i=0; r.numchildren > i; i++) w += r[i].width;
135 w -= $content.maxwidth;
138 ibex.log.debug("tag 3, w="+w+", nextr="+nextr+", $content.numchildren="+$content.numchildren);
140 if (0 > w and $content.numchildren > nextr) {
141 // attempt to pack contents from next row into current row
144 // find first non-empty following row
145 var n = $content[nextr];
146 ibex.log.debug("tag 4, n==null?"+(n==null));
147 while (n != null and 1 > n.numchildren and $content.numchildren > nextr) {
148 n.thisbox = null; n = $content[nextr];
150 ibex.log.debug("tag 5 n.numchildren="+(n==null?-1:n.numchildren));
151 if (n == null || 1 > n.numchildren) break ROW;
153 // move up excess blocks
154 while (w > n[0].width) {
155 ibex.log.debug("r["+r.numchildren+"] = n[0] (n.numchildren="+n.numchildren+")");
156 w -= n[0].width; r[r.numchildren] = n[0];
158 while (n.numchildren == 0) {
159 $content[nextr] = null;
161 if (nextr >= $content.numchildren) break ROW;
166 ibex.log.debug("tag 6");
168 // attempt to split up final block
169 if (n.numchildren > 0 and n[0].splitable) {
170 var splitb = n[0].split(w);
171 if (splitb) r[r.numchildren] = splitb;
175 // push row contents to next row
176 if (nextr == $content.numchildren) $content[$content.numchildren] = row();
178 // move off excess blocks
180 for (b = r[r.numchildren -1]; b != null and w > b.width; b = r[r.numchildren -1]) {
181 $content[nextr][0] = b;
185 if (b == null) continue ROW;
188 // attempt to split up final block
189 var newb = b.split(b.width - w);
192 r[r.numchildren] = newb;
193 $content[nextr][0] = b;
199 if (r.numchildren > 1) $content[nextr][0] = b;
200 else ibex.log.warn("box exceeds window limit"); // FIXME: how do we handle this?
202 ibex.log.debug("tag 10");
207 //ibex.log.debug(debugState());
211 var debugState = function() {
212 var str = "---- DEBUG $content child="+$content.numchildren
213 + "maxwidth="+$content.width+", width="+$content.width+", height="+$content.height+"\n";
214 for (var i=0; $content.numchildren > i; i++) {
215 str += "$content["+i+"].numchildren="+$content[i].numchildren + "\n";
216 for (var j=0; $content[i].numchildren > j; j++) {
217 str += "$content["+i+"]["+j+"] text="+$content[i][j].text
218 + " width="+$content[i][j].width+", height="+$content[i][j].height+"\n";