mirror of https://github.com/espruino/BangleApps
Swipe Menus initial release
parent
23eb487024
commit
435ad5c730
|
@ -0,0 +1 @@
|
|||
0.01: Inital release.
|
|
@ -0,0 +1,9 @@
|
|||
This first release seems servicable in testing so far.
|
||||
|
||||
To get the standard menu scrolling back, just remove this app from your Bangle.
|
||||
|
||||
TODO:
|
||||
- Maybe have how much of "trailing space" there are after the last entry should be dynamic in size, now it's always 8 pixels which corresponds to if there are a widget field and a menu title present.
|
||||
- I want to change the size of menu entries to be a little bigger vertically.
|
||||
|
||||
<a target="_blank" href="https://icons8.com/icon/18714/drag-list-down">Drag List Down</a> icon by <a target="_blank" href="https://icons8.com">Icons8</a>
|
Binary file not shown.
After Width: | Height: | Size: 279 B |
|
@ -0,0 +1,100 @@
|
|||
E.showScroller = (function(options) {
|
||||
/* options = {
|
||||
h = height
|
||||
c = # of items
|
||||
scroll = initial scroll position
|
||||
scrollMin = minimum scroll amount (can be negative)
|
||||
draw = function(idx, rect)
|
||||
select = function(idx)
|
||||
}
|
||||
|
||||
returns {
|
||||
draw = draw all
|
||||
drawItem(idx) = draw specific item
|
||||
}
|
||||
*/
|
||||
if (!options) return Bangle.setUI(); // remove existing handlers
|
||||
|
||||
var menuShowing = false;
|
||||
var R = Bangle.appRect;
|
||||
var Y = Bangle.appRect.y;
|
||||
var n = Math.ceil(R.h/options.h);
|
||||
var menuScrollMin = 0|options.scrollMin;
|
||||
var menuScrollMax = options.h*options.c - R.h;
|
||||
if (menuScrollMax<menuScrollMin) menuScrollMax=menuScrollMin;
|
||||
|
||||
function idxToY(i) {
|
||||
return i*options.h + R.y - rScroll;
|
||||
}
|
||||
function YtoIdx(y) {
|
||||
return Math.floor((y + rScroll - R.y)/options.h);
|
||||
}
|
||||
|
||||
var s = {
|
||||
scroll : E.clip(0|options.scroll,menuScrollMin,menuScrollMax),
|
||||
draw : () => {
|
||||
g.reset().clearRect(R.x,R.y,R.x2,R.y2);
|
||||
g.setClipRect(R.x,R.y,R.x2,R.y2);
|
||||
var a = YtoIdx(R.y);
|
||||
var b = Math.min(YtoIdx(R.y2),options.c-1);
|
||||
for (var i=a;i<=b;i++)
|
||||
options.draw(i, {x:R.x,y:idxToY(i),w:R.w,h:options.h});
|
||||
g.setClipRect(0,0,g.getWidth()-1,g.getHeight()-1);
|
||||
}, drawItem : i => {
|
||||
var y = idxToY(i);
|
||||
g.reset().setClipRect(R.x,y,R.x2,y+options.h);
|
||||
options.draw(i, {x:R.x,y:y,w:R.w,h:options.h});
|
||||
g.setClipRect(0,0,g.getWidth()-1,g.getHeight()-1);
|
||||
}};
|
||||
var rScroll = s.scroll&~1; // rendered menu scroll (we only shift by 2 because of dither)
|
||||
s.draw(); // draw the full scroller
|
||||
g.flip(); // force an update now to make this snappier
|
||||
Bangle.setUI({
|
||||
mode : "custom",
|
||||
back : options.back,
|
||||
swipe : (hor,ver)=>{
|
||||
pixels = 120;
|
||||
var dy = ver*pixels;
|
||||
if (s.scroll - dy > menuScrollMax)
|
||||
dy = s.scroll - menuScrollMax-8; // Makes it so the last 'page' has the same position as previous pages. This should be done dynamically (change the static 8 to be a variable) so the offset is correct even when no widget field or title field is present.
|
||||
if (s.scroll - dy < menuScrollMin)
|
||||
dy = s.scroll - menuScrollMin;
|
||||
s.scroll -= dy;
|
||||
var oldScroll = rScroll;
|
||||
rScroll = s.scroll &~1;
|
||||
dy = oldScroll-rScroll;
|
||||
if (!dy || options.c<=3) return; //options.c<=3 should maybe be dynamic, so 3 would be replaced by a variable dependent on R=Bangle.appRect. It's here so we don't try to scroll if all entries fit in the app rectangle.
|
||||
g.reset().setClipRect(R.x,R.y,R.x2,R.y2);
|
||||
g.scroll(0,dy);
|
||||
var d = ver*pixels;
|
||||
if (d < 0) {
|
||||
g.setClipRect(R.x,R.y2-(1-d),R.x2,R.y2);
|
||||
let i = YtoIdx(R.y2-(1-d));
|
||||
let y = idxToY(i);
|
||||
//print(i, options.c, options.c-i); //debugging info
|
||||
while (y < R.y2 - (options.h*((options.c-i)<=0)) ) { //- (options.h*((options.c-i)<=0)) makes sure we don't go beyond the menu entries in the menu object "options". This has to do with "dy = s.scroll - menuScrollMax-8" above.
|
||||
options.draw(i, {x:R.x,y:y,w:R.w,h:options.h});
|
||||
i++;
|
||||
y += options.h;
|
||||
}
|
||||
} else { // d>0
|
||||
g.setClipRect(R.x,R.y,R.x2,R.y+d);
|
||||
let i = YtoIdx(R.y+d);
|
||||
let y = idxToY(i);
|
||||
//print(i, options.c, options.c-i); //debugging info
|
||||
while (y > R.y-options.h) {
|
||||
options.draw(i, {x:R.x,y:y,w:R.w,h:options.h});
|
||||
y -= options.h;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
g.setClipRect(0,0,g.getWidth()-1,g.getHeight()-1);
|
||||
}, touch : (_,e)=>{
|
||||
if (e.y<R.y-4) return;
|
||||
var i = YtoIdx(e.y);
|
||||
if ((menuScrollMin<0 || i>=0) && i<options.c)
|
||||
options.select(i);
|
||||
}
|
||||
});
|
||||
return s;
|
||||
});
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"id": "swscroll",
|
||||
"name": "Swipe menus",
|
||||
"version": "0.01",
|
||||
"description": "Replace built in E.showScroller to act on swipe instead of drag. Navigate menus in discrete steps instead of a continuous motion.",
|
||||
"readme": "README.md",
|
||||
"icon": "app.png",
|
||||
"type": "bootloader",
|
||||
"tags": "system",
|
||||
"supports": ["BANGLEJS2"],
|
||||
"storage": [
|
||||
{"name":"swscroll.boot.js","url":"boot.js"}
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue