224 lines
8.0 KiB
JavaScript
224 lines
8.0 KiB
JavaScript
E.showMenu = function (items) {
|
|
var ar = Bangle.appRect;
|
|
Bangle.removeAllListeners("drag");
|
|
if (!items) {
|
|
g.clearRect(ar.x, ar.y, ar.x2, ar.y2);
|
|
return false;
|
|
}
|
|
var loc = require("locale");
|
|
const ITEM_HEIGHT = 48;
|
|
var m = {
|
|
info: {
|
|
title: "Menu",
|
|
cB: g.theme.bg,
|
|
cF: g.theme.fg,
|
|
cHB: g.theme.bgH,
|
|
cHF: g.theme.fgH,
|
|
cAB: g.theme.bg2,
|
|
cAF: g.theme.fg2,
|
|
predraw: () => { },
|
|
preflip: () => { }
|
|
},
|
|
scroll: 0,
|
|
items: [],
|
|
selected: -1,
|
|
showTitle: true,
|
|
titleTimeout: null,
|
|
draw: () => {
|
|
g.reset().setFont('12x20');
|
|
m.info.predraw(g);
|
|
const menuStartY = m.showTitle ? ar.y + 20 : ar.y;
|
|
g.setColor(m.info.cB).fillRect(ar.x, menuStartY, ar.x2, ar.y2).setColor(m.info.cF);
|
|
m.items.forEach((e, i) => {
|
|
const s = (i * ITEM_HEIGHT) - m.scroll + menuStartY;
|
|
if (s < ar.y || s > ar.y2 - 10) {
|
|
return false;
|
|
}
|
|
if (i == m.selected) {
|
|
g.setColor(m.info.cHB).fillRect(ar.x, s, ar.x2, Math.min(s + ITEM_HEIGHT, ar.y2)).setColor(m.info.cHF);
|
|
} else {
|
|
g.setColor(m.info.cF);
|
|
}
|
|
g.setFontAlign(0, -1, 0);
|
|
if (e.icon) {
|
|
g.drawString(e.title, ar.x + ((ar.x2 - ar.x) / 2) + 10, s + 5);
|
|
g.drawImage(e.icon, ar.x + ((ar.x2 - ar.x) / 2) - g.stringWidth(e.title) / 2 - 15, s + 5);
|
|
} else {
|
|
g.drawString(e.title, ar.x + ((ar.x2 - ar.x) / 2), s + 5);
|
|
}
|
|
if (e.type && s < ar.y2 - 10) {
|
|
if (e.format) {
|
|
g.setFontAlign(0, -1, 0).drawString(e.format(e.value), ar.x + ((ar.x2 - ar.x) / 2), s + 25);
|
|
} else {
|
|
g.setFontAlign(0, -1, 0).drawString(e.value, ar.x + ((ar.x2 - ar.x) / 2), s + 25);
|
|
}
|
|
}
|
|
});
|
|
if (m.showTitle) {
|
|
g.setColor(m.info.cAB).fillRect(ar.x, ar.y, ar.x2, ar.y + 20);
|
|
g.setColor(m.info.cAF)
|
|
.setFontAlign(0, -1, 0)
|
|
.drawString(m.info.title, ar.x + ((ar.x2 - ar.x) / 2), ar.y + 2);
|
|
}
|
|
m.info.preflip(g, m.scroll > 0, m.scroll < (m.items.length - 1) * ITEM_HEIGHT);
|
|
},
|
|
select: (x, y) => {
|
|
const menuStartY = m.showTitle ? ar.y + 20 : ar.y;
|
|
if (m.selected == -1 || m.selected !== Math.max(Math.min(Math.floor((y + m.scroll - menuStartY) / ITEM_HEIGHT), m.items.length - 1), 0)) {
|
|
if (y) {
|
|
if (y < menuStartY || y > ar.y2) {
|
|
return false;
|
|
} else {
|
|
m.selected = Math.max(Math.min(Math.floor((y + m.scroll - menuStartY) / ITEM_HEIGHT), m.items.length - 1), 0);
|
|
}
|
|
} else {
|
|
m.selected = Math.floor(m.scroll / ITEM_HEIGHT);
|
|
}
|
|
m.draw();
|
|
} else {
|
|
if (m.items[m.selected].type && m.items[m.selected].type === "boolean") {
|
|
m.items[m.selected].value = !m.items[m.selected].value;
|
|
m.items[m.selected].onchange(m.items[m.selected].value);
|
|
m.draw();
|
|
} else if (m.items[m.selected].type && m.items[m.selected].type === "number") {
|
|
if (x && x < ((ar.x + ar.x2) / 2)) {
|
|
m.items[m.selected].value = m.items[m.selected].value - (m.items[m.selected].step ? m.items[m.selected].step : 1);
|
|
} else {
|
|
m.items[m.selected].value = m.items[m.selected].value + (m.items[m.selected].step ? m.items[m.selected].step : 1);
|
|
}
|
|
if (m.items[m.selected].value > (m.items[m.selected].max ? m.items[m.selected].max : Infinity)) {
|
|
m.items[m.selected].value = m.items[m.selected].min ? m.items[m.selected].min : 0;
|
|
}
|
|
if (m.items[m.selected].value < (m.items[m.selected].min ? m.items[m.selected].min : 0)) {
|
|
m.items[m.selected].value = m.items[m.selected].max ? m.items[m.selected].max : 10;
|
|
}
|
|
m.items[m.selected].onchange(m.items[m.selected].value);
|
|
m.draw();
|
|
} else {
|
|
if (m.items[m.selected]) {
|
|
m.items[m.selected]();
|
|
}
|
|
}
|
|
}
|
|
},
|
|
move: d => {
|
|
m.scroll += (d * ITEM_HEIGHT);
|
|
m.scroll = Math.min(Math.max(m.scroll, 0), (m.items.length - 1) * ITEM_HEIGHT);
|
|
const menuStartY = m.showTitle ? ar.y + 20 : ar.y;
|
|
m.selected = Math.max(Math.min(Math.floor((m.scroll - menuStartY) / ITEM_HEIGHT), m.items.length - 1), 0);
|
|
m.draw();
|
|
},
|
|
hideTitle: () => {
|
|
if (m.showTitle) {
|
|
m.showTitle = false;
|
|
m.draw();
|
|
}
|
|
}
|
|
};
|
|
Object.keys(items).forEach(i => {
|
|
if (i == "") {
|
|
m.info = Object.assign(m.info, items[i]);
|
|
} else if (i === "< Back" && items[i]) {
|
|
m.back = items[i];
|
|
} else if (items[i]) {
|
|
m.items.push(items[i]);
|
|
m.items[m.items.length - 1].title = loc.translate(i);
|
|
if (items[i].hasOwnProperty("value")) {
|
|
if (typeof items[i].value === "boolean") {
|
|
m.items[m.items.length - 1].type = "boolean";
|
|
} else {
|
|
m.items[m.items.length - 1].type = "number";
|
|
}
|
|
}
|
|
}
|
|
});
|
|
m.info.title = loc.translate(m.info.title);
|
|
m.draw();
|
|
|
|
// Set timeout to hide title permanently
|
|
m.titleTimeout = setTimeout(() => {
|
|
m.showTitle = false;
|
|
m.draw();
|
|
}, 2000);
|
|
|
|
// Add BTN1 handler for back functionality
|
|
if (m.back) {
|
|
if (Bangle.backHandler) clearWatch(Bangle.backHandler);
|
|
Bangle.backHandler = setWatch(m.back, BTN1, { debounce: 100 });
|
|
}
|
|
|
|
Bangle.on("drag", d => {
|
|
if (!d.b) return false;
|
|
if (d.dx == 0 && d.dy == 0) {
|
|
m.select(d.x, d.y);
|
|
} else {
|
|
m.selected = -1;
|
|
m.scroll -= d.dy;
|
|
m.scroll = Math.min(Math.max(m.scroll, 0), (m.items.length - 1) * ITEM_HEIGHT);
|
|
m.draw();
|
|
}
|
|
});
|
|
return m;
|
|
};
|
|
|
|
E.showAlert = function (e, t) {
|
|
if (!e) {
|
|
E.showMenu();
|
|
return false;
|
|
}
|
|
return new Promise(r => {
|
|
const menu = {
|
|
"": {
|
|
"title": (t ? t : "Alert")
|
|
},
|
|
Ok: () => {
|
|
E.showMenu();
|
|
r();
|
|
}
|
|
};
|
|
menu[e] = () => { };
|
|
E.showMenu(menu);
|
|
});
|
|
};
|
|
E.showMessage = E.showAlert;
|
|
|
|
E.showPrompt = function (e, t) {
|
|
if (!e) {
|
|
E.showMenu();
|
|
return false;
|
|
}
|
|
return new Promise(r => {
|
|
const menu = {
|
|
"": {
|
|
"title": (t && t.title ? t.title : "Choose")
|
|
}
|
|
};
|
|
menu[e] = () => { };
|
|
if (t && t.buttons) {
|
|
Object.keys(t.buttons).forEach(b => {
|
|
menu[b] = () => {
|
|
E.showMenu();
|
|
r(t.buttons[b]);
|
|
};
|
|
});
|
|
} else {
|
|
menu.Yes = () => {
|
|
E.showMenu();
|
|
r(true);
|
|
};
|
|
menu.No = () => {
|
|
E.showMenu();
|
|
r(false);
|
|
};
|
|
}
|
|
E.showMenu(menu);
|
|
});
|
|
};
|
|
|
|
const bsl = Bangle.showLauncher;
|
|
Bangle.showLauncher = function () {
|
|
Bangle.removeAllListeners("drag");
|
|
if (Bangle.backHandler) clearWatch(Bangle.backHandler);
|
|
delete Bangle.backHandler;
|
|
bsl();
|
|
}; |