|
1 |
| -var exports = {}; |
2 | 1 | /* Module that allows for loading of clock 'info' displays
|
3 | 2 | that can be scrolled through on the clock face.
|
4 | 3 |
|
@@ -129,62 +128,112 @@ Simply supply the menu data (from .load) and a function to draw the clock info.
|
129 | 128 |
|
130 | 129 | For example:
|
131 | 130 |
|
132 |
| -let clockInfoMenu = require("clock_info").addInteractive(require("clock_info").load(), (itm, info) => { |
133 |
| - var x = 20, y = 20, w=80, h=48; |
134 |
| - g.reset().clearRect(x,y,x+w-1,y+h-1); |
135 |
| - g.drawRect(x,y,x+w-1,y+h-1); // debug - just to show where we are |
136 |
| - g.drawImage(info.img, x+w/2-12,y+4); |
137 |
| - g.setFont("6x8:2").setFontAlign(0,0).drawString(info.text, x+w/2,y+36); |
138 |
| -}); |
| 131 | +let clockInfoMenu = require("clock_info").addInteractive(require("clock_info").load(), { |
| 132 | + x : 20, y: 20, w: 80, h:80, // dimensions of area used for clock_info |
| 133 | + draw : (itm, info, options) => { |
| 134 | + g.reset().clearRect(options.x, options.y, options.x+options.w-2, options.y+options.h-1); |
| 135 | + if (options.focus) g.drawRect(options.x, options.y, options.x+options.w-2, options.y+options.h-1); // show if focused |
| 136 | + var midx = options.x+options.w/2; |
| 137 | + g.drawImage(info.img, midx-12,options.y+4); |
| 138 | + g.setFont("6x8:2").setFontAlign(0,0).drawString(info.text, midx,options.y+36); |
| 139 | +}}); |
139 | 140 | // then when clock 'unloads':
|
140 | 141 | clockInfoMenu.remove();
|
141 | 142 | delete clockInfoMenu;
|
142 | 143 |
|
143 | 144 | Then if you need to unload the clock info so it no longer
|
144 | 145 | uses memory or responds to swipes, you can call clockInfoMenu.remove()
|
145 | 146 | and delete clockInfoMenu
|
| 147 | +
|
| 148 | +clockInfoMenu is the 'options' parameter, with the following added: |
| 149 | +
|
| 150 | +* 'remove' - remove this clockInfo item |
| 151 | +* 'redraw' - force a redraw |
| 152 | +* 'focus' - bool to show if menu is focused or not |
| 153 | +
|
146 | 154 | */
|
147 |
| -exports.addInteractive = function(menu, drawFn) { |
| 155 | +exports.addInteractive = function(menu, options) { |
| 156 | + if ("function" == typeof options) options = {draw:options}; // backwards compatibility |
| 157 | + exports.loadCount = (0|exports.loadCount)+1; |
| 158 | + options.focus = exports.loadCount==1; // focus if we're the first one loaded |
148 | 159 | if (!menu.length || !menu[0].items.length) return; // no info
|
149 |
| - var menuA = 0, menuB = 0; |
| 160 | + if (options.menuA===undefined) options.menuA = 0; |
| 161 | + if (options.menuB===undefined) options.menuB = Math.min(exports.loadCount, menu[0].items.length)-1; |
| 162 | + function drawItem(itm) { |
| 163 | + options.draw(itm, itm.get(), options); |
| 164 | + } |
150 | 165 | function menuShowItem(itm) {
|
151 |
| - itm.on('redraw', ()=>drawFn(itm, itm.get())); |
152 |
| - itm.show(); |
| 166 | + options.redrawHandler = ()=>drawItem(itm); |
| 167 | + itm.on('redraw', options.redrawHandler); |
| 168 | + itm.uses = (0|itm.uses)+1; |
| 169 | + if (itm.uses==1) itm.show(); |
153 | 170 | itm.emit("redraw");
|
154 | 171 | }
|
| 172 | + function menuHideItem(itm) { |
| 173 | + itm.removeListener('redraw',options.redrawHandler); |
| 174 | + delete options.redrawHandler; |
| 175 | + itm.uses--; |
| 176 | + if (!itm.uses) |
| 177 | + itm.hide(); |
| 178 | + } |
155 | 179 | // handling for swipe between menu items
|
156 | 180 | function swipeHandler(lr,ud){
|
| 181 | + if (!options.focus) return; // ignore if we're not focussed |
157 | 182 | var oldMenuItem;
|
158 | 183 | if (ud) {
|
159 |
| - if (menu[menuA].items.length==1) return; // 1 item - can't move |
160 |
| - oldMenuItem = menu[menuA].items[menuB]; |
161 |
| - menuB += ud; |
162 |
| - if (menuB<0) menuB = menu[menuA].items.length-1; |
163 |
| - if (menuB>=menu[menuA].items.length) menuB = 0; |
| 184 | + if (menu[options.menuA].items.length==1) return; // 1 item - can't move |
| 185 | + oldMenuItem = menu[options.menuA].items[options.menuB]; |
| 186 | + options.menuB += ud; |
| 187 | + if (options.menuB<0) options.menuB = menu[options.menuA].items.length-1; |
| 188 | + if (options.menuB>=menu[options.menuA].items.length) options.menuB = 0; |
164 | 189 | } else if (lr) {
|
165 | 190 | if (menu.length==1) return; // 1 item - can't move
|
166 |
| - oldMenuItem = menu[menuA].items[menuB]; |
167 |
| - menuA += ud; |
168 |
| - if (menuA<0) menuA = menu.length-1; |
169 |
| - if (menuA>=menu.length) menuA = 0; |
170 |
| - menuB = 0; |
| 191 | + oldMenuItem = menu[options.menuA].items[options.menuB]; |
| 192 | + options.menuA += ud; |
| 193 | + if (options.menuA<0) options.menuA = menu.length-1; |
| 194 | + if (options.menuA>=menu.length) options.menuA = 0; |
| 195 | + options.menuB = 0; |
171 | 196 | }
|
172 | 197 | if (oldMenuItem) {
|
173 |
| - oldMenuItem.hide(); |
| 198 | + menuHideItem(oldMenuItem); |
174 | 199 | oldMenuItem.removeAllListeners("draw");
|
175 |
| - menuShowItem(menu[menuA].items[menuB]); |
| 200 | + menuShowItem(menu[options.menuA].items[options.menuB]); |
176 | 201 | }
|
177 | 202 | }
|
178 | 203 | Bangle.on("swipe",swipeHandler);
|
| 204 | + var touchHandler; |
| 205 | + if (options.x!==undefined && options.y!==undefined && options.w && options.h) { |
| 206 | + touchHandler = function(_,e) { |
| 207 | + if (e.x<options.x || e.y<options.y || |
| 208 | + e.x>(options.x+options.w) || e.y>(options.y+options.h)) { |
| 209 | + if (options.focus) { |
| 210 | + options.focus=false; |
| 211 | + options.redraw(); |
| 212 | + } |
| 213 | + return; // outside area |
| 214 | + } |
| 215 | + if (!options.focus) { |
| 216 | + options.focus=true; // if not focussed, set focus |
| 217 | + options.redraw(); |
| 218 | + } else if (menu[options.menuA].items[options.menuB].run) |
| 219 | + menu[options.menuA].items[options.menuB].run(); // allow tap on an item to run it (eg home assistant) |
| 220 | + else options.focus=true; |
| 221 | + }; |
| 222 | + Bangle.on("touch",touchHandler); |
| 223 | + } |
179 | 224 | // draw the first item
|
180 |
| - menuShowItem(menu[menuA].items[menuB]); |
| 225 | + menuShowItem(menu[options.menuA].items[options.menuB]); |
181 | 226 | // return an object with info that can be used to remove the info
|
182 |
| - return { |
183 |
| - remove : function() { |
184 |
| - Bangle.removeListener("swipe",swipeHandler); |
185 |
| - menu[menuA].items[menuB].hide(); |
186 |
| - } |
| 227 | + options.remove = function() { |
| 228 | + Bangle.removeListener("swipe",swipeHandler); |
| 229 | + if (touchHandler) Bangle.removeListener("touch",touchHandler); |
| 230 | + menuHideItem(menu[options.menuA].items[options.menuB]); |
| 231 | + exports.loadCount--; |
| 232 | + }; |
| 233 | + options.redraw = function() { |
| 234 | + drawItem(menu[options.menuA].items[options.menuB]); |
187 | 235 | };
|
| 236 | + return options; |
188 | 237 | };
|
189 | 238 |
|
190 | 239 | // Code for testing (plots all elements from first list)
|
|
0 commit comments