diff --git a/apps/cc_clock24/ChangeLog b/apps/cc_clock24/ChangeLog new file mode 100644 index 000000000..531e6c047 --- /dev/null +++ b/apps/cc_clock24/ChangeLog @@ -0,0 +1 @@ +0.01: Copied from andark (V0.08) diff --git a/apps/cc_clock24/README.md b/apps/cc_clock24/README.md new file mode 100644 index 000000000..84b1fa874 --- /dev/null +++ b/apps/cc_clock24/README.md @@ -0,0 +1,16 @@ +# Analog Clock With 24 hour hands + +## Features + +* second hand (only on unlocked screen) +* date +* battery percentage (showing charge status with color) +* turned off or swipeable widgets (choose in settings) + +![logo](cc_clock24_screen.png) + +## Settings + +* whether to load widgets, or not; if widgets are loaded, they are swipeable from the top; if not, NO ACTIONS of widgets are available +* date and battery can be printed both below hands (as if hands were physical) and above (more readable) +* hour hand can be made slighly shorter to improve readability when minute hand is behind a number diff --git a/apps/cc_clock24/app.js b/apps/cc_clock24/app.js new file mode 100644 index 000000000..9049dfdbd --- /dev/null +++ b/apps/cc_clock24/app.js @@ -0,0 +1,178 @@ +{ +const defaultSettings = { + loadWidgets : false, + textAboveHands : false, + shortHrHand : false +}; +const settings = Object.assign(defaultSettings, require('Storage').readJSON('cc_clock24.json',1)||{}); + +const c={"x":g.getWidth()/2,"y":g.getHeight()/2}; + +const zahlpos=(function() { + let z=[]; + let sk=1; + for(let i=-10;i<50;i+=5){ + let win=i*2*Math.PI/60; + let xsk =c.x+2+Math.cos(win)*(c.x-10), + ysk =c.y+2+Math.sin(win)*(c.x-10); + if(sk==3){xsk-=10;} + if(sk==6){ysk-=10;} + if(sk==9){xsk+=10;} + if(sk==12){ysk+=10;} + if(sk==10){xsk+=3;} + z.push([sk,xsk,ysk]); + sk+=1; + } + return z; +})(); + +const zeiger = function(len,dia,tim) { + const x=c.x+ Math.cos(tim)*len/2, + y=c.y + Math.sin(tim)*len/2, + d={"d":3,"x":dia/2*Math.cos(tim+Math.PI/2),"y":dia/2*Math.sin(tim+Math.PI/2)}, + pol=[c.x-d.x,c.y-d.y,c.x+d.x,c.y+d.y,x+d.x,y+d.y,x-d.x,y-d.y]; + return pol; +}; + +const drawHands = function(d) { + let m=d.getMinutes(), h=d.getHours(), s=d.getSeconds(); + g.setColor(1,1,1); + + if(h>12){ + h=h-12; + } + //calculates the position of the minute, second and hour hand + h=2*Math.PI/12*(h+m/60)-Math.PI/2; + //more accurate + //m=2*Math.PI/60*(m+s/60)-Math.PI/2; + m=2*Math.PI/60*(m)-Math.PI/2; + + s=2*Math.PI/60*s-Math.PI/2; + //g.setColor(1,0,0); + const hz = zeiger(settings.shortHrHand?88:100,5,h); + g.fillPoly(hz,true); + //g.setColor(1,1,1); + const minz = zeiger(150,5,m); + g.fillPoly(minz,true); + if (unlock){ + const sekz = zeiger(150,2,s); + g.fillPoly(sekz,true); + } + g.fillCircle(c.x,c.y,4); +}; + +const drawText = function(d) { + g.setFont("Vector",10); + g.setBgColor(0,0,0); + g.setColor(1,1,1); + const dateStr = require("locale").date(d); + g.drawString(dateStr, c.x, c.y+20, true); + const batStr = Math.round(E.getBattery()/5)*5+"%"; + if (Bangle.isCharging()) { + g.setBgColor(1,0,0); + } + g.drawString(batStr, c.x, c.y+40, true); +}; + +const drawNumbers = function() { + //draws the numbers on the screen + g.setFont("Vector",20); + g.setColor(1,1,1); + g.setBgColor(0,0,0); + for(let i = 0;i<12;i++){ + g.drawString(zahlpos[i][0],zahlpos[i][1],zahlpos[i][2],true); + } +}; + +let drawTimeout; +let queueMillis = 1000; +let unlock = true; + +const updateState = function() { + if (Bangle.isLCDOn()) { + if (!Bangle.isLocked()) { + queueMillis = 1000; + unlock = true; + } else { + queueMillis = 60000; + unlock = false; + } + draw(); + } else { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + } +}; + +const queueDraw = function() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, queueMillis - (Date.now() % queueMillis)); +}; + +const draw = function() { + // draw black rectangle in the middle to clear screen from scale and hands + g.setColor(0,0,0); + g.fillRect(10,10,2*c.x-10,2*c.x-10); + // prepare for drawing the text + g.setFontAlign(0,0); + // do drawing + drawNumbers(); + const d=new Date(); + if (settings.textAboveHands) { + drawHands(d); drawText(d); + } else { + drawText(d); drawHands(d); + } + queueDraw(); +}; + +//draws the scale once the app is startet +const drawScale = function() { + // clear the screen + g.setBgColor(0,0,0); + g.clear(); + // draw the ticks of the scale + for(let i=-14;i<47;i++){ + const win=i*2*Math.PI/60; + let d=2; + if(i%5==0){d=5;} + g.fillPoly(zeiger(300,d,win),true); + g.setColor(0,0,0); + g.fillRect(10,10,2*c.x-10,2*c.x-10); + g.setColor(1,1,1); + } +}; + +//// main running sequence //// + +// Show launcher when middle button pressed, and widgets that we're clock +Bangle.setUI({ + mode: "clock", + remove: function() { + Bangle.removeListener('lcdPower', updateState); + Bangle.removeListener('lock', updateState); + Bangle.removeListener('charging', draw); + // We clear drawTimout after removing all listeners, because they can add one again + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + require("widget_utils").show(); + } +}); +// Load widgets if needed, and make them show swipeable +if (settings.loadWidgets) { + Bangle.loadWidgets(); + require("widget_utils").swipeOn(); +} else if (global.WIDGETS) require("widget_utils").hide(); + +// Stop updates when LCD is off, restart when on +Bangle.on('lcdPower', updateState); +Bangle.on('lock', updateState); +Bangle.on('charging', draw); // Immediately redraw when charger (dis)connected + +updateState(); +drawScale(); +draw(); +} diff --git a/apps/cc_clock24/app_icon.js b/apps/cc_clock24/app_icon.js new file mode 100644 index 000000000..b213fe5c8 --- /dev/null +++ b/apps/cc_clock24/app_icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwgIEBoUAiAKCgUCBQUEColEAYUQhAmKCwgeCAAcCgEDjwEBkEAg8TBocNgYFDh8GAYMDxkPjEA8EAwkHJgIcBAoPfAoYWCBYYFIgfvAoX4FYRJEAp9gAomYNAOAArPwAogAC4AFiRoIFJLgIFJuADCg//Q4U//4FDj4FEAAV4Aoi0CSxBsCA==")) \ No newline at end of file diff --git a/apps/cc_clock24/cc_clock24_icon.png b/apps/cc_clock24/cc_clock24_icon.png new file mode 100644 index 000000000..cded02071 Binary files /dev/null and b/apps/cc_clock24/cc_clock24_icon.png differ diff --git a/apps/cc_clock24/cc_clock24_screen.png b/apps/cc_clock24/cc_clock24_screen.png new file mode 100644 index 000000000..1f0e5b089 Binary files /dev/null and b/apps/cc_clock24/cc_clock24_screen.png differ diff --git a/apps/cc_clock24/metadata.json b/apps/cc_clock24/metadata.json new file mode 100644 index 000000000..e450893b7 --- /dev/null +++ b/apps/cc_clock24/metadata.json @@ -0,0 +1,18 @@ +{ "id": "cc_clock24", + "name": "CC Clock 24", + "shortName":"CC-Clock24", + "version":"0.01", + "description": "analog clock face with 24 hour pointer", + "icon": "cc_clock24_icon.png", + "type": "clock", + "tags": "clock", + "supports" : ["BANGLEJS2"], + "screenshots": [{"url":"cc_clock24_screen.png"}], + "readme": "README.md", + "storage": [ + {"name":"cc_clock24.app.js","url":"app.js"}, + {"name":"cc_clock24.settings.js","url":"settings.js"}, + {"name":"cc_clock24.img","url":"app_icon.js","evaluate":true} + ], + "data": [{"name":"cc_clock24.json"}] +} diff --git a/apps/cc_clock24/settings.js b/apps/cc_clock24/settings.js new file mode 100644 index 000000000..46401e526 --- /dev/null +++ b/apps/cc_clock24/settings.js @@ -0,0 +1,28 @@ +(function(back) { + const defaultSettings = { + loadWidgets : false, + textAboveHands : false, + shortHrHand : false + } + let settings = Object.assign(defaultSettings, require('Storage').readJSON('cc_clock24.json',1)||{}); + + const save = () => require('Storage').write('cc_clock24.json', settings); + + const appMenu = { + '': {title: 'cc_clock24'}, '< Back': back, + /*LANG*/'Load widgets': { + value : !!settings.loadWidgets, + onchange : v => { settings.loadWidgets=v; save();} + }, + /*LANG*/'Text above hands': { + value : !!settings.textAboveHands, + onchange : v => { settings.textAboveHands=v; save();} + }, + /*LANG*/'Short hour hand': { + value : !!settings.shortHrHand, + onchange : v => { settings.shortHrHand=v; save();} + }, + }; + + E.showMenu(appMenu); +})