2021-12-29 06:04:25 +00:00
|
|
|
let ScreenWidth = g.getWidth(), CenterX = ScreenWidth/2;
|
|
|
|
let ScreenHeight = g.getHeight(), CenterY = ScreenHeight/2;
|
|
|
|
|
|
|
|
let outerRadius = Math.min(CenterX,CenterY) * 0.9;
|
|
|
|
|
2022-09-06 18:29:56 +00:00
|
|
|
Bangle.setUI('clock');
|
|
|
|
|
2021-12-29 06:04:25 +00:00
|
|
|
Bangle.loadWidgets();
|
|
|
|
|
|
|
|
/**** updateClockFaceSize ****/
|
|
|
|
|
|
|
|
function updateClockFaceSize () {
|
|
|
|
CenterX = ScreenWidth/2;
|
|
|
|
CenterY = ScreenHeight/2;
|
|
|
|
|
|
|
|
outerRadius = Math.min(CenterX,CenterY) * 0.9;
|
|
|
|
|
|
|
|
if (global.WIDGETS == null) { return; }
|
|
|
|
|
|
|
|
let WidgetLayouts = {
|
|
|
|
tl:{ x:0, y:0, Direction:0 },
|
|
|
|
tr:{ x:ScreenWidth-1, y:0, Direction:1 },
|
|
|
|
bl:{ x:0, y:ScreenHeight-24, Direction:0 },
|
|
|
|
br:{ x:ScreenWidth-1, y:ScreenHeight-24, Direction:1 }
|
|
|
|
};
|
|
|
|
|
|
|
|
for (let Widget of WIDGETS) {
|
|
|
|
let WidgetLayout = WidgetLayouts[Widget.area]; // reference, not copy!
|
|
|
|
if (WidgetLayout == null) { continue; }
|
|
|
|
|
|
|
|
Widget.x = WidgetLayout.x - WidgetLayout.Direction * Widget.width;
|
|
|
|
Widget.y = WidgetLayout.y;
|
|
|
|
|
|
|
|
WidgetLayout.x += Widget.width * (1-2*WidgetLayout.Direction);
|
|
|
|
}
|
|
|
|
|
|
|
|
let x,y, dx,dy;
|
|
|
|
let cx = CenterX, cy = CenterY, r = outerRadius, r2 = r*r;
|
|
|
|
|
|
|
|
x = WidgetLayouts.tl.x; y = WidgetLayouts.tl.y+24; dx = x - cx; dy = y - cy;
|
|
|
|
if (dx*dx + dy*dy < r2) {
|
|
|
|
cy = CenterY + 12; dy = y - cy; r2 = dx*dx + dy*dy; r = Math.sqrt(r2);
|
|
|
|
}
|
|
|
|
|
|
|
|
x = WidgetLayouts.tr.x; y = WidgetLayouts.tr.y+24; dx = x - cx; dy = y - cy;
|
|
|
|
if (dx*dx + dy*dy < r2) {
|
|
|
|
cy = CenterY + 12; dy = y - cy; r2 = dx*dx + dy*dy; r = Math.sqrt(r2);
|
|
|
|
}
|
|
|
|
|
|
|
|
x = WidgetLayouts.bl.x; y = WidgetLayouts.bl.y; dx = x - cx; dy = y - cy;
|
|
|
|
if (dx*dx + dy*dy < r2) {
|
|
|
|
cy = CenterY - 12; dy = y - cy; r2 = dx*dx + dy*dy; r = Math.sqrt(r2);
|
|
|
|
}
|
|
|
|
|
|
|
|
x = WidgetLayouts.br.x; y = WidgetLayouts.br.y; dx = x - cx; dy = y - cy;
|
|
|
|
if (dx*dx + dy*dy < r2) {
|
|
|
|
cy = CenterY - 12; dy = y - cy; r2 = dx*dx + dy*dy; r = Math.sqrt(r2);
|
|
|
|
}
|
|
|
|
|
|
|
|
CenterX = cx; CenterY = cy; outerRadius = r * 0.9;
|
|
|
|
}
|
|
|
|
|
|
|
|
updateClockFaceSize();
|
|
|
|
|
|
|
|
/**** custom version of Bangle.drawWidgets (does not clear the widget areas) ****/
|
|
|
|
|
|
|
|
Bangle.drawWidgets = function () {
|
|
|
|
var w = g.getWidth(), h = g.getHeight();
|
|
|
|
|
|
|
|
var pos = {
|
|
|
|
tl:{x:0, y:0, r:0, c:0}, // if r==1, we're right->left
|
|
|
|
tr:{x:w-1, y:0, r:1, c:0},
|
|
|
|
bl:{x:0, y:h-24, r:0, c:0},
|
|
|
|
br:{x:w-1, y:h-24, r:1, c:0}
|
|
|
|
};
|
|
|
|
|
|
|
|
if (global.WIDGETS) {
|
|
|
|
for (var wd of WIDGETS) {
|
|
|
|
var p = pos[wd.area];
|
|
|
|
if (!p) continue;
|
|
|
|
|
|
|
|
wd.x = p.x - p.r*wd.width;
|
|
|
|
wd.y = p.y;
|
|
|
|
|
|
|
|
p.x += wd.width*(1-2*p.r);
|
|
|
|
p.c++;
|
|
|
|
}
|
|
|
|
|
2021-12-29 07:59:04 +00:00
|
|
|
g.reset(); // also loads the current theme
|
2021-12-29 06:04:25 +00:00
|
|
|
|
|
|
|
if (pos.tl.c || pos.tr.c) {
|
|
|
|
g.setClipRect(0,h-24,w-1,h-1);
|
2021-12-29 07:59:04 +00:00
|
|
|
g.reset(); // also (re)loads the current theme
|
2021-12-29 06:04:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (pos.bl.c || pos.br.c) {
|
|
|
|
g.setClipRect(0,h-24,w-1,h-1);
|
2021-12-29 07:59:04 +00:00
|
|
|
g.reset(); // also (re)loads the current theme
|
2021-12-29 06:04:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
for (wd of WIDGETS) {
|
|
|
|
g.clearRect(wd.x,wd.y, wd.x+wd.width-1,23);
|
|
|
|
wd.draw(wd);
|
|
|
|
}
|
|
|
|
} catch (e) { print(e); }
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let innerRadius = Math.min(CenterX,CenterY) * 0.8 - 14;
|
|
|
|
|
|
|
|
let HourHandLength = outerRadius * 0.5;
|
|
|
|
let HourHandWidth = 2*3, halfHourHandWidth = HourHandWidth/2;
|
|
|
|
|
|
|
|
let MinuteHandLength = outerRadius * 0.7;
|
|
|
|
let MinuteHandWidth = 2*2, halfMinuteHandWidth = MinuteHandWidth/2;
|
|
|
|
|
|
|
|
let SecondHandLength = outerRadius * 0.9;
|
|
|
|
let SecondHandOffset = 6;
|
|
|
|
|
|
|
|
let twoPi = 2*Math.PI;
|
|
|
|
let Pi = Math.PI;
|
|
|
|
let halfPi = Math.PI/2;
|
|
|
|
|
|
|
|
let sin = Math.sin, cos = Math.cos;
|
|
|
|
|
|
|
|
let HourHandPolygon = [
|
|
|
|
-halfHourHandWidth,halfHourHandWidth,
|
|
|
|
-halfHourHandWidth,halfHourHandWidth-HourHandLength,
|
|
|
|
halfHourHandWidth,halfHourHandWidth-HourHandLength,
|
|
|
|
halfHourHandWidth,halfHourHandWidth,
|
|
|
|
];
|
|
|
|
|
|
|
|
let MinuteHandPolygon = [
|
|
|
|
-halfMinuteHandWidth,halfMinuteHandWidth,
|
|
|
|
-halfMinuteHandWidth,halfMinuteHandWidth-MinuteHandLength,
|
|
|
|
halfMinuteHandWidth,halfMinuteHandWidth-MinuteHandLength,
|
|
|
|
halfMinuteHandWidth,halfMinuteHandWidth,
|
|
|
|
];
|
|
|
|
|
|
|
|
/**** drawClockFace ****/
|
|
|
|
|
|
|
|
function drawClockFace () {
|
|
|
|
for (let i = 0; i < 60; i++) {
|
|
|
|
let Phi = i * twoPi/60;
|
|
|
|
|
|
|
|
let x = CenterX + outerRadius * sin(Phi);
|
|
|
|
let y = CenterY - outerRadius * cos(Phi);
|
|
|
|
|
|
|
|
let Color = E.HSBtoRGB(i/60,1,1, true);
|
|
|
|
g.setColor(Color[0]/255,Color[1]/255,Color[2]/255);
|
|
|
|
|
|
|
|
g.fillCircle(x,y, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
g.setFont('Vector', 20);
|
|
|
|
g.setFontAlign(0,0);
|
|
|
|
|
|
|
|
for (let i = 0; i < 12; i++) {
|
|
|
|
let Phi = i * twoPi/12;
|
|
|
|
|
|
|
|
let Radius = innerRadius;
|
|
|
|
if (i >= 10) { Radius -= 4; }
|
|
|
|
|
|
|
|
let x = CenterX + Radius * sin(Phi);
|
|
|
|
let y = CenterY - Radius * cos(Phi);
|
|
|
|
|
|
|
|
let Color = E.HSBtoRGB(i/12,1,1, true);
|
|
|
|
g.setColor(Color[0]/255,Color[1]/255,Color[2]/255);
|
|
|
|
|
|
|
|
g.drawString(i == 0 ? '12' : '' + i, x,y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**** transforme polygon ****/
|
|
|
|
|
|
|
|
let transformedPolygon = new Array(HourHandPolygon.length);
|
|
|
|
|
|
|
|
function transformPolygon (originalPolygon, OriginX,OriginY, Phi) {
|
|
|
|
let sPhi = sin(Phi), cPhi = cos(Phi), x,y;
|
|
|
|
|
|
|
|
for (let i = 0, l = originalPolygon.length; i < l; i+=2) {
|
|
|
|
x = originalPolygon[i];
|
|
|
|
y = originalPolygon[i+1];
|
|
|
|
|
|
|
|
transformedPolygon[i] = OriginX + x*cPhi + y*sPhi;
|
|
|
|
transformedPolygon[i+1] = OriginY + x*sPhi - y*cPhi;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**** draw clock hands ****/
|
|
|
|
|
|
|
|
function drawClockHands () {
|
|
|
|
let now = new Date();
|
|
|
|
|
|
|
|
let Hours = now.getHours() % 12;
|
|
|
|
let Minutes = now.getMinutes();
|
|
|
|
let Seconds = now.getSeconds();
|
|
|
|
|
|
|
|
let HoursAngle = (Hours+(Minutes/60))/12 * twoPi - Pi;
|
|
|
|
let MinutesAngle = (Minutes/60) * twoPi - Pi;
|
|
|
|
let SecondsAngle = (Seconds/60) * twoPi - Pi;
|
|
|
|
|
2021-12-29 07:59:04 +00:00
|
|
|
g.setColor(g.theme.fg);
|
2021-12-29 06:04:25 +00:00
|
|
|
|
|
|
|
transformPolygon(HourHandPolygon, CenterX,CenterY, HoursAngle);
|
|
|
|
g.fillPoly(transformedPolygon);
|
|
|
|
|
|
|
|
transformPolygon(MinuteHandPolygon, CenterX,CenterY, MinutesAngle);
|
|
|
|
g.fillPoly(transformedPolygon);
|
|
|
|
|
|
|
|
let sPhi = Math.sin(SecondsAngle), cPhi = Math.cos(SecondsAngle);
|
|
|
|
|
2022-01-01 07:13:02 +00:00
|
|
|
g.setColor(g.theme.fg2);
|
2021-12-29 06:04:25 +00:00
|
|
|
g.drawLine(
|
|
|
|
CenterX + SecondHandOffset*sPhi,
|
|
|
|
CenterY - SecondHandOffset*cPhi,
|
|
|
|
CenterX - SecondHandLength*sPhi,
|
|
|
|
CenterY + SecondHandLength*cPhi
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**** refreshDisplay ****/
|
|
|
|
|
|
|
|
let Timer;
|
|
|
|
function refreshDisplay () {
|
2021-12-29 07:59:04 +00:00
|
|
|
g.clear(true); // also loads current theme
|
2021-12-29 06:04:25 +00:00
|
|
|
|
|
|
|
Bangle.drawWidgets();
|
|
|
|
|
|
|
|
drawClockFace();
|
|
|
|
drawClockHands();
|
|
|
|
|
|
|
|
let Pause = 1000 - (Date.now() % 1000);
|
|
|
|
Timer = setTimeout(refreshDisplay,Pause);
|
|
|
|
}
|
|
|
|
|
|
|
|
setTimeout(refreshDisplay, 500); // enqueue first draw request
|
|
|
|
|
|
|
|
Bangle.on('lcdPower', (on) => {
|
|
|
|
if (on) {
|
|
|
|
if (Timer != null) { clearTimeout(Timer); Timer = undefined; }
|
|
|
|
refreshDisplay();
|
|
|
|
}
|
|
|
|
});
|