Complete rewrite to add animation and loop ( issue #210 )

pull/233/head
Dimitri Gigot 2020-04-05 00:12:04 +00:00
parent 25a59c8743
commit 32dc0d6d7f
3 changed files with 132 additions and 83 deletions

View File

@ -1030,7 +1030,7 @@
"name": "Touch Launcher", "name": "Touch Launcher",
"shortName":"Menu", "shortName":"Menu",
"icon": "app.png", "icon": "app.png",
"version":"0.03", "version":"0.04",
"description": "Touch enable left to right launcher.", "description": "Touch enable left to right launcher.",
"tags": "tool,system,launcher", "tags": "tool,system,launcher",
"type":"launch", "type":"launch",

View File

@ -1,3 +1,4 @@
0.01: New App! 0.01: New App!
0.02: Add swipe support and doucle tap to run application 0.02: Add swipe support and doucle tap to run application
0.03: Close launcher when lcd turn off 0.03: Close launcher when lcd turn off
0.04: Complete rewrite to add animation and loop ( issue #210 )

View File

@ -1,4 +1,6 @@
Bangle.setLCDMode("120x120");
g.clear(); g.clear();
g.flip();
const Storage = require("Storage"); const Storage = require("Storage");
@ -14,99 +16,144 @@ function getApps(){
}); });
} }
const selected = 0; const HEIGHT = g.getHeight();
const apps = getApps(); const WIDTH = g.getWidth();
const HALF = WIDTH/2;
const ANIMATION_SPEED = 0;
const ANIMATION_STEP = 20;
function prev(){ function getPosition(index){
if (selected>=0) { return (index*HALF);
selected--;
}
drawMenu();
} }
function next() { let current_app = 0;
if (selected+1<apps.length) { let target = 0;
selected++; let slideOffset = 0;
}
drawMenu();
}
function run() { const back = {
if(selected < 0) return load(); name: 'BACK',
if (!apps[selected].src) return; back: true
if (Storage.read(apps[selected].src)===undefined) { };
E.showMessage("App Source\nNot found");
setTimeout(drawMenu, 2000);
} else {
E.showMessage("Loading...");
load(apps[selected].src);
}
}
function getCurrentApp(){ const apps = [back].concat(getApps());
return apps[selected]; apps.push(back);
}
function getNextApp(){ function noIcon(x, y, size){
return apps[selected+1]; const half = size/2;
}
function drawFallbackIcon(){
g.setColor(1,1,1); g.setColor(1,1,1);
g.fillRect(72, 40, 168, 136); g.setFontAlign(-0,0);
g.setColor(0,0,0); const fontSize = Math.floor(size / 30 * 2);
g.setFont('6x8', 8); g.setFont('6x8', fontSize);
g.drawString('?', 124, 88); if(fontSize) g.drawString('-?-', x+1.5, y);
g.drawRect(x-half, y-half, x+half, y+half);
} }
function drawArrow(x, y, size, dir){ function drawIcons(offset){
size = size || 10; apps.forEach((app, i) => {
dir = dir || 1; const x = getPosition(i) + HALF - offset;
g.moveTo(x, y).lineTo(x+(size*dir), y-size).lineTo(x+(size*dir),y+size).lineTo(x, y); const y = HALF - (HALF*0.3);//-(HALF*0.7);
} let diff = (x - HALF);
if(diff < 0) diff *=-1;
let size = 30;
if((diff*0.5) < size) size -= (diff*0.5);
else size = 0;
function drawMenu(){ const scale = size / 30;
if(size){
let c = size / 30 * 2;
c = c -1;
if(c < 0) c = 0;
if(selected < 0){ if(app.back){
g.clear(); g.setFont('6x8', 1);
g.setFontAlign(0,0); g.setFontAlign(0, -1);
g.setFont('6x8', 2); g.setColor(c,c,c);
g.drawString('Back', 120, 120); g.drawString('Back', HALF, HALF);
drawArrow(220, 120, 10, -1);
return; return;
} }
// icon
const app = getCurrentApp(); const icon = app.icon ? Storage.read(app.icon) : null;
g.clear(); if(icon){
g.setFontAlign(0,0); try {
g.setFont('6x8', 2); g.drawImage(icon, x-(scale*24), y-(scale*24), { scale: scale });
if(!app) return g.drawString('???', 120, 120); } catch(e){
g.drawString(app.name, 120, 160); noIcon(x, y, size);
if (app.icon) icon = Storage.read(app.icon); }
if (icon) try {g.drawImage(icon, 120-48, 40, { scale: 2 });} catch(e){ drawFallbackIcon(); } }else{
else drawFallbackIcon(); noIcon(x, y, size);
}
//text
g.setFont('6x8', 1); g.setFont('6x8', 1);
g.setFontAlign(0, -1);
g.setColor(c,c,c);
g.drawString(app.name, HALF, HEIGHT - (HALF*0.7));
const type = app.type ? app.type : 'App'; const type = app.type ? app.type : 'App';
const version = app.version ? app.version : '0.00'; const version = app.version ? app.version : '0.00';
const info = type+' v'+version; const info = type+' v'+version;
g.setFontAlign(-1,1); g.setFontAlign(0,1);
g.drawString(info, 20, 220); g.setFont('4x6', 0.25);
g.setColor(c,c,c);
const count = (selected+1)+'/'+apps.length; g.drawString(info, HALF, 110, { scale: scale });
g.setFontAlign(1,1); }
g.drawString(count, 220, 220); });
drawArrow(20, 120, 10, 1);
if(getNextApp()) drawArrow(220, 120, 10, -1);
} }
drawMenu(); function draw(ignoreLoop){
g.clear();
drawIcons(slideOffset);
g.flip();
if(slideOffset == target) return;
if(slideOffset < target) slideOffset+= ANIMATION_STEP;
else if(slideOffset > target) slideOffset -= ANIMATION_STEP;
if(!ignoreLoop) setTimeout(draw, ANIMATION_SPEED);
}
// Physical buttons function animateTo(index){
setWatch(prev, BTN1, {repeat:true}); target = getPosition(index);
setWatch(next, BTN3, {repeat:true}); draw();
}
function goTo(index){
current_app = index;
target = getPosition(index);
slideOffset = target;
draw(true);
}
goTo(1);
function prev(){
if(current_app == 0) goTo(apps.length-1);
current_app -= 1;
if(current_app < 0) current_app = 0;
animateTo(current_app);
}
function next(){
if(current_app == apps.length-1) goTo(0);
current_app += 1;
if(current_app > apps.length-1) current_app = apps.length-1;
animateTo(current_app);
}
function run() {
const app = apps[current_app];
if(app.back) return load();
if (Storage.read(app.src)===undefined) {
E.showMessage("App Source\nNot found");
setTimeout(draw, 2000);
} else {
Bangle.setLCDMode();
g.clear();
g.flip();
E.showMessage("Loading...");
load(app.src);
}
}
setWatch(prev, BTN1, { repeat: true });
setWatch(next, BTN3, { repeat: true });
setWatch(run, BTN2, {repeat:true,edge:"falling"}); setWatch(run, BTN2, {repeat:true,edge:"falling"});
// Screen event // Screen event
@ -129,6 +176,7 @@ Bangle.on('swipe', dir => {
else next(); else next();
}); });
Bangle.on('lcdPower', function(on) { // close launcher when lcd is off
Bangle.on('lcdPower', on => {
if(!on) return load(); if(!on) return load();
}); });