var softkeysClass = { new : func (device, node, role) { var m = { parents: [ softkeysClass ] }; m.node = node; m.device = device; m.role = role; m.path = []; return m; }, clean : func { # deletes unsed bindings foreach (var b; keys(me.bindings)) if (b != me.role) delete(me.bindings, b); }, SoftKey : func (n, a) { # released key not yet managed if (a == 1) return; var key = me.device.display.screenElements[sprintf("SoftKey%02i-text",n)].get('text'); if (key == '' or key == nil) return; var path = keyMap[me.role]; foreach(var p; me.path) { if (contains(path, p)) path = path[p]; else break; } var bindings = me.bindings[me.role]; foreach(var p; me.path) { if (contains(bindings, p)) bindings = bindings[p]; else break; } if (contains(path, key)) { append(me.path, key); if (contains(bindings, key)) if (contains(bindings[key], 'hook')) call(bindings[key].hook, [], me); me.device.display.updateSoftKeys(); } elsif (contains(bindings, key)) { call(bindings[key], [], me); } elsif (key == 'BACK') { pop(me.path); me.device.display.updateSoftKeys(); } else { var list_path = ''; foreach(var p; me.path) list_path ~= p ~ '/'; print(me.device.role ~ ':' ~ list_path ~ key ~ ' : not yet implemented'); } }, bindings : { PFD : { INSET: { OFF: func { pop(me.path); me.device.display.updateSoftKeys(); }, }, PFD: { 'STD BARO': func { pop(me.path); me.device.display.updateSoftKeys(); }, 'AOA/WIND' : { WIND : { OPTN1 : func { me.device.display._winddata_optn = 1; me.device.display.screenElements['WindData'].show(); me.device.display.screenElements['WindData-OPTN1'].show(); me.device.display.screenElements['WindData-OPTN1-HDG'].show(); me.device.display.screenElements['WindData-OPTN2'].hide(); me.device.display.updateWindData(); }, OPTN2 : func { me.device.display._winddata_optn = 2; me.device.display.screenElements['WindData'].show(); me.device.display.screenElements['WindData-OPTN1'].hide(); me.device.display.screenElements['WindData-OPTN2'].show(); me.device.display.screenElements['WindData-OPTN2-symbol'].show(); me.device.display.screenElements['WindData-OPTN2-headwind'].show(); me.device.display.screenElements['WindData-OPTN2-crosswind'].show(); me.device.display.updateWindData(); }, OFF : func { me.device.display._winddata_optn = 0; me.device.display.screenElements['WindData'].hide(); me.device.display.screenElements['WindData-OPTN1'].hide(); me.device.display.screenElements['WindData-OPTN2'].hide(); }, }, }, BRG1 : func (brg = 1){ var source = 'brg' ~ brg ~ '-source'; var list = ['NAV' ~ brg, 'GPS', 'ADF', 'OFF']; var index = std.Vector .new(list) .index(radios.getNode(source).getValue()); var next = (index == size(list) -1) ? 0 : index + 1; radios.getNode(source).setValue(list[next]); }, BRG2 : func { call(me.bindings.PFD.PFD.BRG1, [ 2 ], me); }, }, XPDR: { STBY : func { me.bindings.PFD.XPDR.inactivity.restart(45); setprop('/instrumentation/transponder/ident', 0); setprop('/instrumentation/transponder/knob-mode', 1); setprop('/instrumentation/zkv1000/radio/xpdr-mode', 'STBY'); me.device.display.updateXPDR(); }, ON : func { me.bindings.PFD.XPDR.inactivity.restart(45); setprop('/instrumentation/transponder/ident', 1); setprop('/instrumentation/transponder/knob-mode', 4); setprop('/instrumentation/zkv1000/radio/xpdr-mode', 'ON'); me.device.display.updateXPDR(); }, ALT : func { me.bindings.PFD.XPDR.inactivity.restart(45); setprop('/instrumentation/transponder/ident', 1); setprop('/instrumentation/transponder/knob-mode', 5); setprop('/instrumentation/zkv1000/radio/xpdr-mode', 'ALT'); me.device.display.updateXPDR(); }, VFR : func { me.bindings.PFD.XPDR.inactivity.restart(45); setprop('/instrumentation/transponder/id-code', '1200'); me.device.display.updateXPDR(); }, IDENT : func { me.bindings.PFD.XPDR.inactivity.restart(45); call(me.bindings.PFD.IDENT, [], me); }, CODE : { '0' : func (n = 0) { me.bindings.PFD.XPDR.inactivity.restart(45); var tuning = radios.getNode('xpdr-tuning-digit'); var d = tuning.getValue(); setprop('/instrumentation/transponder/inputs/digit[' ~ d ~ ']', n); d += (d > 0) ? -1 : 3; tuning.setValue(d); me.device.display.updateXPDR(); }, '1' : func { call(me.bindings.PFD.XPDR.CODE['0'], [ 1 ], me); }, '2' : func { call(me.bindings.PFD.XPDR.CODE['0'], [ 2 ], me); }, '3' : func { call(me.bindings.PFD.XPDR.CODE['0'], [ 3 ], me); }, '4' : func { call(me.bindings.PFD.XPDR.CODE['0'], [ 4 ], me); }, '5' : func { call(me.bindings.PFD.XPDR.CODE['0'], [ 5 ], me); }, '6' : func { call(me.bindings.PFD.XPDR.CODE['0'], [ 6 ], me); }, '7' : func { call(me.bindings.PFD.XPDR.CODE['0'], [ 7 ], me); }, IDENT: func { me.bindings.PFD.XPDR.inactivity.restart(45); call(me.bindings.PFD.IDENT, [], me); }, BKSP: func { me.bindings.PFD.XPDR.inactivity.restart(45); var tuning = radios.getNode('xpdr-tuning-digit'); var d = tuning.getValue(); d += (d < 3) ? 1 : -3; tuning.setValue(d); me.device.display.updateXPDR(); }, BACK : func (inactive = 0) { var code = sprintf('%i', getprop('/instrumentation/zkv1000/radios/xpdr-backup-code')); for (var i = 0; i < 4; i += 1) setprop('/instrumentation/transponder/inputs/digit[' ~ (3 - i) ~ ']', substr(code, i, 1)); pop(me.path); call(me.bindings.PFD.XPDR.CODE.exit, inactive ? [[]] : [me.path], me); }, exit : func (p) { if (contains(me.bindings.PFD.XPDR, 'inactivity')) # does not exists if IDENT pressed from top-level me.bindings.PFD.XPDR.inactivity.stop(); radios.removeChild('xpdr-tuning-digit', 0); radios.removeChild('xpdr-backup-code', 0); me.path = p; me.device.display.updateXPDR(); me.device.display.updateSoftKeys(); }, hook : func { me.bindings.PFD.XPDR.inactivity.restart(45); var tuning = getprop('/instrument/zkv1000/radios/xpdr-tuning-digit'); if (tuning == nil) { radios.getNode('xpdr-tuning-digit', 1).setValue(3); radios.getNode('xpdr-backup-code', 1).setValue(getprop('/instrumentation/transponder/id-code')); me.device.display.updateXPDR(); } }, }, hook : func { me.bindings.PFD.XPDR.inactivity = maketimer(45, func call(me.bindings.PFD.XPDR.CODE.BACK, [1], me)); me.bindings.PFD.XPDR.inactivity.singleShot = 1; me.bindings.PFD.XPDR.inactivity.start(); }, }, IDENT : func { if (getprop('/instrumentation/zkv1000/radio/xpdr-mode') == 'STBY') return; setprop('/instrumentation/transponder/ident', 1); me.bindings.PFD.XPDR.ident = maketimer(18, func { setprop('/instrumentation/transponder/ident', 0); me.device.display.updateXPDR(); }); me.bindings.PFD.XPDR.ident.singleShot = 1; me.bindings.PFD.XPDR.ident.start(); call(me.bindings.PFD.XPDR.CODE.exit, [[]], me); }, CDI : func { var list = ['OFF']; if (getprop('/instrumentation/gps/route-distance-nm') != nil) append(list, 'GPS'); if (getprop('/instrumentation/nav/in-range') != nil) append(list, 'NAV1'); if (getprop('/instrumentation/nav[1]/in-range') != nil) append(list, 'NAV2'); var index = std.Vector .new(list) .index(cdi.getNode('source').getValue()); var next = (index == size(list) -1) ? 0 : index + 1; cdi.getNode('source').setValue(list[next]); CDIfromSOURCE(list[next]); me.device.display.updateCDI(); }, }, MFD : { ENGINE: { FUEL: { UNDO: func { pop(me.path); me.device.display.updateSoftKeys(); }, ENTER: func { pop(me.path); me.device.display.updateSoftKeys(); }, }, ENGINE: func { me.path = []; me.device.display.updateSoftKeys(); }, }, CHKLIST : { EXIT: func { me.path = []; me.device.display.updateSoftKeys(); }, }, }, }, };