Skip to content

Instantly share code, notes, and snippets.

@gfwilliams
Last active February 10, 2020 14:36
Show Gist options
  • Save gfwilliams/4bd0d57bc653fe6fb63c1a0adb4c7d4f to your computer and use it in GitHub Desktop.
Save gfwilliams/4bd0d57bc653fe6fb63c1a0adb4c7d4f to your computer and use it in GitHub Desktop.
Modules.addCached("graphical_menu",function() {
exports.list = function(g, items) {
var options = items[""];
var menuItems = Object.keys(items);
if (options) menuItems.splice(menuItems.indexOf(""),1);
if (!(options instanceof Object)) options = {};
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 = options.cB||0; // background col
var cFg = options.cF; // foreground col
if (cFg===undefined) cFg=-1;
var cHighlightBg = options.cHlB;
if (cHighlightBg===undefined) cHighlightBg=-1;
var cHighlightFg = options.cHlF||0;
var l = {
draw : function() {
g.setColor(cFg);
if (options.predraw) options.predraw(g);
g.setFontAlign(0,-1);
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];
g.setColor((idx==options.selected && !l.selectEdit) ? cHighlightBg : cBg);
g.fillRect(x,iy,x2,iy+options.fontHeight-1);
g.setColor(cHighlightFg);
g.setFontAlign(-1,-1);
g.drawString(name,x,iy);
if ("object" == typeof item) {
var xo = x2;
var v = item.value;
if (item.format) v=item.format(v);
if (l.selectEdit) {
var s = (options.fontHeight>10)?2:1;
xo -= 12*s + 1;
g.setColor(cHighlightBg);
g.fillRect(xo-(g.stringWidth(v)+4),iy,x2,iy+options.fontHeight-1);
g.setColor(cHighlightFg);
g.drawImage({width:12,height:5,buffer:" \x07\x00\xF9\xF0\x0E\x00@",transparent:0},xo,iy+(options.fontHeight-5*s)/2,{scale:s});
}
g.setFontAlign(1,-1);
g.drawString(v,xo-2,iy);
}
g.setColor(cFg);
iy += options.fontHeight;
idx++;
}
g.setFontAlign(-1,-1);
if (options.preflip) options.preflip(g,less,idx<menuItems.length);
if (g.flip) g.flip();
},
select : function(dir) {
var item = items[menuItems[options.selected]];
if ("function" == typeof item) item(l);
else if ("object" == typeof item) {
// if a number, go into 'edit mode'
if ("number" == typeof item.value)
l.selectEdit = l.selectEdit?undefined:item;
else { // else just toggle bools
if ("boolean" == typeof item.value) item.value=!item.value;
if (item.onchange) item.onchange(item.value);
}
l.draw();
}
},
move : function(dir) {
if (l.selectEdit) {
var item = l.selectEdit;
item.value -= (dir||1)*(item.step||1);
if (item.min!==undefined && item.value<item.min) item.value = item.min;
if (item.max!==undefined && item.value>item.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();
return l;
};
});
E.showMenu = function(menudata) {
if (Bangle.btnWatches) {
Bangle.btnWatches.forEach(clearWatch);
Bangle.btnWatches = undefined;
}
g.clear(1);g.flip(); // clear screen if no menu supplied
Bangle.drawWidgets();
if (!menudata) return;
function im(b) {
return {
width:8,height:b.length,bpp:1,buffer:new Uint8Array(b).buffer
};
}
if (!menudata[""]) menudata[""]={};
var w = g.getWidth()-9;
var h = g.getHeight();
menudata[""].fontHeight=16;
menudata[""].x=0;
menudata[""].x2=w-2;
menudata[""].y=24;
menudata[""].y2=220;
menudata[""].cB=0x0007;
menudata[""].cHlB=0x02F7;
menudata[""].cHlF=-1;
menudata[""].predraw=function() {
g.setFont('6x8',2);g.setFontAlign(-1,-1,0);
};
menudata[""].preflip=function(g,less,more) {
g.drawImage(im([
0b00010000,
0b00111000,
0b01111100,
0b11111110,
0b00010000,
0b00010000,
0b00010000,
0b00010000,
]),w,40);
g.drawImage(im([
0b00010000,
0b00010000,
0b00010000,
0b00010000,
0b11111110,
0b01111100,
0b00111000,
0b00010000,
]),w,194);
g.drawImage(im([
0b00000000,
0b00001000,
0b00001100,
0b00001110,
0b11111111,
0b00001110,
0b00001100,
0b00001000,
]),w,116);
g.setColor(more?-1:0);
g.fillPoly([104,220,136,220,120,228]);
//g.drawLine(7,0,7,h);
//g.drawLine(w,0,w,h);
};
var m = require("graphical_menu").list(g, menudata);
Bangle.btnWatches = [
setWatch(function() { m.move(-1); }, BTN1, {repeat:1}),
setWatch(function() { m.move(1); }, BTN3, {repeat:1}),
setWatch(function() { m.select(); }, BTN2, {repeat:1})
];
return m;
};
var mainmenu = {
'': { 'title': 'Settings' },
'Make Connectable': ()=>{},
'BLE': ()=>{},
'Programmable': ()=>{},
'LCD Timeout': {
value: 10,
min: 0,
max: 60,
step: 5},
'Beep': ()=>{},
'Vibration': ()=>{},
'Locale': ()=>{},
'Select Clock': ()=>{},
'HID': ()=>{},
'Set Time': ()=>{},
'Reset Settings': ()=>{},
'Turn Off': ()=>{},
'< Back': ()=> {load();}
};
Bangle.loadWidgets();
E.showMenu(mainmenu);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment