From 28733a400eabb03c8ca1c7f33f7893440a0d1b61 Mon Sep 17 00:00:00 2001 From: Ben Whittaker Date: Mon, 13 Sep 2021 11:14:12 -0400 Subject: [PATCH] Add vector clock --- apps.json | 13 +++++ apps/vectorclock/Changelog | 1 + apps/vectorclock/app-icon.js | 1 + apps/vectorclock/app.js | 93 +++++++++++++++++++++++++++++++++++ apps/vectorclock/app.png | Bin 0 -> 12820 bytes 5 files changed, 108 insertions(+) create mode 100644 apps/vectorclock/Changelog create mode 100644 apps/vectorclock/app-icon.js create mode 100644 apps/vectorclock/app.js create mode 100644 apps/vectorclock/app.png diff --git a/apps.json b/apps.json index 560d6505b..7632d9a47 100644 --- a/apps.json +++ b/apps.json @@ -3442,5 +3442,18 @@ "data": [ {"name":"app.json"} ] +}, +{ "id": "vectorclock", + "name": "Vector Clock", + "icon": "app.png", + "version": "0.01", + "description": "A digital clock that uses the built-in vector font.", + "tags": "clock", + "type": "clock", + "allow_emulator": true, + "storage": [ + {"name":"vectorclock.app.js","url":"app.js"}, + {"name":"vectorclock.img","url":"app-icon.js","evaluate":true} + ] } ] diff --git a/apps/vectorclock/Changelog b/apps/vectorclock/Changelog new file mode 100644 index 000000000..a483abca9 --- /dev/null +++ b/apps/vectorclock/Changelog @@ -0,0 +1 @@ +0.1: New watch face \ No newline at end of file diff --git a/apps/vectorclock/app-icon.js b/apps/vectorclock/app-icon.js new file mode 100644 index 000000000..14933670b --- /dev/null +++ b/apps/vectorclock/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwkEIf4AxgMhgUAiIHCmYKCmcgBAUCmQDEgUzkcg+QJBl//AYfzDgX///wAYcCmMzmQXC+c/AYM/kU/iEAgfzkfyAYcCAYM/HIUwC4QxCkEhgcwEYIDDgUwgcSC4QsBLQf/iATEAYcBiB3FC4cvKAIvINAMxgSGDC4UT/4ICC5EDkcjI40/mIHCgaNBC4IDCBAMDmUiXwU/mcQ/8zAYMyQ4M/RYQDBC4yxBIgIDDE4M//5FBAYasBifxf5QA/AC0iAALFDA4ICBgMhC5SBB//wA4gCBUoIXLXYKaBAAUjC54KJC6Ejmcxe4MAiczC4IJBmEjNwILBL4b5Bl7vCD4IEB+cCNgUP+A3EL4MyC4IkBiE/BoMD+cP+MvCoPygfxI4wXBA4UD+QZBh8wgacB/4ODC5YvC+EfC4JVBiAXLgP/n5JBZgcPSwgXIRYPz+cBQoIXBLwgARgU/c4gAQJYJeDF6TXBAH5OMmUBmcQkcgicxBQMTkBbDBIMCSAcTl8jmcxmXymczBQIECCIQEBkbDBAAUfFgMwgPymUDiUg+EjiUwgUhBIMQC4cCfgIXBeAINBicwC4JBBgY7BgcAC4cfkEDkUx+UAmUjBQPxmZZDBIQXDl//kQBC+UvDQIKBmM//4FCBYP/bX4A/ACIA=")) diff --git a/apps/vectorclock/app.js b/apps/vectorclock/app.js new file mode 100644 index 000000000..b9e5f7bef --- /dev/null +++ b/apps/vectorclock/app.js @@ -0,0 +1,93 @@ +const is12Hour = (require("Storage").readJSON("setting.json",1)||{})["12hour"]; +const locale = require("locale"); + +function padNum(n, l) { + return ("0".repeat(l)+n).substr(-l); +} + +let rects = {}; +let rectsToClear = {}; +let commands = []; + +function pushCommand(command) { + let hash = E.CRC32(E.toJS(arguments)); + if (!delete rectsToClear[hash]) { + commands.push({hash: hash, command: Function.apply.bind(command, null, arguments.slice(1))}); + } +} + +function executeCommands() { + "ram"; + for (let hash in rectsToClear) delete rects[hash]; + for (let r of rectsToClear) if (r) g.clearRect(r.x1, r.y1, r.x2, r.y2); + g.getModified(true); + for (let c of commands) { + c.command(); + rects[c.hash] = g.getModified(true); + } + rectsToClear = Object.assign({}, rects); + commands = []; +} + +function drawVectorText(text, size, x, y, alignX, alignY) { + g.setFont("Vector", size).setFontAlign(alignX, alignY).drawString(text, x, y); +} + +function draw() { + g.reset(); + + let d = new Date(); + let hours = is12Hour ? ((d.getHours() + 11) % 12) + 1 : d.getHours(); + let timeText = `${hours}:${padNum(d.getMinutes(), 2)}`; + let meridian = is12Hour ? ((d.getHours() < 12) ? "AM" : "PM") : ""; + let secondsText = padNum(d.getSeconds(), 2); + let dowText = locale.dow(d); + let dateText = locale.date(d, true); + + g.setFont("Vector", 256); + let timeFontSize = g.getWidth() / ((g.stringWidth(timeText) / 256) + (Math.max(g.stringWidth(meridian), g.stringWidth(secondsText)) / 512 * 9 / 10)); + let dowFontSize = g.getWidth() / (g.stringWidth(dowText) / 256); + let dateFontSize = g.getWidth() / (g.stringWidth(dateText) / 256); + + let timeHeight = g.setFont("Vector", timeFontSize).getFontHeight() * 9 / 10; + let dowHeight = g.setFont("Vector", dowFontSize).getFontHeight(); + let dateHeight = g.setFont("Vector", dateFontSize).getFontHeight(); + + let remainingHeight = g.getHeight() - 24 - timeHeight - dowHeight - dateHeight; + let spacer = remainingHeight / 4; + + let y = 24 + spacer; + + pushCommand(drawVectorText, timeText, timeFontSize, 0, y, -1, -1); + pushCommand(drawVectorText, meridian, timeFontSize*9/20, g.getWidth(), y, 1, -1); + pushCommand(drawVectorText, secondsText, timeFontSize*9/20, g.getWidth(), y + timeHeight, 1, 1); + y += timeHeight + spacer; + + pushCommand(drawVectorText, dowText, dowFontSize, g.getWidth()/2, y, 0, -1); + y += dowHeight + spacer; + + pushCommand(drawVectorText, dateText, dateFontSize, g.getWidth()/2, y, 0, -1); + + executeCommands(); +} + +let timeout; + +function tick() { + draw(); + timeout = setTimeout(tick, 1000 - getTime() % 1 * 1000); +} + +Bangle.on('lcdPower', function(on) { + if (timeout) clearTimeout(timeout); + timeout = null; + if (on) tick(); +}); + +g.clear(); +tick(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +// Show launcher when middle button pressed +setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); diff --git a/apps/vectorclock/app.png b/apps/vectorclock/app.png new file mode 100644 index 0000000000000000000000000000000000000000..00723fce9c09e01ffb7a0371e27fa499a6e106e0 GIT binary patch literal 12820 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 m+ddOl5?RH7iUA*x0sjK3*Kz*WhXSeq0000