Merge pull request #1202 from kyleplo/patch-5

Add Touch Menu
pull/1207/head^2
Gordon Williams 2022-01-05 08:32:16 +00:00 committed by GitHub
commit 98fed5ba0f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 252 additions and 0 deletions

View File

@ -5357,5 +5357,19 @@
{ "name": "diract.app.js", "url": "diract.js" }, { "name": "diract.app.js", "url": "diract.js" },
{ "name": "diract.img", "url": "diract-icon.js", "evaluate": true } { "name": "diract.img", "url": "diract-icon.js", "evaluate": true }
] ]
},
{
"id": "touchmenu",
"name": "TouchMenu",
"version": "0.01",
"description": "Redesigned menu that uses the full touchscreen on the Bangle.js 2",
"screenshots": [{"url":"touchmenu.gif"}],
"icon": "touchmenu.png",
"type": "bootloader",
"tags": "tool",
"supports": ["BANGLEJS2"],
"storage": [
{"name":"touchmenu.boot.js","url":"touchmenu.js"},
]
} }
] ]

1
apps/touchmenu/ChangeLog Normal file
View File

@ -0,0 +1 @@
0.01: App launched

40
apps/touchmenu/README.md Normal file
View File

@ -0,0 +1,40 @@
# TouchMenu
A redesign of the built-in `E.showMenu()` to take advantage of the full touch screen on the Bangle.js 2.
![screenshot](touchmenu.gif)
## Features
- All of the features of the built-in `E.showMenu()`
- Icon support for menu items:
```javascript
menu.items[0].icon = Graphics.createImage(...);
```
- Custom accent colors:
```javascript
E.showMenu({
"": {
cAB: g.theme.bg2, // Accent background
cAF: g.theme.fg2 // Accent foreground
}
})
```
- Automatic back button detection - name a button `< Back` and it will be given a special position and icon
## Controls
- Scroll through the options
- Tap on an option to select it
- Tap on a button again to use it
- Tap on a selected Boolean to toggle it
- Tap on a selected number to change - tap the right side of the screen to decrease, left side to increase
- If detected, tap on the back button in the upper left to go back
## Requests
Contact information is on my website: [kyleplo](https://kyleplo.com)
## Creator
[kyleplo](https://kyleplo.com)

View File

@ -0,0 +1,197 @@
E.showMenu = function(items) {
const gw = g.getWidth();
const gh = g.getHeight();
Bangle.removeAllListeners("drag");
if(!items){
delete m;
g.clearRect(0, 30, gw, gh - 30);
return false;
}
var loc = require("locale");
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,
draw: () => {
g.reset().setFont('12x20');
m.info.predraw(g);
g.setColor(m.info.cB).fillRect(0, 50, gw, gh - 30).setColor(m.info.cF);
m.items.forEach((e, i) => {
const s = (i * 48) - m.scroll + 50;
if(s < 30 || s > gh - 74){
return false;
}
if(i == m.selected){
g.setColor(m.info.cHB).fillRect(0, s, gw, Math.min(s + 48, gh - 30)).setColor(m.info.cHF);
}else{
g.setColor(m.info.cF);
}
g.drawString(e.title, (e.icon ? 30 : 10), s + 5);
if(e.icon){
g.drawImage(e.icon, 5, s + 5);
}
if(e.type && s < gh - 72){
if(e.format){
g.setFontAlign(1, -1, 0).drawString(e.format(e.value), gw - 10, s + 25).setFontAlign(-1, -1, 0);
}else{
g.setFontAlign(1, -1, 0).drawString(e.value, gw - 10, s + 25).setFontAlign(-1, -1, 0);
}
}
});
g.setColor(m.info.cAB).fillRect(0, 30, gw, 50);
g.setColor(m.info.cAF).drawString(m.info.title, (m.back ? 30 : 10), 32);
if(m.back){
g.drawLine(5, 40, 20, 40);
g.drawLine(5, 40, 15, 33);
g.drawLine(5, 40, 15, 47);
}
m.info.preflip(g, m.scroll > 0, m.scroll < (m.items.length - 1) * 48);
},
select: (x, y) => {
if(m.selected == -1 || m.selected !== Math.max(Math.min(Math.floor((y + m.scroll - 50) / 48), m.items.length - 1), 0)){
if(y){
if(y < 50 || y > gh - 30){
return false;
}else{
m.selected = Math.max(Math.min(Math.floor((y + m.scroll - 50) / 48), m.items.length - 1), 0);
}
}else{
m.selected = Math.floor(m.scroll / 48);
}
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 < (gw / 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 * 48);
m.scroll = Math.min(Math.max(m.scroll, 0), (m.items.length - 1) * 48);
m.selected = Math.max(Math.min(Math.floor((m.scroll - 50) / 48), m.items.length - 1), 0);
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();
Bangle.on("drag", d => {
if(!d.b){
return false;
}
if(d.dx == 0 && d.dy == 0){
if(d.x < 30 && d.y < 50){
m.back();
return false;
}
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) * 48);
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);
});
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 602 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB