Showing 4 changed files with 236 additions and 87 deletions
+79
Nasal/knobs.nas
... ...
@@ -63,6 +63,85 @@ var knobsClass = {
63 63
         me.device.display.updateXPDR();
64 64
     },
65 65
 
66
+    MenuSettings : func (d) {
67
+        var (id, selected) = split('-', me.device.windows.selected);
68
+        var state = me.device.windows.state[id];
69
+        if (find('choices', state.lines[selected].type) > -1) {
70
+            var val = me.device.windows.window[me.device.windows.selected]
71
+                .get('text');
72
+            forindex (var i; state.lines[selected].choices)
73
+                if (state.lines[selected].choices[i] == val) {
74
+                    if (i == size(state.lines[selected].choices) - 1)
75
+                        me.device.windows.window[me.device.windows.selected]
76
+                            .setText(state.lines[selected].choices[0]);
77
+                     else
78
+                        me.device.windows.window[me.device.windows.selected]
79
+                            .setText(state.lines[selected].choices[i + 1]);
80
+                     break;
81
+                }
82
+        }
83
+        elsif (find('time', state.lines[selected].type) > -1) {
84
+            var val = me.device.windows.window[me.device.windows.selected]
85
+                .get('text');
86
+            var (hh, mm, ss) = split(':', val);
87
+            var time = hh * 3600 + mm * 60 + ss;
88
+            if (time >= 600) # 10 min
89
+                d *= 60;
90
+            elsif (time >= 300) # 5 minutes
91
+                d *= 30;
92
+            elsif (time >= 180) # 3 minutes
93
+                d *= 10;
94
+
95
+            ss += d;
96
+
97
+            if (ss > 59) {
98
+                ss -= 60;
99
+                mm += 1;
100
+                if (mm > 59) {
101
+                    mm = 0;
102
+                    hh += 1;
103
+                }
104
+            }
105
+            elsif (ss < 0) {
106
+                if (mm > 0) {
107
+                    ss += 60;
108
+                    mm -= 1;
109
+                }
110
+                elsif (mm == 0 and hh > 0) {
111
+                    ss += 60;
112
+                    mm = 59;
113
+                    hh -= 1;
114
+                }
115
+                elsif (mm == 0 and hh == 0)
116
+                    ss = 0;
117
+            }
118
+            me.device.windows.window[me.device.windows.selected]
119
+                .setText(sprintf('%02i:%02i:%02i', hh, mm, ss));
120
+        }
121
+    },
122
+
123
+    NavigateMenu : func (d) {
124
+        var (id, selected) = split('-', me.device.windows.selected);
125
+        var state = me.device.windows.state[id];
126
+        for (var i = selected + d; i >= 0 and i < size(state.lines); i += d) {
127
+            if (find('editable', state.lines[i].type) > -1) {
128
+                state.lines[i].type = string.replace(state.lines[i].type,
129
+                        'editable', 'selected');
130
+                state.lines[selected].type = string.replace(state.lines[selected].type,
131
+                        'selected', 'editable');
132
+                me.device.windows.window[me.device.windows.selected]
133
+                    .setDrawMode(0x01)
134
+                    .setColor(0,1,1);
135
+                me.device.windows.window[id ~ '-' ~ i]
136
+                    .setDrawMode(0x05)
137
+                    .setColorFill(0,1,1)
138
+                    .setColor(0,0,0);
139
+                me.device.windows.selected = id ~ '-' ~ i;
140
+                break;
141
+            }
142
+        }
143
+    },
144
+
66 145
     FmsInner : void,
67 146
     FmsOuter : void
68 147
 };
