ctrlpad: retab

master
Rob Pilling 2023-08-28 12:17:07 +01:00
parent 9a864c1488
commit db52196fcc
1 changed files with 178 additions and 178 deletions

View File

@ -1,97 +1,97 @@
(() => { (() => {
if(!Bangle.prependListener){ if(!Bangle.prependListener){
type Event<T> = T extends `#on${infer Evt}` ? Evt : never; type Event<T> = T extends `#on${infer Evt}` ? Evt : never;
Bangle.prependListener = function( Bangle.prependListener = function(
evt: Event<keyof BangleEvents>, evt: Event<keyof BangleEvents>,
listener: () => void listener: () => void
){ ){
// move our drag to the start of the event listener array // move our drag to the start of the event listener array
const handlers = (Bangle as BangleEvents)[`#on${evt}`] const handlers = (Bangle as BangleEvents)[`#on${evt}`]
if(!handlers){ if(!handlers){
Bangle.on(evt as any, listener); Bangle.on(evt as any, listener);
}else{ }else{
if(typeof handlers === "function"){ if(typeof handlers === "function"){
// get Bangle to convert to array // get Bangle to convert to array
Bangle.on(evt as any, listener); Bangle.on(evt as any, listener);
} }
// shuffle array // shuffle array
(Bangle as BangleEvents)[`#on${evt}`] = [listener as any].concat( (Bangle as BangleEvents)[`#on${evt}`] = [listener as any].concat(
(handlers as Array<any>).filter((f: unknown) => f !== listener) (handlers as Array<any>).filter((f: unknown) => f !== listener)
); );
} }
}; };
} }
class Overlay { class Overlay {
g2: Graphics; g2: Graphics;
width: number; width: number;
height: number; height: number;
constructor() { constructor() {
// x padding: 10 each side // x padding: 10 each side
// y top: 24, y bottom: 10 // y top: 24, y bottom: 10
this.width = g.getWidth() - 10 * 2; this.width = g.getWidth() - 10 * 2;
this.height = g.getHeight() - 24 - 10; this.height = g.getHeight() - 24 - 10;
this.g2 = Graphics.createArrayBuffer( this.g2 = Graphics.createArrayBuffer(
this.width, this.width,
this.height, this.height,
/*bpp*/1, /*bpp*/1,
{ msb: true } { msb: true }
); );
this.renderG2(); this.renderG2();
} }
setBottom(bottom: number): void { setBottom(bottom: number): void {
const { g2 } = this; const { g2 } = this;
const y = bottom - this.height; const y = bottom - this.height;
Bangle.setLCDOverlay(g2, 10, y - 10); Bangle.setLCDOverlay(g2, 10, y - 10);
} }
hide(): void { hide(): void {
Bangle.setLCDOverlay(); Bangle.setLCDOverlay();
} }
renderG2(): void { renderG2(): void {
const g = this.g2; const g = this.g2;
g g
.reset() .reset()
.clearRect(0, 0, this.width, this.height) .clearRect(0, 0, this.width, this.height)
.drawRect(0, 0, this.width - 1, this.height - 1) .drawRect(0, 0, this.width - 1, this.height - 1)
.drawRect(1, 1, this.width - 2, this.height - 2); .drawRect(1, 1, this.width - 2, this.height - 2);
const centreY = this.height / 2; const centreY = this.height / 2;
const circleGapY = 30; const circleGapY = 30;
g g
.setFontAlign(0, 0) .setFontAlign(0, 0)
.setFont("Vector:20"); .setFont("Vector:20");
this.drawCtrl(this.width / 4 - 10, centreY - circleGapY, "<"); this.drawCtrl(this.width / 4 - 10, centreY - circleGapY, "<");
this.drawCtrl(this.width / 2, centreY - circleGapY, "@"); this.drawCtrl(this.width / 2, centreY - circleGapY, "@");
this.drawCtrl(this.width * 3/4 + 10, centreY - circleGapY, ">"); this.drawCtrl(this.width * 3/4 + 10, centreY - circleGapY, ">");
this.drawCtrl(this.width / 3, centreY + circleGapY, "-"); this.drawCtrl(this.width / 3, centreY + circleGapY, "-");
this.drawCtrl(this.width * 2/3, centreY + circleGapY, "+"); this.drawCtrl(this.width * 2/3, centreY + circleGapY, "+");
} }
drawCtrl(x: number, y: number, label: string): void { drawCtrl(x: number, y: number, label: string): void {
const g = this.g2; const g = this.g2;
g g
.setColor("#fff") .setColor("#fff")
.fillCircle(x, y, 23) .fillCircle(x, y, 23)
.setColor("#000") .setColor("#000")
.drawString(label, x, y); .drawString(label, x, y);
} }
} }
const settings = require("Storage").readJSON("setting.json", true) as Settings || ({ HID: false } as Settings); const settings = require("Storage").readJSON("setting.json", true) as Settings || ({ HID: false } as Settings);
if (settings.HID !== "kbmedia") { if (settings.HID !== "kbmedia") {
@ -110,114 +110,114 @@
} }
let state = State.NoConn; let state = State.NoConn;
let startY = 0; let startY = 0;
let startedUpDrag = false; let startedUpDrag = false;
let upDragAnim: IntervalId | undefined; let upDragAnim: IntervalId | undefined;
let overlay: Overlay | undefined; let overlay: Overlay | undefined;
let touchDown = false; let touchDown = false;
const onDrag = (e => { const onDrag = (e => {
const dragDistance = 30; const dragDistance = 30;
if (e.b === 0) touchDown = startedUpDrag = false; if (e.b === 0) touchDown = startedUpDrag = false;
switch (state) { switch (state) {
case State.NoConn: case State.NoConn:
break; break;
case State.IgnoreCurrent: case State.IgnoreCurrent:
if(e.b === 0){ if(e.b === 0){
state = State.Idle; state = State.Idle;
overlay = undefined; overlay = undefined;
} }
break; break;
case State.Idle: case State.Idle:
if(e.b && !touchDown){ // no need to check Bangle.CLKINFO_FOCUS if(e.b && !touchDown){ // no need to check Bangle.CLKINFO_FOCUS
if(e.y <= 40){ if(e.y <= 40){
state = State.TopDrag state = State.TopDrag
startY = e.y; startY = e.y;
console.log(" topdrag detected, starting @ " + startY); console.log(" topdrag detected, starting @ " + startY);
}else{ }else{
console.log(" ignoring this drag (too low @ " + e.y + ")"); console.log(" ignoring this drag (too low @ " + e.y + ")");
state = State.IgnoreCurrent; state = State.IgnoreCurrent;
overlay = undefined overlay = undefined
} }
} }
break; break;
case State.TopDrag: case State.TopDrag:
if(e.b === 0){ if(e.b === 0){
console.log("topdrag stopped, distance: " + (e.y - startY)); console.log("topdrag stopped, distance: " + (e.y - startY));
if(e.y > startY + dragDistance){ if(e.y > startY + dragDistance){
console.log("activating"); console.log("activating");
activate(); activate();
break; break;
}
console.log("returning to idle");
state = State.Idle;
overlay?.hide();
overlay = undefined;
}else{
// partial drag, show UI feedback:
const dragOffset = 32;
if (!overlay) overlay = new Overlay();
overlay.setBottom(e.y - dragOffset);
} }
break; console.log("returning to idle");
state = State.Idle;
overlay?.hide();
overlay = undefined;
}else{
// partial drag, show UI feedback:
const dragOffset = 32;
if (!overlay) overlay = new Overlay();
overlay.setBottom(e.y - dragOffset);
}
break;
case State.Active: case State.Active:
console.log("stolen drag handling, do whatever here"); console.log("stolen drag handling, do whatever here");
E.stopEventPropagation?.(); E.stopEventPropagation?.();
if(e.b){ if(e.b){
if(!touchDown){ if(!touchDown){
startY = e.y; startY = e.y;
}else if(startY){ }else if(startY){
const dist = Math.max(0, startY - e.y); const dist = Math.max(0, startY - e.y);
if (startedUpDrag || (startedUpDrag = dist > 10)) // ignore small drags if (startedUpDrag || (startedUpDrag = dist > 10)) // ignore small drags
overlay!.setBottom(g.getHeight() - dist); overlay!.setBottom(g.getHeight() - dist);
} }
}else if(e.b === 0 && startY > dragDistance){ }else if(e.b === 0 && startY > dragDistance){
let bottom = g.getHeight() - Math.max(0, startY - e.y); let bottom = g.getHeight() - Math.max(0, startY - e.y);
if (upDragAnim) clearInterval(upDragAnim); if (upDragAnim) clearInterval(upDragAnim);
upDragAnim = setInterval(() => { upDragAnim = setInterval(() => {
if (!overlay || bottom <= 0) { if (!overlay || bottom <= 0) {
clearInterval(upDragAnim!); clearInterval(upDragAnim!);
upDragAnim = undefined; upDragAnim = undefined;
overlay?.hide(); overlay?.hide();
overlay = undefined; overlay = undefined;
return; return;
} }
overlay?.setBottom(bottom) overlay?.setBottom(bottom)
bottom -= 10; bottom -= 10;
}, 50) }, 50)
deactivate(); deactivate();
} }
break; break;
} }
if(e.b) touchDown = true; if(e.b) touchDown = true;
}) satisfies DragCallback; }) satisfies DragCallback;
const onTouch = ((_btn, _xy) => { const onTouch = ((_btn, _xy) => {
// TODO: button presses // TODO: button presses
}) satisfies TouchCallback; }) satisfies TouchCallback;
const activate = () => { const activate = () => {
state = State.Active; state = State.Active;
startY = 0; startY = 0;
Bangle.prependListener("touch", onTouch); Bangle.prependListener("touch", onTouch);
Bangle.buzz(20); Bangle.buzz(20);
overlay!.setBottom(g.getHeight()); overlay!.setBottom(g.getHeight());
}; };
const deactivate = () => { const deactivate = () => {
Bangle.removeListener("touch", onTouch); Bangle.removeListener("touch", onTouch);
state = State.Idle; state = State.Idle;
}; };
Bangle.prependListener("drag", onDrag); Bangle.prependListener("drag", onDrag);
const redraw = () => setTimeout(Bangle.drawWidgets, 10); const redraw = () => setTimeout(Bangle.drawWidgets, 10);
@ -229,10 +229,10 @@
if(this.width === 0) return; if(this.width === 0) return;
g.drawImage( g.drawImage(
state === State.Active state === State.Active
? require("heatshrink").decompress(atob("jEYxH+AEfH44XXAAYXXDKIXZDYp3pC/6KHUMwWHC/4XvUy4YGdqoA/AFoA==")) ? require("heatshrink").decompress(atob("jEYxH+AEfH44XXAAYXXDKIXZDYp3pC/6KHUMwWHC/4XvUy4YGdqoA/AFoA=="))
: require("heatshrink").decompress(atob("jEYxH+AEcdjoXXAAYXXDKIXZDYp3pC/6KHUMwWHC/4XvUy4YGdqoA/AFoA==")), : require("heatshrink").decompress(atob("jEYxH+AEcdjoXXAAYXXDKIXZDYp3pC/6KHUMwWHC/4XvUy4YGdqoA/AFoA==")),
this.x! + 2, this.x! + 2,
this.y! + 2 this.y! + 2
); );
}, },
width: connected ? 24 : 0, width: connected ? 24 : 0,
@ -255,25 +255,25 @@
}); });
//const DEBUG = true; //const DEBUG = true;
/* /*
const sendHid = (code: number) => { const sendHid = (code: number) => {
//if(DEBUG) return; //if(DEBUG) return;
try{ try{
NRF.sendHIDReport( NRF.sendHIDReport(
[1, code], [1, code],
() => NRF.sendHIDReport([1, 0]), () => NRF.sendHIDReport([1, 0]),
); );
}catch(e){ }catch(e){
console.log("sendHIDReport:", e); console.log("sendHIDReport:", e);
} }
}; };
const hid = { const hid = {
next: () => sendHid(0x01), next: () => sendHid(0x01),
prev: () => sendHid(0x02), prev: () => sendHid(0x02),
toggle: () => sendHid(0x10), toggle: () => sendHid(0x10),
up: () => sendHid(0x40), up: () => sendHid(0x40),
down: () => sendHid(0x80), down: () => sendHid(0x80),
}; };
*/ */
})() })()