navmanager.lzx
<library>
<node name="navmanager">
<attribute name="views" value="{}
"/>
<attribute name="focused" value="null
"/>
<attribute name="focustrap" value="null
"/>
<method name="add" args="v">
var uid = v.getUID();
this.views[uid] = v;
</method>
<method name="distance" args="dx, dy">
return Math.sqrt((dx*dx) + (dy*dy));
</method>
<method name="angle" args="dx, dy">
return (Math.atan2(dy, dx) / Math.PI) + 1;
</method>
<method name="focus" args="v,ani">
if (v == this.focused || v == null) return;
//if (typeof v.id != 'undefined' && v.id == "fullview" && this.focused instanceof taglink) return;
// Sets the cursor without animation.
if(v && ani == false){
canvas.highlight.show(v, 0);
}
this.setAttribute('focused', v);
if (v && v['onfocused'] ){
v.onfocused.sendEvent();
}
</method>
<handler name="onwidth" reference="canvas" method="refocus"/>
<handler name="onheight" reference="canvas" method="refocus"/>
<method name="refocus" args="v">
if (this.focused) this.setAttribute('focused', this.focused);
</method>
<handler name="onkeyup" reference="lz.Keys" args="k">
if (this.focused && this.focused['handlekeyup']) {
var skip = this.focused.handlekeyup(k);
if (skip) return;
}
</handler>
<handler name="onkeydown" reference="lz.Keys" args="k">
var skip;
// let the canvas take first crack at processing the key press
if ( canvas['handlekeydown'] ) {
skip = canvas.handlekeydown( k );
if ( skip ) return;
}
var show;
if (this.focused) {
// now let the focused view process the key press
if ( this.focused['handlekeydown'] ) {
skip = this.focused.handlekeydown( k );
if (skip) return;
}
if (k == 37 && this.focused['findprev']) {
show = this.focused.findprev();
} else if (k == 39 && this.focused['findnext']) {
show = this.focused.findnext();
}
}
if (show) {
this.focus(show, true);
} else {
this.move(k);
}
</handler>
<method name="move" args="k">
var up,down,left,right;
switch(k) {
case 38:
up = true;
targetangle = .5;
break;
case 40:
down = true;
var targetangle = 1.5;
break;
case 37:
left = true;
targetangle = 0;
break;
case 39:
right = true;
targetangle = 1;
break;
default:
return;
}
var closest = null;
var f = this.focused;
var fx = f.width * .5;
var fy = f.height * .5;
if (f) {
while (f != canvas) {
fx += f.x; //INLINE getAttributeRelative('x', canvas);
fy += f.y; //INLINE getAttributeRelative('y', canvas);
f = f.immediateparent;
}
}
var maxdistance = this.distance(canvas.width, canvas.height);
var mindistance = Infinity;
for (var uid in this.views) {
var v = this.views[uid]
if (v == this.focused) continue;
if (v.focusable != true) continue;
// all parents are visible
var vis = true;
// always valid if there is no focustrap
var valid = this.focustrap == null;
var f = v;
var x = f.width * .5;
var y = f.height * .5;
while (f != canvas) {
if (! f.visible) {
vis = false;
break;
}
if (this.focustrap && this.focustrap == f) {
// if there is a focustrap and it's a parent, validate
valid = true;
}
x += f.x; //INLINE getAttributeRelative('x', canvas);
y += f.y; //INLINE getAttributeRelative('y', canvas);
f = f.immediateparent;
}
if (! vis) continue;
if (! valid) continue;
if (up && y >= fy) continue;
if (down && fy >= y) continue;
if (left && x >= fx) continue;
if (right && fx >= x) continue;
// find closest
var dx = x - fx;
var dy = y - fy;
var dist = Math.sqrt((dx*dx) + (dy*dy)) / maxdistance; // INLINE this.distance(dx, dy);
var angle = (Math.atan2(dy, dx) / Math.PI) + 1; // INLINE this.angle(dx, dy);
var angledelta = Math.abs(targetangle - angle);
if (angledelta > 1) angledelta = 2 - angledelta;
var weighted = ((dist + (angledelta * .5)) * .5);
//v.setAttribute('opacity', 1 - (weighted * 5));
if (weighted < mindistance) {
mindistance = weighted;
closest = v;
}
}
if (closest) this.focus(closest, true);
</method>
</node>
</library>
Cross References
Named Instances