diff --git a/boards/SMAQ3.py b/boards/SMAQ3.py index 250e8a9d6..6bda94a98 100644 --- a/boards/SMAQ3.py +++ b/boards/SMAQ3.py @@ -50,6 +50,7 @@ info = { 'SOURCES += libs/misc/nmea.c', 'JSMODULESOURCES += libs/js/banglejs/locale.min.js', 'DEFINES += -DBANGLEJS', + 'DEFINES += -D\'IS_PIN_A_BUTTON(PIN)=((PIN==17)||(PIN==40)||(PIN==41))\'', # 'DEFINES += -DBOARD_PCA10056', # 'DEFINES += -DNRF_USB=1 -DUSB', @@ -107,7 +108,7 @@ devices = { }, 'BAT' : { 'pin_charging' : 'D23', # active low -# 'pin_voltage' : '' + 'pin_voltage' : 'D3' }, 'HEARTRATE' : { 'device' : 'VC31', 'addr' : 0x33, diff --git a/libs/banglejs/jswrap_bangle.c b/libs/banglejs/jswrap_bangle.c index 9a5ee1488..1e0fbdd52 100644 --- a/libs/banglejs/jswrap_bangle.c +++ b/libs/banglejs/jswrap_bangle.c @@ -858,6 +858,9 @@ void touchHandler(bool state, IOEventFlags flags) { lastBtn2 = btn2; lastBtn3 = btn3; + + + lastGesture = gesture; } #endif @@ -2727,7 +2730,6 @@ Draws to the screen and returns immediately. E.showMessage("These are\nLots of\nLines","My Title") ``` */ - /*JSON{ "type" : "staticmethod", "class" : "E", @@ -2774,6 +2776,19 @@ The second `options` argument can contain: ``` */ +/*JSON{ + "type" : "staticmethod", "class" : "E", "name" : "showMenu", "patch":true, + "generate_js" : "libs/js/banglejs/E_showMenu_SMAQ3.js", + "#if" : "defined(BANGLEJS) && defined(SMAQ3)" +} +*/ +/*JSON{ + "type" : "staticmethod", "class" : "E", "name" : "showPrompt", "patch":true, + "generate_js" : "libs/js/banglejs/E_showPrompt_SMAQ3.js", + "#if" : "defined(BANGLEJS) && defined(SMAQ3)" +} +*/ + /*JSON{ "type" : "staticmethod", "class" : "E", @@ -2882,4 +2897,3 @@ This is a fake pin, used only for injecting 'fake' button press events from the "return" : ["pin",""] } */ - diff --git a/libs/banglejs/jswrap_bangle.h b/libs/banglejs/jswrap_bangle.h index b8ff36def..ff01d3ba3 100644 --- a/libs/banglejs/jswrap_bangle.h +++ b/libs/banglejs/jswrap_bangle.h @@ -49,6 +49,7 @@ bool jswrap_banglejs_idle(); bool jswrap_banglejs_gps_character(char ch); #ifdef SMAQ3 +// We use pins that are unused for 'fake' buttons to allow Bangle.js v1 apps to work #define FAKE_BTN1_PIN 40 #define FAKE_BTN3_PIN 41 #endif diff --git a/libs/js/banglejs/E_showMenu_SMAQ3.js b/libs/js/banglejs/E_showMenu_SMAQ3.js new file mode 100644 index 000000000..0cbd20e34 --- /dev/null +++ b/libs/js/banglejs/E_showMenu_SMAQ3.js @@ -0,0 +1,148 @@ +(function(items) { + if (Bangle.btnWatches) { + Bangle.btnWatches.forEach(clearWatch); + Bangle.btnWatches = undefined; + } + g.clear(1);g.flip(); // clear screen if no menu supplied + Bangle.drawWidgets(); + if (!items) return; + var w = g.getWidth()-9; + var h = g.getHeight(); + var menuItems = Object.keys(items); + var options = items[""]; + if (options) menuItems.splice(menuItems.indexOf(""),1); + if (!(options instanceof Object)) options = {}; + options.fontHeight=16; + options.x=0; + options.x2=w-2; + options.y=24; + options.y2=220; + if (options.selected === undefined) + options.selected = 0; + if (!options.fontHeight) + options.fontHeight = 6; + var x = 0|options.x; + var x2 = options.x2||(g.getWidth()-1); + var y = 0|options.y; + var y2 = options.y2||(g.getHeight()-1); + if (options.title) + y += options.fontHeight+2; + var cBg = 0; // background col + var cFg = 7; // foreground col + var cHighlightBg = 1; + var cHighlightFg = 7; + var loc = require("locale"); + var l = { + draw : function() { + g.reset(); + g.setColor(cFg); + g.setFont('6x8',2).setFontAlign(0,-1,0); + if (options.title) { + g.drawString(options.title,(x+x2)/2,y-options.fontHeight-2); + g.drawLine(x,y-2,x2,y-2); + } + + var rows = 0|Math.min((y2-y) / options.fontHeight,menuItems.length); + var idx = E.clip(options.selected-(rows>>1),0,menuItems.length-rows); + var iy = y; + var less = idx>0; + while (rows--) { + var name = menuItems[idx]; + var item = items[name]; + var hl = (idx==options.selected && !l.selectEdit); + g.setColor(hl ? cHighlightBg : cBg); + g.fillRect(x,iy,x2,iy+options.fontHeight-1); + g.setColor(hl ? cHighlightFg : cFg); + g.setFontAlign(-1,-1); + g.drawString(loc.translate(name),x,iy); + if ("object" == typeof item) { + var xo = x2; + var v = item.value; + if (item.format) v=item.format(v); + v = loc.translate(""+v); + if (l.selectEdit && idx==options.selected) { + xo -= 24 + 1; + g.setColor(cHighlightBg); + g.fillRect(xo-(g.stringWidth(v)+4),iy,x2,iy+options.fontHeight-1); + g.setColor(cHighlightFg); + g.drawImage("\x0c\x05\x81\x00 \x07\x00\xF9\xF0\x0E\x00@",xo,iy+(options.fontHeight-10)/2,{scale:2}); + } + g.setFontAlign(1,-1); + g.drawString(v,xo-2,iy); + } + g.setColor(cFg); + iy += options.fontHeight; + idx++; + } + g.setFontAlign(-1,-1); + var more = idxitem.max) item.value = item.max; + if (item.onchange) item.onchange(item.value); + } else { + options.selected = (dir+options.selected)%menuItems.length; + if (options.selected<0) options.selected += menuItems.length; + } + l.draw(); + } + }; + l.draw(); + Bangle.btnWatches = [ + setWatch(function() { l.move(-1); }, BTN1, {repeat:1}), + setWatch(function() { l.move(1); }, BTN3, {repeat:1}), + setWatch(function() { l.select(); }, BTN2, {repeat:1}) + ]; + return l; +}) diff --git a/libs/js/banglejs/E_showPrompt_SMAQ3.js b/libs/js/banglejs/E_showPrompt_SMAQ3.js new file mode 100644 index 000000000..22b3a3b55 --- /dev/null +++ b/libs/js/banglejs/E_showPrompt_SMAQ3.js @@ -0,0 +1,83 @@ +/* options = { + title: text + buttons : {"Yes":true,"No":false} +} */ +(function(msg,options) { + if (!options) options={}; + if (!options.buttons) + options.buttons = {"Yes":true,"No":false}; + var loc = require("locale"); + var btns = Object.keys(options.buttons); + if (!options.selected) + options.selected = 0; + function draw() { + g.reset().setFont("6x8",2).setFontAlign(0,0).setColor(7); + var W = g.getWidth(); + var H = g.getHeight(); + var title = options.title; + if (title) { + title = loc.translate(title); + g.drawString(title,W/2,34); + var w = (g.stringWidth(title)+16)/2; + g.fillRect((W/2)-w,44,(W/2)+w,44); + } + var lines = msg.split("\n"); + var offset = (H - lines.length*16)/2; + lines.forEach((line,y)=> + g.drawString(loc.translate(line),W/2,offset + y*16)); + var buttonWidths = 0; + var buttonPadding = 16; + btns.forEach(btn=>buttonWidths += buttonPadding+g.stringWidth(loc.translate(btn))); + var x = (W-buttonWidths)/2; + var y = H-40; + btns.forEach((btn,idx)=>{ + btn = loc.translate(btn); + var w = g.stringWidth(btn); + x += (buttonPadding+w)/2; + var bw = 2+w/2; + var poly = [x-bw,y-12, + x+bw,y-12, + x+bw+4,y-8, + x+bw+4,y+8, + x+bw,y+12, + x-bw,y+12, + x-bw-4,y+8, + x-bw-4,y-8, + x-bw,y-12]; + g.setColor(idx==options.selected ? 1 : 0).fillPoly(poly).setColor(7).drawPoly(poly).drawString(btn,x,y+1); + x += (buttonPadding+w)/2; + }); + g.setColor(7).flip(); // turn screen on + } + + if (Bangle.btnWatches) { + Bangle.btnWatches.forEach(clearWatch); + Bangle.btnWatches = undefined; + } + g.clear(1); // clear screen + Bangle.drawWidgets(); // redraw widgets + if (!msg) { + return Promise.resolve(); + } + draw(); + return new Promise(resolve=>{ + Bangle.btnWatches = [ + setWatch(function() { + if (options.selected>0) { + options.selected--; + draw(); + } + }, BTN1, {repeat:1}), + setWatch(function() { + if (options.selected2", // add a #if statement in the generated C file (ONLY if type==object) +# "patch" : true // if true, this isn't a complete JSON, but just updates another with the same class+name #}*/ # # description can be an array of strings as well as a simple string (in which case each element is separated by a newline), @@ -230,6 +231,13 @@ def get_jsondata(is_for_document, parseArgs = True, board = False): if not r: print(dropped_prefix+" because of #if "+jsondata["#if"]+ " -> "+expr) drop = True + if not drop and "patch" in jsondata: + targetjsondata = [x for x in jsondatas if x["type"]==jsondata["type"] and x["class"]==jsondata["class"] and x["name"]==jsondata["name"]][0] + for key in jsondata: + if not key in ["type","class","name","patch"]: + print("Copying "+key+" --- "+jsondata[key]); + targetjsondata[key] = jsondata[key] + drop = True if not drop: jsondatas.append(jsondata) except ValueError as e: