var softkeysClass = { new : func (device, node, role) { var m = { parents: [ softkeysClass ] }; m.node = node; m.device = device; m.role = role; m.path = []; return m; }, 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: { '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); }, 'STD BARO' : func { setprop('/instrumentation/altimeter/setting-inhg', 29.92); me.device.display.updateBARO(); pop(me.path); me.device.display.updateSoftKeys(); }, IN : func { me.device.display._baro_unit = 'inhg'; me.device.display.updateBARO(); }, HPA : func { me.device.display._baro_unit = 'hpa'; me.device.display.updateBARO(); }, }, XPDR: { STBY : func { setprop('/instrumentation/transponder/ident', 0); setprop('/instrumentation/transponder/knob-mode', 1); setprop('/instrumentation/zkv1000/radio/xpdr-mode', 'STBY'); me.device.display.updateXPDR(); }, ON : func { setprop('/instrumentation/transponder/ident', 1); setprop('/instrumentation/transponder/knob-mode', 4); setprop('/instrumentation/zkv1000/radio/xpdr-mode', 'ON'); me.device.display.updateXPDR(); }, ALT : func { setprop('/instrumentation/transponder/ident', 1); setprop('/instrumentation/transponder/knob-mode', 5); setprop('/instrumentation/zkv1000/radio/xpdr-mode', 'ALT'); me.device.display.updateXPDR(); }, VFR : func { setprop('/instrumentation/transponder/id-code', '1200'); me.device.display.updateXPDR(); }, IDENT : func { call(me.bindings.PFD.IDENT, [], me); }, CODE : { '0' : func (n = 0) { if (getprop('/instrumentation/zkv1000/radios/xpdr-tuning-fms-method')) return; me.device.display.timers2.softkeys_inactivity.stop(); me.bindings.PFD.XPDR.CODE.inactivity.restart(me.device.display.softkeys_inactivity_delay); # disable FMS knob entering method me.device.knobs.FmsInner = void; # When entering the code, the next softkey in sequence # must be pressed within 10 seconds, or the entry is cancelled # and restored to the previous code if (!contains(me.bindings.PFD.XPDR.CODE, 'on_change_inactivity')) { me.bindings.PFD.XPDR.CODE.on_change_inactivity = maketimer(10, func { setprop('/instrumentation/zkv1000/radios/xpdr-tuning-digit', 3); me.device.knobs.FmsInner = me.device.knobs.XPDRCodeSetDigits; me.device.knobs.FmsOuter = me.device.knobs.XPDRCodeNextDigits; call(me.bindings.PFD.XPDR.CODE.restore, [], me); }); me.bindings.PFD.XPDR.CODE.on_change_inactivity.singleShot = 1; me.bindings.PFD.XPDR.CODE.on_change_inactivity.start(); } else me.bindings.PFD.XPDR.CODE.on_change_inactivity.restart(10); var tuning = radios.getNode('xpdr-tuning-digit'); var d = tuning.getValue(); setprop('/instrumentation/transponder/inputs/digit[' ~ d ~ ']', n); if (d == 1) { if (!contains(me.bindings.PFD.XPDR.CODE, 'on_change_auto_validation')) me.bindings.PFD.XPDR.CODE.on_change_auto_validation = maketimer(5, func call(me.bindings.PFD.IDENT, [], me)); me.bindings.PFD.XPDR.CODE.on_change_auto_validation.singleShot = 1; me.bindings.PFD.XPDR.CODE.on_change_auto_validation.start(); } else { d -= 1; 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.CODE.inactivity.restart(me.device.display.softkeys_inactivity_delay); me.device.display.timers2.softkeys_inactivity.restart(me.device.display.softkeys_inactivity_delay); call(me.bindings.PFD.IDENT, [], me); }, BKSP: func { if (getprop('/instrumentation/zkv1000/radios/xpdr-tuning-fms-method')) return; if (contains(me.bindings.PFD.XPDR.CODE, 'on_change_inactivity')) me.bindings.PFD.XPDR.CODE.on_change_inactivity.restart(10); if (contains(me.bindings.PFD.XPDR.CODE, 'on_change_auto_validation')) me.bindings.PFD.XPDR.CODE.on_change_auto_validation.stop(); var tuning = radios.getNode('xpdr-tuning-digit'); var d = tuning.getValue(); if (d < 3) { d += 1; tuning.setValue(d); } me.device.display.updateXPDR(); }, BACK : func (inactive = 0) { call(me.bindings.PFD.XPDR.CODE.restore, [], me); pop(me.path); call(me.bindings.PFD.XPDR.CODE.exit, [me.path], me); }, restore : func { setprop('/instrumentation/transponder/id-code', sprintf('%s', getprop('/instrumentation/zkv1000/radios/xpdr-backup-code'))); me.device.display.updateXPDR(); }, exit : func (p) { if (contains(me.bindings.PFD.XPDR.CODE, 'inactivity')) # does not exists if IDENT pressed from top-level me.bindings.PFD.XPDR.CODE.inactivity.stop(); radios.removeChild('xpdr-tuning-digit', 0); radios.removeChild('xpdr-backup-code', 0); radios.removeChild('xpdr-tuning-fms-method', 0); me.path = p; me.device.display.updateXPDR(); me.device.display.updateSoftKeys(); me.device.knobs.FmsInner = void; me.device.knobs.FmsOuter = void; me.device.display.timers2.softkeys_inactivity.restart(me.device.display.softkeys_inactivity_delay); }, hook : func { # this level has its own timer as we may need to revert changes, and got different timers me.device.display.timers2.softkeys_inactivity.stop(); me.bindings.PFD.XPDR.CODE.inactivity = maketimer( me.device.display.softkeys_inactivity_delay, func call(me.bindings.PFD.XPDR.CODE.BACK, [], me)); me.bindings.PFD.XPDR.CODE.inactivity.singleShot = 1; me.bindings.PFD.XPDR.CODE.inactivity.start(); 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')); radios.getNode('xpdr-tuning-fms-method', 1).setValue(0); me.device.display.updateXPDR(); } me.device.knobs.FmsInner = me.device.knobs.XPDRCodeSetDigits; me.device.knobs.FmsOuter = me.device.knobs.XPDRCodeNextDigits; }, }, }, 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(); }, 'TMR/REF' : func { if (!contains(me.device.windows.state, 'TMR/REF')) { me.device.windows.draw( 'TMR/REF', {x: 720, y: 535, w: 300, l: 5, sep: 3}, [ # objects infos {text: 'REFERENCES', type: 'title'}, {type: 'separator'}, {text: 'TIMER', type: 'normal'}, {text: '00:00:00', type: 'selected|time', }, {text: '< UP >', type: 'editable', choices: ['< UP >', ''], callback: func}, {text: 'START?', type: 'editable|end-of-line|choices', choices: ['START?', 'RESET?', 'STOP?'], callback: func}, {type: 'separator'}, {text: 'Vx 20KT', type: 'normal', scrollgroup:0}, {text: '< ON >', type: 'editable|end-of-line', choices: ['< ON >', '< OFF >'], scrollgroup:0, callback: func}, {text: 'Vy 50KT', type: 'normal', scrollgroup:1}, {text: '< ON >', type: 'editable|end-of-line', choices: ['< ON >', '< OFF >'], scrollgroup:1, callback: func}, {text: 'Vr 70KT', type: 'normal', scrollgroup:2}, {text: '< ON >', type: 'editable|end-of-line', choices: ['< ON >', '< OFF >'], scrollgroup:2, callback: func}, {text: 'Vglide 100KT', type: 'normal', scrollgroup:3}, {text: '< ON >', type: 'editable|end-of-line', choices: ['< ON >', '< OFF >'], scrollgroup:3, callback: func}, {text: 'Vfoo bar baz', type: 'normal', scrollgroup:4}, {text: '< ON >', type: 'editable|end-of-line', choices: ['< ON >', '< OFF >'], scrollgroup:4, callback: func}, {type: 'separator'}, {text: 'MINIMUMS', type: 'normal'}, {text: ' BARO >', type: 'editable', choices: [' BARO >','< TST1 >','< TST2 '], callback: func}, {text: ' 1000FT', type: 'editable', format: '% 5iFT', factor: 100, callback: func}, ], { # scrolling info, see menu.nas lines : 3, columns : 2, } ); me.device.knobs.FmsInner = me.device.knobs.MenuSettings; me.device.knobs.FmsOuter = me.device.knobs.NavigateMenu; } else { me.device.knobs.FmsInner = func; me.device.knobs.FmsOuter = func; me.device.windows.del(); } }, }, 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(); }, }, }, }, };