+155 -86
Nasal/menu.nas
... ...
@@ -1,86 +1,155 @@
1
-var ADFDME = func { 
2
-    nyi('AFDME softkey'); 
3
-}
4
-
5
-var IDENT = func { 
6
-    nyi('IDENT softkey'); 
7
-}
8
-
9
-var VOR1 = func {
10
-    radios.getNode('nav2-selected').setIntValue(0);
11
-    radios.getNode('nav1-selected').setIntValue(1);
12
-    CDIfromNAV(0);
13
-}
14
-
15
-var VOR2 = func {
16
-    radios.getNode('nav1-selected').setIntValue(0);
17
-    radios.getNode('nav2-selected').setIntValue(1);
18
-    CDIfromNAV(1);
19
-}
20
-
21
-var STDBY = func { 
22
-    setprop('/instrumentation/zkv1000/radios/xpdr-mode', 'STBY');
23
-    setprop('/instrumentation/transponder/serviceable', 0);
24
-}
25
-
26
-var ON = func { 
27
-    setprop("/instrumentation/zkv1000/radios/xpdr-mode", "ON");
28
-}
29
-
30
-var ALT = func { 
31
-    setprop("/instrumentation/zkv1000/radios/xpdr-mode", "ALT");
32
-}
33
-
34
-var GND = func { 
35
-    setprop("/instrumentation/zkv1000/radios/xpdr-mode", "GND");
36
-}
37
-
38
-var VFR = func { 
39
-    XPDR_old = getprop("/instrumentation/transponder/id-code");
40
-    setprop("/instrumentation/transponder/id-code", 1200);
41
-}
42
-
43
-var BKSP = func { 
44
-    if (XPDR_n < 3) XPDR_n += 1;
45
-}
46
-
47
-var LIGHT = func {
48
-    var b = '/instrumentation/zkv1000/body-emission';
49
-    setprop(b, getprop(b) < 0.1 ? 0.5 : 0.0);
50
-}
51
-
52
-var CHECKLIST = func {
53
-}
54
-
55
-var LEAN = func {
56
-}
57
-
58
-var FUEL = func (v) {
59
-}
60
-
61
-var XPDR_n = 3;
62
-var XPDR_old = 0;
63
-
64
-
65
-var menuTable = [
66
-    '         INSET            PFD              CDI    ADF   XPDR  IDENT   TMR   NRST',
67
-    '         VOR1   VOR2   GPS    OFF                                                 BACK',
68
-    ' OFF   DCLTR          TRAFF  TOPO  TERR  STRM   NEXR XMLTG           BACK',
69
-    ' OFF   DCLT1 DCLT2 DCLT3                                                        BACK',
70
-    'LIGHT DFLTS  WIND   DME   BRG1   HSI    BRG2           ALT U  BARO  BACK',
71
-    'VOR1    GPS    ADF             OFF                                                BACK',
72
-    'VOR2    GPS    ADF             OFF                                                BACK',
73
-    '                                               360    ARC                              BACK',
74
-    '                  OPT1   OPT2   OPT3            OFF                              BACK',
75
-    '                                             METER             IN     HPA            BACK',
76
-    '                   STBY    ON     ALT    GND    VFR   CODE  IDENT          BACK',
77
-    '   0        1       2        3       4        5       6        7    IDENT  BKSP  BACK',
78
-    ' SFD    ENG             MAP           DCLTR          CHKLS',
79
-    '                 DCLT1           DCLT2          DCLT3                             BACK',
80
-    '                          TRAFF  TOPO   TERR  STRM  NEXR  XMLTG          BACK',
81
-    'ENGN           LEAN                              DECF   INCF   RSTF',
82
-    ' MFD  INSET            PFD              CDI    ADF   XPDR  IDENT   TMR   NRST',
83
-    '  LCL    UTC               RL            CHRON                                     BACK',
84
-];
85
-
86
-
1
+var pageClass = {
2
+    new : func (d) {
3
+        var m = { parents : [pageClass] };
4
+        m.page = d.display.screen;
5
+        m.window = {};
6
+        m.state = {};
7
+        m.selected = '';
8
+        return m;
9
+    },
10
+
11
+    del : func (id = nil) {
12
+        if (id != nil and typeof(v) == 'scalar') {
13
+            delete(me.state, id);
14
+            id = [ id ];
15
+        }
16
+        else {
17
+            foreach (var s; keys(me.state))
18
+                delete(me.state, s);
19
+            id = keys(me.window);
20
+        }
21
+        foreach (var w; id) {
22
+            me.window[w]
23
+                .hide()
24
+                .del();
25
+            delete(me.window, w);
26
+        }
27
+    },
28
+
29
+    _selected_text : func (id, text, x, y) {
30
+        me.selected = id;
31
+        me.window[id]
32
+            .setFontSize(16)
33
+            .setFont('LiberationFonts/LiberationMono-Regular.ttf')
34
+            .setTranslation(x, y)
35
+            .setDrawMode(0x01 + 0x04)
36
+            .setText(text)
37
+            .setColorFill(0,1,1)
38
+            .setColor(0,0,0);
39
+    },
40
+
41
+    _editable_text : func (id, text, x, y) {
42
+        me.window[id]
43
+            .setFontSize(16)
44
+            .setFont('LiberationFonts/LiberationMono-Regular.ttf')
45
+            .setTranslation(x, y)
46
+            .setText(text)
47
+            .setColorFill(0,0,0)
48
+            .setColor(0,1,1);
49
+    },
50
+
51
+    _normal_text : func (id, text, x, y) {
52
+        me.window[id]
53
+            .setFontSize(16)
54
+            .setFont('LiberationFonts/LiberationMono-Regular.ttf')
55
+            .setTranslation(x, y)
56
+            .setText(text)
57
+            .setColorFill(0,0,0)
58
+            .setColor(1,1,1);
59
+    },
60
+
61
+    _title_text : func (id, text, x, y) {
62
+        me.window[id]
63
+            .setFontSize(16)
64
+            .setFont('LiberationFonts/LiberationMono-Regular.ttf')
65
+            .setTranslation(x, y)
66
+            .setAlignment('center-center')
67
+            .setText(text)
68
+            .setColorFill(0,0,0)
69
+            .setColor(0,1,1);
70
+    },
71
+
72
+    fill : func (id) {
73
+        var state = me.state[id];
74
+        forindex (var line; state.lines) {
75
+            if (find('separator', state.lines[line].type) > -1) {
76
+                me.window[id ~ '-' ~ line] = me.page.createChild('path')
77
+                    .setStrokeLineWidth(1)
78
+                    .moveTo(state.x_base, state.geometry.y - 12)
79
+                    .horiz(state.geometry.w - 20)
80
+                    .setColor(1,1,1);
81
+                state.geometry.x = state.x_base;
82
+                state.geometry.y += 8;
83
+            }
84
+            else {
85
+                me.window[id ~ '-' ~ line] = me.page.createChild('text');
86
+                if (find('normal', state.lines[line].type) > -1)
87
+                    me._normal_text(
88
+                            id ~ '-' ~ line,
89
+                            state.lines[line].text,
90
+                            state.geometry.x,
91
+                            state.geometry.y,
92
+                            );
93
+
94
+                elsif (find('selected', state.lines[line].type) > -1)
95
+                    me._selected_text(
96
+                            id ~ '-' ~ line,
97
+                            state.lines[line].text,
98
+                            state.geometry.x,
99
+                            state.geometry.y,
100
+                            );
101
+
102
+                elsif (find('editable', state.lines[line].type) > -1)
103
+                    me._editable_text(
104
+                            id ~ '-' ~ line,
105
+                            state.lines[line].text,
106
+                            state.geometry.x,
107
+                            state.geometry.y,
108
+                            );
109
+
110
+                elsif (find('title', state.lines[line].type) > -1)
111
+                    me._title_text(
112
+                            id ~ '-' ~ line,
113
+                            state.lines[line].text,
114
+                            state.x_base - 10 + state.geometry.w / 2,
115
+                            state.geometry.y
116
+                        );
117
+
118
+                if (find('end-of-line', state.lines[line].type) > -1
119
+                or  find('title', state.lines[line].type) > -1) {
120
+                    state.geometry.x = state.x_base;
121
+                    state.geometry.y += 24;
122
+                }
123
+                else
124
+                    state.geometry.x += size(state.lines[line].text) * 10 + 8;
125
+            }
126
+        }
127
+    },
128
+    
129
+    draw : func (id, geometry, lines) {
130
+        if (contains(me.window, id ~ '-bg')) {
131
+            printlog('debug', 'objet ' ~ id ~ ' already exists');
132
+            return;
133
+        }
134
+        if (!contains(geometry, 'h') and !contains(geometry, 'l')) {
135
+            printlog('debug', 'missing parameter l or h');
136
+            return;
137
+        }
138
+        me.state[id] = {
139
+            lines: lines, 
140
+            geometry: geometry,
141
+            x_base : geometry.x + 10,
142
+            h_max : contains(geometry, 'h') ? h : geometry.l * 24 + 8 + geometry.sep * 16,
143
+        };
144
+        me.state[id].y_max = me.state[id].h_max + me.state[id].geometry.y;
145
+        me.window[id ~ '-bg'] = me.page.createChild('path');
146
+        me.window[id ~ '-bg']
147
+            .rect(geometry.x, geometry.y,
148
+                  geometry.w, me.state[id].h_max)
149
+            .setColor(1,1,1)
150
+            .setColorFill(0,0,0);
151
+        me.state[id].geometry.x += 10;
152
+        me.state[id].geometry.y += 16;
153
+        me.fill(id);
154
+    },
155
+};
+1
README.md
... ...
@@ -81,6 +81,7 @@ Please report bug at <seb.marque@free.fr>.
81 81
 * ![][70%]
82 82
   * make booting animation visible ![][pending]
83 83
 * ![][60%]
84
+  * windows management: selectable items ![][done], modifiable items ![][done], scrolling ![][ongoing]
84 85
 * ![][50%]
85 86
   * EIS: animations for temperature for YaSim and JSBSim
86 87
 * ![][40%]
+1 -1
zkv1000.nas
... ...
@@ -8,9 +8,9 @@ files_to_load = [
8 8
     'softkeys.nas',# handles softkeys and menus items
9 9
     'map.nas',     # moves the maps
10 10
     'display.nas',
11
+    'menu.nas',    # manage windows
11 12
     'core.nas',    # the scheduler and switch on button
12 13
 ];
13
-#    'menu.nas',    # manages menu entries andd perform some simple actions
14 14
 #    'afcs.nas',    # Automatic Flight Control System
15 15
 #    'routes.nas',  # manages flightplans and routes
16 16
 #    'display.nas', # display messages and popups