83
apps.json
|
@ -5098,6 +5098,89 @@
|
|||
{"name":"ltherm.img","url":"icon.js","evaluate":true}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id":"colorwheel",
|
||||
"name":"Color Wheel",
|
||||
"tags":"app,tool",
|
||||
"version":"0.01",
|
||||
"description":"a tappable wheel of good-looking colors",
|
||||
"readme":"README.md",
|
||||
"supports":["BANGLEJS2"],
|
||||
"allow_emulator":true,
|
||||
"icon":"colorwheel.png",
|
||||
"storage": [
|
||||
{"name":"colorwheel.app.js","url":"app.js"},
|
||||
{"name":"colorwheel.img","url":"app-icon.js","evaluate":true}
|
||||
]
|
||||
},
|
||||
{ "id": "minimal_clock",
|
||||
"name": "Minimal Analog Clock",
|
||||
"shortName":"Minimal Clock",
|
||||
"version":"0.03",
|
||||
"description": "a minimal analog clock - just with some hands and no clock face",
|
||||
"icon": "app-icon.png",
|
||||
"type": "clock",
|
||||
"tags": "clock",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"allow_emulator": true,
|
||||
"screenshots": [{"url":"app-screenshot.png"}],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name":"minimal_clock.app.js","url":"app.js"},
|
||||
{"name":"minimal_clock.img","url":"app-icon.js","evaluate":true}
|
||||
]
|
||||
},
|
||||
{ "id": "simple_clock",
|
||||
"name": "Simple Analog Clock",
|
||||
"shortName":"Simple Clock",
|
||||
"version":"0.02",
|
||||
"description": "a simple, yet stylish, analog clock",
|
||||
"icon": "app-icon.png",
|
||||
"type": "clock",
|
||||
"tags": "clock",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"allow_emulator": true,
|
||||
"screenshots": [{"url":"app-screenshot.png"}],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name":"simple_clock.app.js","url":"app.js"},
|
||||
{"name":"simple_clock.img","url":"app-icon.js","evaluate":true}
|
||||
]
|
||||
},
|
||||
{ "id": "colorful_clock",
|
||||
"name": "Colorful Analog Clock",
|
||||
"shortName":"Colorful Clock",
|
||||
"version":"0.02",
|
||||
"description": "a colorful analog clock",
|
||||
"icon": "app-icon.png",
|
||||
"type": "clock",
|
||||
"tags": "clock",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"allow_emulator": true,
|
||||
"screenshots": [{"url":"app-screenshot.png"}],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name":"colorful_clock.app.js","url":"app.js"},
|
||||
{"name":"colorful_clock.img","url":"app-icon.js","evaluate":true}
|
||||
]
|
||||
},
|
||||
{ "id": "themesetter",
|
||||
"name": "Theme Setter",
|
||||
"shortName":"Theme Setter",
|
||||
"version":"0.04",
|
||||
"description": "a comfortable way to configure theme colors",
|
||||
"icon": "app-icon.png",
|
||||
"type": "app",
|
||||
"tags": "tool",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"allow_emulator": true,
|
||||
"screenshots": [{"url":"app-screenshot.png"}],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name":"themesetter.app.js","url":"app.js"},
|
||||
{"name":"themesetter.img","url":"app-icon.js","evaluate":true}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "widviztime",
|
||||
"name": "Widget Autohide Widget",
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
# Colorful Analog Clock #
|
||||
|
||||
This app displays an analog clock with a colorful face. It considers the
|
||||
currently configured "theme" (and may therefore look different than shown in
|
||||
the screenshot on your watch depending on which theme you prefer).
|
||||
|
||||

|
||||
|
||||
This clock also acts as an example for the building blocks found in the author's
|
||||
[GitHub repository](https://github.com/rozek/banglejs-2-activities)
|
||||
|
||||
## License ##
|
||||
|
||||
[MIT License](LICENSE)
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEwgZC/AB0BkmCCBsShEAiFBkARLwEBkGSgEECBQdBCIMSAwMYCBEKCgeQgE2gFgCA0C6Moiw1Dk0AhoRGikACIIHDgzECCI5ECg/gEYOACI+ggMti2ACIUkCIImCABARCAAMNCYIADgu0hdACI1twHACQm0rdoCI0BEYsoilRCI9sUgkBoG2rY1JgYjDCINLCI4fCa5ARHAAggCfYIjLgUB0AECCIy7BFwUCR4IKChIRFm1ACJAjGgwRL+AFDiwREI4YABn41FI4hxFn6IJPoh1B/AQFUI4ABh4RGUIsEyARC4ALEwAjECIl/CIkECIsICId+EQkkwEIA4gRDAAojBLwwHFexAADhaFDgETBw6UChdgA4cbCIKuGggCBCIMDCIkQCI8BEwMbCgMSAQIRGgGQQoQRCEYJrGAAMGIgZKDmBzIjARFTwpuHAARoGAAsMwQVCzARLAAPbtq5KAH4AEA"))
|
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 3.1 KiB |
|
@ -0,0 +1,247 @@
|
|||
let ScreenWidth = g.getWidth(), CenterX = ScreenWidth/2;
|
||||
let ScreenHeight = g.getHeight(), CenterY = ScreenHeight/2;
|
||||
|
||||
let outerRadius = Math.min(CenterX,CenterY) * 0.9;
|
||||
|
||||
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++;
|
||||
}
|
||||
|
||||
g.reset(); // also loads the current theme
|
||||
|
||||
if (pos.tl.c || pos.tr.c) {
|
||||
g.setClipRect(0,h-24,w-1,h-1);
|
||||
g.reset(); // also (re)loads the current theme
|
||||
}
|
||||
|
||||
if (pos.bl.c || pos.br.c) {
|
||||
g.setClipRect(0,h-24,w-1,h-1);
|
||||
g.reset(); // also (re)loads the current theme
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
g.setColor(g.theme.fg);
|
||||
|
||||
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);
|
||||
|
||||
g.setColor(g.theme.fg2);
|
||||
g.drawLine(
|
||||
CenterX + SecondHandOffset*sPhi,
|
||||
CenterY - SecondHandOffset*cPhi,
|
||||
CenterX - SecondHandLength*sPhi,
|
||||
CenterY + SecondHandLength*cPhi
|
||||
);
|
||||
}
|
||||
|
||||
/**** refreshDisplay ****/
|
||||
|
||||
let Timer;
|
||||
function refreshDisplay () {
|
||||
g.clear(true); // also loads current theme
|
||||
|
||||
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();
|
||||
}
|
||||
});
|
||||
|
||||
Bangle.loadWidgets();
|
||||
|
||||
Bangle.setUI('clock');
|
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.0 KiB |
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2021 Andreas Rozek
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,12 @@
|
|||
# ColorWheel #
|
||||
|
||||
Choosing the right color on a Bangle.js 2 is not always easy. This little app therefore displays a wheel of rather good looking colors and reveals the associated color code by tapping on it
|
||||
|
||||

|
||||

|
||||
|
||||
Please note: you may also tap outside the wheel (for black) or inside it (for white).
|
||||
|
||||
## License ##
|
||||
|
||||
[MIT License](LICENSE)
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEwgYtr4cEiAQMku27ckyVICBUDlmy5YRBpMkCBEE7dtEYYRBwARHm3LEY3QCA0BEAIjFk3boARFhoOBEYs06dNCIogCEYoHCNAoOCEYlNEYUgCIcbEZekCIYODtgjHmgRHtu3///yQrESQfTBIYQBAAPNEYU2SQUGEYd/CIf9EYYRCDAYRF/4KBCIioBAwPfCAn/+wKC7QjEmgRG/xADZAIyBAwIQFCIgjFmoRKEYL4DRgQAFGoojKCIoje7Nly1ZEYLzCkojLNYIRCNZAjIkm/EZ4RH/1ZEYYRMWYpZDy4jJrARBggRBlrYG+VJEYgRBDIVfCIgtCy1QCIZhDCAfkKIW24ARBgJeBEYNbvoQBvOkCIQjDgE2EYYCD2gRCyQQCgEGEYYRBzVp0wRCyAREEY+2CIWAEY4OCEYoQDAAMbEY/SpMgCAkCjIjHzVJEQoABWYIjF7VICI8BBwYjDe4IAHSQ3QCBBuBLgQjCCBIAChu26dMCBgAdA"))
|
|
@ -0,0 +1,80 @@
|
|||
//----------------------------------------------------------------------------//
|
||||
//-- ColorWheel - draws a "wheel" of good looking colors --//
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
let ColorList = [
|
||||
'#0000FF', '#8000FF', '#FF00FF', '#FF0080', '#FF0000', '#FF8000',
|
||||
'#FFFF00', '#80FF00', '#00FF00', '#00FF80', '#00FFFF', '#0080FF'
|
||||
];
|
||||
|
||||
let ScreenWidth = g.getWidth(), CenterX = ScreenWidth/2;
|
||||
let ScreenHeight = g.getHeight(), CenterY = ScreenHeight/2;
|
||||
|
||||
let outerRadius = Math.min(CenterX,CenterY) * 0.9;
|
||||
let innerRadius = outerRadius*0.5;
|
||||
|
||||
let sin = Math.sin, cos = Math.cos;
|
||||
let twoPi = 2*Math.PI, halfPi = Math.PI/2;
|
||||
|
||||
let DeltaPhi = twoPi/72;
|
||||
let Epsilon = 0.001;
|
||||
|
||||
g.clear();
|
||||
|
||||
g.setColor(0,0,0);
|
||||
g.fillRect(0,0, ScreenWidth,ScreenHeight);
|
||||
|
||||
for (let i = 0; i < 12; i++) {
|
||||
let Phi0 = i * twoPi/12, Phi1 = (i+1) * twoPi/12;
|
||||
|
||||
let Polygon = [];
|
||||
for (let Phi = Phi0; Phi <= Phi1+Epsilon; Phi += DeltaPhi) {
|
||||
Polygon.push(CenterX + outerRadius * sin(Phi));
|
||||
Polygon.push(CenterY - outerRadius * cos(Phi));
|
||||
}
|
||||
|
||||
for (let Phi = Phi1; Phi >= Phi0-Epsilon; Phi -= DeltaPhi) {
|
||||
Polygon.push(CenterX + innerRadius * sin(Phi));
|
||||
Polygon.push(CenterY - innerRadius * cos(Phi));
|
||||
}
|
||||
g.setColor(ColorList[i]);
|
||||
g.fillPoly(Polygon);
|
||||
}
|
||||
|
||||
g.setColor(1,1,1);
|
||||
g.fillCircle(CenterX,CenterY, innerRadius);
|
||||
|
||||
g.setFont12x20();
|
||||
g.setFontAlign(0,0);
|
||||
g.setColor(0,0,0);
|
||||
|
||||
g.drawString('Tap', CenterX,CenterY-20);
|
||||
g.drawString('on a', CenterX,CenterY);
|
||||
g.drawString('Color', CenterX,CenterY+20);
|
||||
|
||||
Bangle.on('touch', function (Button,Position) {
|
||||
Bangle.buzz();
|
||||
|
||||
let dx = Position.x - CenterX;
|
||||
let dy = Position.y - CenterY;
|
||||
|
||||
let Radius = Math.sqrt(dx*dx + dy*dy);
|
||||
|
||||
let Color;
|
||||
switch (true) {
|
||||
case (Radius > outerRadius): Color = '#000000'; break;
|
||||
case (Radius < innerRadius): Color = '#FFFFFF'; break;
|
||||
default:
|
||||
let Phi = Math.atan2(dy,dx) + halfPi;
|
||||
if (Phi < 0) { Phi += twoPi; }
|
||||
if (Phi > twoPi) { Phi -= twoPi; }
|
||||
|
||||
let Index = Math.floor(12*Phi/twoPi);
|
||||
Color = ColorList[Index];
|
||||
}
|
||||
g.setColor(1,1,1);
|
||||
g.fillCircle(CenterX,CenterY, innerRadius);
|
||||
|
||||
g.setColor(0,0,0);
|
||||
g.drawString(Color, CenterX,CenterY);
|
||||
});
|
After Width: | Height: | Size: 3.8 KiB |
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2021 Andreas Rozek
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,15 @@
|
|||
# Minimal Analog Clock #
|
||||
|
||||
This app displays the perhaps most basic analog clock one can think of - just
|
||||
some clock hands and no clock face. It considers the currently configured
|
||||
"theme" (and may therefore look different than shown in the screenshot on your
|
||||
watch depending on which theme you prefer).
|
||||
|
||||

|
||||
|
||||
This clock also acts as an example for the building blocks found in the author's
|
||||
[GitHub repository](https://github.com/rozek/banglejs-2-activities)
|
||||
|
||||
## License ##
|
||||
|
||||
[MIT License](LICENSE)
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEwgJC/AEBhCjgCBgeAgF8AoXggHwCIXwgfADAX8h4TBAAM+jwkDj/4AocPDwIACgdgBYgoCAAMEuB+/AH4="))
|
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.6 KiB |
|
@ -0,0 +1,230 @@
|
|||
let ScreenWidth = g.getWidth(), CenterX = ScreenWidth/2;
|
||||
let ScreenHeight = g.getHeight(), CenterY = ScreenHeight/2;
|
||||
|
||||
let outerRadius = Math.min(CenterX,CenterY) * 0.9;
|
||||
|
||||
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++;
|
||||
}
|
||||
|
||||
g.reset(); // also loads the current theme
|
||||
|
||||
if (pos.tl.c || pos.tr.c) {
|
||||
g.setClipRect(0,h-24,w-1,h-1);
|
||||
g.reset(); // also (re)loads the current theme
|
||||
}
|
||||
|
||||
if (pos.bl.c || pos.br.c) {
|
||||
g.setClipRect(0,h-24,w-1,h-1);
|
||||
g.reset(); // also (re)loads the current theme
|
||||
}
|
||||
|
||||
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 HourHandLength = outerRadius * 0.5;
|
||||
let HourHandWidth = 2*5, halfHourHandWidth = HourHandWidth/2;
|
||||
|
||||
let MinuteHandLength = outerRadius * 0.7;
|
||||
let MinuteHandWidth = 2*3, halfMinuteHandWidth = MinuteHandWidth/2;
|
||||
|
||||
let SecondHandLength = outerRadius * 0.9;
|
||||
let SecondHandOffset = halfHourHandWidth + 10;
|
||||
|
||||
let outerBoltRadius = halfHourHandWidth + 2, innerBoltRadius = outerBoltRadius - 4;
|
||||
let HandOffset = outerBoltRadius + 4;
|
||||
|
||||
let twoPi = 2*Math.PI, deg2rad = Math.PI/180;
|
||||
let Pi = Math.PI;
|
||||
let halfPi = Math.PI/2;
|
||||
|
||||
let sin = Math.sin, cos = Math.cos;
|
||||
|
||||
let sine = [0, sin(30*deg2rad), sin(60*deg2rad), 1];
|
||||
|
||||
let HandPolygon = [
|
||||
-sine[3],-sine[0], -sine[2],-sine[1], -sine[1],-sine[2], -sine[0],-sine[3],
|
||||
sine[0],-sine[3], sine[1],-sine[2], sine[2],-sine[1], sine[3],-sine[0],
|
||||
sine[3], sine[0], sine[2], sine[1], sine[1], sine[2], sine[0], sine[3],
|
||||
-sine[0], sine[3], -sine[1], sine[2], -sine[2], sine[1], -sine[3], sine[0],
|
||||
];
|
||||
|
||||
let HourHandPolygon = new Array(HandPolygon.length);
|
||||
for (let i = 0, l = HandPolygon.length; i < l; i+=2) {
|
||||
HourHandPolygon[i] = halfHourHandWidth*HandPolygon[i];
|
||||
HourHandPolygon[i+1] = halfHourHandWidth*HandPolygon[i+1];
|
||||
if (i < l/2) { HourHandPolygon[i+1] -= HourHandLength; }
|
||||
if (i > l/2) { HourHandPolygon[i+1] += HandOffset; }
|
||||
}
|
||||
let MinuteHandPolygon = new Array(HandPolygon.length);
|
||||
for (let i = 0, l = HandPolygon.length; i < l; i+=2) {
|
||||
MinuteHandPolygon[i] = halfMinuteHandWidth*HandPolygon[i];
|
||||
MinuteHandPolygon[i+1] = halfMinuteHandWidth*HandPolygon[i+1];
|
||||
if (i < l/2) { MinuteHandPolygon[i+1] -= MinuteHandLength; }
|
||||
if (i > l/2) { MinuteHandPolygon[i+1] += HandOffset; }
|
||||
}
|
||||
|
||||
/**** transforme polygon ****/
|
||||
|
||||
let transformedPolygon = new Array(HandPolygon.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;
|
||||
|
||||
g.setColor(g.theme.fg);
|
||||
|
||||
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);
|
||||
|
||||
g.setColor(g.theme.fg2);
|
||||
g.drawLine(
|
||||
CenterX + SecondHandOffset*sPhi,
|
||||
CenterY - SecondHandOffset*cPhi,
|
||||
CenterX - SecondHandLength*sPhi,
|
||||
CenterY + SecondHandLength*cPhi
|
||||
);
|
||||
|
||||
g.setColor(g.theme.fg);
|
||||
g.fillCircle(CenterX,CenterY, outerBoltRadius);
|
||||
|
||||
g.setColor(g.theme.bg);
|
||||
g.drawCircle(CenterX,CenterY, outerBoltRadius);
|
||||
g.fillCircle(CenterX,CenterY, innerBoltRadius);
|
||||
}
|
||||
|
||||
/**** refreshDisplay ****/
|
||||
|
||||
let Timer;
|
||||
function refreshDisplay () {
|
||||
g.clear(true); // also loads current theme
|
||||
|
||||
Bangle.drawWidgets();
|
||||
|
||||
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();
|
||||
}
|
||||
});
|
||||
|
||||
Bangle.loadWidgets();
|
||||
|
||||
Bangle.setUI('clock');
|
|
@ -0,0 +1,14 @@
|
|||
# Simple Analog Clock #
|
||||
|
||||
This app displays a simple, yet stylish, analog clock. It considers the
|
||||
currently configured "theme" (and may therefore look different than shown in
|
||||
the screenshot on your watch depending on which theme you prefer).
|
||||
|
||||

|
||||
|
||||
This clock also acts as an example for the building blocks found in the author's
|
||||
[GitHub repository](https://github.com/rozek/banglejs-2-activities)
|
||||
|
||||
## License ##
|
||||
|
||||
[MIT License](LICENSE)
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEwwcBIf4AOgPAjgROh/A/+AEZ8DCKH8Gp/4Gp0QCKAARgQRigFACMUICMT7SEcUAkAvK/EAv//BpH8eoYOBAQP//0ECIrvDCIQABj4TB8AREj4RCgIyFn4RJh5HBCJQ1DAA0/UKBuJQZIRgL4wRL4ARhAH4AIg4RQdIwRcnAjiLKIA/ACI="))
|
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 1.9 KiB |
|
@ -0,0 +1,230 @@
|
|||
let ScreenWidth = g.getWidth(), CenterX = ScreenWidth/2;
|
||||
let ScreenHeight = g.getHeight(), CenterY = ScreenHeight/2;
|
||||
|
||||
let outerRadius = Math.min(CenterX,CenterY) * 0.9;
|
||||
|
||||
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++;
|
||||
}
|
||||
|
||||
g.reset(); // also loads the current theme
|
||||
|
||||
if (pos.tl.c || pos.tr.c) {
|
||||
g.setClipRect(0,h-24,w-1,h-1);
|
||||
g.reset(); // also (re)loads the current theme
|
||||
}
|
||||
|
||||
if (pos.bl.c || pos.br.c) {
|
||||
g.setClipRect(0,h-24,w-1,h-1);
|
||||
g.reset(); // also (re)loads the current theme
|
||||
}
|
||||
|
||||
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 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 () {
|
||||
g.setColor(g.theme.fg);
|
||||
g.setFont('Vector', 22);
|
||||
|
||||
g.setFontAlign(0,-1);
|
||||
g.drawString('12', CenterX,CenterY-outerRadius);
|
||||
|
||||
g.setFontAlign(1,0);
|
||||
g.drawString('3', CenterX+outerRadius,CenterY);
|
||||
|
||||
g.setFontAlign(0,1);
|
||||
g.drawString('6', CenterX,CenterY+outerRadius);
|
||||
|
||||
g.setFontAlign(-1,0);
|
||||
g.drawString('9', CenterX-outerRadius,CenterY);
|
||||
}
|
||||
|
||||
/**** 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;
|
||||
|
||||
g.setColor(g.theme.fg);
|
||||
|
||||
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);
|
||||
|
||||
g.setColor(g.theme.fg2);
|
||||
g.drawLine(
|
||||
CenterX + SecondHandOffset*sPhi,
|
||||
CenterY - SecondHandOffset*cPhi,
|
||||
CenterX - SecondHandLength*sPhi,
|
||||
CenterY + SecondHandLength*cPhi
|
||||
);
|
||||
}
|
||||
|
||||
/**** refreshDisplay ****/
|
||||
|
||||
let Timer;
|
||||
function refreshDisplay () {
|
||||
g.clear(true); // also loads current theme
|
||||
|
||||
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();
|
||||
}
|
||||
});
|
||||
|
||||
Bangle.loadWidgets();
|
||||
|
||||
Bangle.setUI('clock');
|
|
@ -0,0 +1,22 @@
|
|||
# Theme Setter #
|
||||
|
||||
This little tool allows you to configure the global theme of all Bangle.js apps
|
||||
(provided that they do not override global settings) in a more comfortable way
|
||||
than through the settings menu.
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
This app also acts as an example for a non-trivial Bangle.js application
|
||||
using the "layout" library, custom controls and generic event dispatching.
|
||||
See [GitHub](https://github.com/rozek/banglejs-2-activities) for details.
|
||||
|
||||
## License ##
|
||||
|
||||
[MIT License](LICENSE)
|
||||
|
||||
## Credits ##
|
||||
|
||||
The icon for this app was taken from [icons8.com](https://icons8.com/).
|
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 3.1 KiB |
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEwgP/ACHgDAQWBApfjCoXxAqHwg4FP+PHApY7EApheEAq3+g4FD/EPAofAj4QDgAQECwgQQ8E/Cwg+EAvYAhA=="))
|
After Width: | Height: | Size: 940 B |
After Width: | Height: | Size: 3.2 KiB |
|
@ -0,0 +1,498 @@
|
|||
let Layout = require('Layout');
|
||||
|
||||
let ScreenWidth = g.getWidth(), halfWidth = ScreenWidth/2;
|
||||
let ScreenHeight = g.getHeight();
|
||||
|
||||
let normalizedColorSet = {
|
||||
black:g.toColor(0,0,0), white: g.toColor(1,1,1),
|
||||
red: g.toColor(1,0,0), yellow: g.toColor(1,1,0),
|
||||
green:g.toColor(0,1,0), magenta:g.toColor(1,0,1),
|
||||
blue: g.toColor(0,0,1), cyan: g.toColor(0,1,1)
|
||||
};
|
||||
|
||||
let activeTheme = g.theme; // currently active theme
|
||||
let pendingTheme = Object.assign({},activeTheme);
|
||||
let chosenDetail = null; // one of 'fg','bg','fg2','bg2','fgH','bgH'
|
||||
|
||||
/**** Label ****/
|
||||
|
||||
function Label (Text, Options) {
|
||||
function renderLabel (Details) {
|
||||
let halfWidth = Details.w/2, xAlignment = Details.halign || 0;
|
||||
let halfHeight = Details.h/2, yAlignment = Details.valign || 0;
|
||||
let Padding = Details.pad || 0;
|
||||
|
||||
g.setColor(Details.col || g.theme.fg || '#000000');
|
||||
|
||||
if (Details.font != null) { g.setFont(Details.font); }
|
||||
g.setFontAlign(xAlignment,yAlignment);
|
||||
|
||||
let x = Details.x + halfWidth + xAlignment*(halfWidth+Padding);
|
||||
let y = Details.y + halfHeight + yAlignment*(halfHeight+Padding);
|
||||
|
||||
g.drawString(Details.label, x,y);
|
||||
if (Details.bold) {
|
||||
g.drawString(Details.label, x+1,y);
|
||||
g.drawString(Details.label, x,y+1);
|
||||
g.drawString(Details.label, x+1,y+1);
|
||||
}
|
||||
}
|
||||
|
||||
let Result = Object.assign((
|
||||
Options == null ? {} : Object.assign({}, Options.common || {}, Options)
|
||||
), {
|
||||
type:'custom', render:renderLabel, label:Text || ''
|
||||
});
|
||||
let TextMetrics;
|
||||
if (! Result.width || ! Result.height) {
|
||||
if (Result.font != null) { g.setFont(Result.font); }
|
||||
TextMetrics = g.stringMetrics(Result.label);
|
||||
}
|
||||
|
||||
Result.width = Result.width || TextMetrics.width + 2*(Result.pad || 0);
|
||||
Result.height = Result.height || TextMetrics.height + 2*(Result.pad || 0);
|
||||
return Result;
|
||||
}
|
||||
|
||||
if (g.drawRoundedRect == null) {
|
||||
g.drawRoundedRect = function drawRoundedRect (x1,y1, x2,y2, r) {
|
||||
let x,y;
|
||||
if (x1 > x2) { x = x1; x1 = x2; x2 = x; }
|
||||
if (y1 > y2) { y = y1; y1 = y2; y2 = y; }
|
||||
|
||||
r = Math.min(r || 0, (x2-x1)/2, (y2-y1)/2);
|
||||
|
||||
let cx1 = x1+r, cx2 = x2-r;
|
||||
let cy1 = y1+r, cy2 = y2-r;
|
||||
|
||||
this.drawLine(cx1,y1, cx2,y1);
|
||||
this.drawLine(cx1,y2, cx2,y2);
|
||||
this.drawLine(x1,cy1, x1,cy2);
|
||||
this.drawLine(x2,cy1, x2,cy2);
|
||||
|
||||
x = r; y = 0;
|
||||
|
||||
let dx,dy, Error = 0;
|
||||
while (y <= x) {
|
||||
dy = 1 + 2*y; y++; Error -= dy;
|
||||
if (Error < 0) {
|
||||
dx = 1 - 2*x; x--; Error -= dx;
|
||||
}
|
||||
|
||||
this.setPixel(cx1 - x, cy1 - y); this.setPixel(cx1 - y, cy1 - x);
|
||||
this.setPixel(cx2 + x, cy1 - y); this.setPixel(cx2 + y, cy1 - x);
|
||||
this.setPixel(cx2 + x, cy2 + y); this.setPixel(cx2 + y, cy2 + x);
|
||||
this.setPixel(cx1 - x, cy2 + y); this.setPixel(cx1 - y, cy2 + x);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**** Button ****/
|
||||
|
||||
function Button (Text, Options) {
|
||||
function renderButton (Details) {
|
||||
let x = Details.x, Width = Details.w, halfWidth = Width/2;
|
||||
let y = Details.y, Height = Details.h, halfHeight = Height/2;
|
||||
let Padding = Details.pad || 0;
|
||||
|
||||
g.setColor(Details.col || g.theme.fg || '#000000');
|
||||
|
||||
if (Details.font != null) { g.setFont(Details.font); }
|
||||
g.setFontAlign(0,0);
|
||||
|
||||
g.drawRoundedRect(x+Padding,y+Padding, x+Width-Padding-1,y+Height-Padding-1,8);
|
||||
g.drawString(Details.label, x+halfWidth,y+halfHeight);
|
||||
g.drawString(Details.label, x+halfWidth+1,y+halfHeight);
|
||||
g.drawString(Details.label, x+halfWidth,y+halfHeight+1);
|
||||
g.drawString(Details.label, x+halfWidth+1,y+halfHeight+1);
|
||||
}
|
||||
|
||||
let Result = Object.assign((
|
||||
Options == null ? {} : Object.assign({}, Options.common || {}, Options)
|
||||
), {
|
||||
type:'custom', render:renderButton, label:Text || 'Tap'
|
||||
});
|
||||
let TextMetrics;
|
||||
if (! Result.width || ! Result.height) {
|
||||
if (Options.font != null) { g.setFont(Options.font); }
|
||||
TextMetrics = g.stringMetrics(Result.label);
|
||||
}
|
||||
|
||||
Result.width = Result.width || TextMetrics.width + 2*10 + 2*(Result.pad || 0);
|
||||
Result.height = Result.height || TextMetrics.height + 2*5 + 2*(Result.pad || 0);
|
||||
return Result;
|
||||
}
|
||||
|
||||
/**** ColorDemo ****/
|
||||
|
||||
function ColorDemo (Text, Options) {
|
||||
function renderDemo (Details) {
|
||||
let x = Details.x, Width = Details.w, halfWidth = Width/2;
|
||||
let y = Details.y, Height = Details.h, halfHeight = Height/2;
|
||||
let Padding = Details.pad || 0;
|
||||
|
||||
if (Details.font != null) { g.setFont(Details.font); }
|
||||
g.setFontAlign(0,0);
|
||||
|
||||
g.setColor(Details.bg); // do not use "bgCol"!
|
||||
g.fillRect(x+Padding, y+Padding, x+Width-Padding, y+Height-Padding);
|
||||
|
||||
g.setColor(Details.fg);
|
||||
g.drawString(Details.label, x+halfWidth,y+halfHeight);
|
||||
}
|
||||
|
||||
let Result = Object.assign((
|
||||
Options == null ? {} : Object.assign({}, Options.common || {}, Options)
|
||||
), {
|
||||
type:'custom', render:renderDemo, label:Text || 'Test'
|
||||
});
|
||||
let TextMetrics;
|
||||
if (! Result.width || ! Result.height) {
|
||||
if (Result.font != null) { g.setFont(Result.font); }
|
||||
TextMetrics = g.stringMetrics(Result.label);
|
||||
}
|
||||
|
||||
Result.width = Result.width || TextMetrics.width + 2*2 + 2*(Result.pad || 0);
|
||||
Result.height = Result.height || TextMetrics.height + 2*2 + 2*(Result.pad || 0);
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
/**** ColorView ****/
|
||||
|
||||
function ColorView (Color, Options) {
|
||||
function renderColorView (Details) {
|
||||
let x = Details.x, Width = Details.w;
|
||||
let y = Details.y, Height = Details.h;
|
||||
let Padding = Details.pad || 0;
|
||||
|
||||
g.setColor('#000000');
|
||||
g.drawRect(x+Padding,y+Padding, x+Width-Padding-1,y+Height-Padding-1);
|
||||
|
||||
g.setColor(Details.col);
|
||||
g.fillRect(x+Padding+2, y+Padding+2, x+Width-Padding-3, y+Height-Padding-3);
|
||||
}
|
||||
|
||||
let Result = Object.assign((
|
||||
Options == null ? {} : Object.assign({}, Options.common || {}, Options)
|
||||
), {
|
||||
type:'custom', render:renderColorView, col:Color
|
||||
});
|
||||
Result.width = Math.max(10, Result.width || 10) + 2*(Result.pad || 0);
|
||||
Result.height = Math.max(10, Result.height || 10) + 2*(Result.pad || 0);
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
/**** ColorSelectionView ****/
|
||||
|
||||
function ColorSelectionView (Color, Options) {
|
||||
function renderColorView (Details) {
|
||||
let x = Details.x, Width = Details.w;
|
||||
let y = Details.y, Height = Details.h;
|
||||
let Padding = Details.pad || 0;
|
||||
|
||||
if (Details.selected) {
|
||||
g.setColor(Details.selected ? '#FF0000' : '#000000');
|
||||
g.fillRect(x+Padding,y+Padding, x+Width-Padding-1,y+Height-Padding-1);
|
||||
|
||||
g.setColor('#FFFFFF');
|
||||
g.drawRect(x+Padding+4,y+Padding+4, x+Width-Padding-5,y+Height-Padding-5);
|
||||
} else {
|
||||
g.setColor('#000000');
|
||||
g.drawRect(x+Padding+3,y+Padding+3, x+Width-Padding-4,y+Height-Padding-4);
|
||||
}
|
||||
|
||||
g.setColor(Details.col);
|
||||
g.fillRect(x+Padding+5, y+Padding+5, x+Width-Padding-6, y+Height-Padding-6);
|
||||
}
|
||||
|
||||
let Result = Object.assign((
|
||||
Options == null ? {} : Object.assign({}, Options.common || {}, Options)
|
||||
), {
|
||||
type:'custom', render:renderColorView, col:Color
|
||||
});
|
||||
Result.width = Math.max(10, Result.width || 10) + 2*(Result.pad || 0);
|
||||
Result.height = Math.max(10, Result.height || 10) + 2*(Result.pad || 0);
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
/**** EventConsumerAtPoint ****/
|
||||
|
||||
function EventConsumerAtPoint (HandlerName, x,y) {
|
||||
let Layout = (activeLayout || {}).l;
|
||||
if (Layout == null) { return; }
|
||||
|
||||
function ConsumerIn (Control) {
|
||||
if (
|
||||
(x < Control.x) || (x >= Control.x + Control.w) ||
|
||||
(y < Control.y) || (y >= Control.y + Control.h)
|
||||
) { return undefined; }
|
||||
|
||||
if (typeof Control[HandlerName] === 'function') { return Control; }
|
||||
|
||||
if (Control.c != null) {
|
||||
let ControlList = Control.c;
|
||||
for (let i = 0, l = ControlList.length; i < l; i++) {
|
||||
let Consumer = ConsumerIn(ControlList[i]);
|
||||
if (Consumer != null) { return Consumer; }
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return ConsumerIn(Layout);
|
||||
}
|
||||
|
||||
/**** dispatchTouchEvent ****/
|
||||
|
||||
function dispatchTouchEvent () {
|
||||
function handleTouchEvent (Button, xy) {
|
||||
let Control = EventConsumerAtPoint('onTouch', xy.x,xy.y);
|
||||
if (Control != null) {
|
||||
Control.onTouch(Control, Button, xy);
|
||||
}
|
||||
}
|
||||
Bangle.on('touch',handleTouchEvent);
|
||||
}
|
||||
dispatchTouchEvent();
|
||||
|
||||
/**** dispatchStrokeEvent ****/
|
||||
|
||||
function dispatchStrokeEvent () {
|
||||
function handleStrokeEvent (Coordinates) {
|
||||
let Control = EventConsumerAtPoint('onStroke', Coordinates.xy[0],Coordinates.xy[1]);
|
||||
if (Control != null) {
|
||||
Control.onStroke(Control, Coordinates);
|
||||
}
|
||||
}
|
||||
Bangle.on('stroke',handleStrokeEvent);
|
||||
}
|
||||
dispatchStrokeEvent();
|
||||
|
||||
let ScreenSet = {};
|
||||
|
||||
g.setFont12x20(); // does not seem to be respected in layout!
|
||||
let leftColumnWidth = Math.max(
|
||||
g.stringWidth('Normal '), g.stringWidth('Accented '), g.stringWidth('Hilighted ')
|
||||
);
|
||||
|
||||
let StdFont = { font:'12x20' };
|
||||
let legible = Object.assign({ col:'#000000', bgCol:'#FFFFFF' }, StdFont);
|
||||
let leftAligned = Object.assign({ halign:-1, valign:0 }, legible);
|
||||
let MainLabel = Object.assign({ pad:4, width:leftColumnWidth }, leftAligned);
|
||||
let halfWidthButton = Object.assign({ pad:4, width:halfWidth }, legible);
|
||||
|
||||
ScreenSet['MainScreen'] = new Layout({
|
||||
type:'v', c:[
|
||||
Label('Current Theme', { common:legible, pad:8, bold:true, filly:1 }),
|
||||
{ type:'h', c:[
|
||||
Label('Normal', { common:MainLabel }),
|
||||
ColorDemo(' Demo ',{ common:StdFont, pad:2, id:'NormalDemo' }),
|
||||
] },
|
||||
{ type:'h', c:[
|
||||
Label('Accented', { common:MainLabel }),
|
||||
ColorDemo(' Demo ',{ common:StdFont, pad:2, id:'AccentedDemo' }),
|
||||
] },
|
||||
{ type:'h', c:[
|
||||
Label('Hilighted', { common:MainLabel }),
|
||||
ColorDemo(' Demo ',{ common:StdFont, pad:2, id:'HilitedDemo' }),
|
||||
] },
|
||||
{ height:4 },
|
||||
{ type:'h', c:[
|
||||
Button('Exit', { common:halfWidthButton, onTouch:() => load() }),
|
||||
Button('Config', { common:halfWidthButton, onTouch:() => gotoScreen('DetailSelectionScreen') })
|
||||
], filly:1 }
|
||||
]
|
||||
});
|
||||
|
||||
let LabelWidth = Math.max(
|
||||
g.stringWidth('Fg '), g.stringWidth('Fg2 '), g.stringWidth('FgH '),
|
||||
g.stringWidth('Bg '), g.stringWidth('Bg2 '), g.stringWidth('BgH ')
|
||||
);
|
||||
let LabelHeight = g.stringMetrics('FgH').height;
|
||||
|
||||
let DetailLabel = Object.assign({ pad:4, width:LabelWidth }, leftAligned);
|
||||
let DetailView = { width:30, height:LabelHeight, pad:2 };
|
||||
|
||||
ScreenSet['DetailSelectionScreen'] = new Layout({
|
||||
type:'v', c:[
|
||||
Label('Configure Detail', { font:'12x20', pad:8, col:'#000000', bgCol:'#FFFFFF', bold:true, filly:1 }),
|
||||
{ type:'h', c:[
|
||||
Label('fg', { common:DetailLabel, onTouch:() => configureDetail('fg') }),
|
||||
ColorView(0, { common:DetailView, onTouch:() => configureDetail('fg'), id:'fgView' }),
|
||||
{ width:20 },
|
||||
Label('bg', { common:DetailLabel, onTouch:() => configureDetail('bg') }),
|
||||
ColorView(0, { common:DetailView, onTouch:() => configureDetail('bg'), id:'bgView' }),
|
||||
] },
|
||||
{ type:'h', c:[
|
||||
Label('fg2', { common:DetailLabel, onTouch:() => configureDetail('fg2') }),
|
||||
ColorView(0, { common:DetailView, onTouch:() => configureDetail('fg2'), id:'fg2View' }),
|
||||
{ width:20 },
|
||||
Label('bg2', { common:DetailLabel, onTouch:() => configureDetail('bg2') }),
|
||||
ColorView(0, { common:DetailView, onTouch:() => configureDetail('bg2'), id:'bg2View' }),
|
||||
] },
|
||||
{ type:'h', c:[
|
||||
Label('fgH', { common:DetailLabel, onTouch:() => configureDetail('fgH') }),
|
||||
ColorView(0, { common:DetailView, onTouch:() => configureDetail('fgH'), id:'fgHView' }),
|
||||
{ width:20 },
|
||||
Label('bgH', { common:DetailLabel, onTouch:() => configureDetail('bgH') }),
|
||||
ColorView(0, { common:DetailView, onTouch:() => configureDetail('bgH'), id:'bgHView' }),
|
||||
] },
|
||||
{ type:'h', c:[
|
||||
Button('Save', { common:halfWidthButton, onTouch:() => { applyChanges(); gotoScreen('MainScreen'); } }),
|
||||
Button('Cancel', { common:halfWidthButton, onTouch:() => gotoScreen('MainScreen') })
|
||||
], filly:1 },
|
||||
]
|
||||
});
|
||||
|
||||
let StdSelectionView = { width:40, height:40, pad:2 };
|
||||
|
||||
ScreenSet['ColorSelectionScreen'] = new Layout({
|
||||
type:'v', c:[
|
||||
Label('Choose Color', { font:'12x20', pad:8, col:'#000000', bgCol:'#FFFFFF', bold:true, filly:1 }),
|
||||
{ type:'h', c:[
|
||||
ColorSelectionView('#000000',{ common:StdSelectionView, id:'black',
|
||||
onTouch:() => selectColor(0,0,0) }),
|
||||
ColorSelectionView('#FF0000',{ common:StdSelectionView, id:'red',
|
||||
onTouch:() => selectColor(1,0,0) }),
|
||||
ColorSelectionView('#00FF00',{ common:StdSelectionView, id:'green',
|
||||
onTouch:() => selectColor(0,1,0) }),
|
||||
ColorSelectionView('#0000FF',{ common:StdSelectionView, id:'blue',
|
||||
onTouch:() => selectColor(0,0,1) }),
|
||||
] },
|
||||
{ type:'h', c:[
|
||||
ColorSelectionView('#FFFFFF',{ common:StdSelectionView, id:'white',
|
||||
onTouch:() => selectColor(1,1,1) }),
|
||||
ColorSelectionView('#FFFF00',{ common:StdSelectionView, id:'yellow',
|
||||
onTouch:() => selectColor(1,1,0) }),
|
||||
ColorSelectionView('#FF00FF',{ common:StdSelectionView, id:'magenta',
|
||||
onTouch:() => selectColor(1,0,1) }),
|
||||
ColorSelectionView('#00FFFF',{ common:StdSelectionView, id:'cyan',
|
||||
onTouch:() => selectColor(0,1,1) }),
|
||||
] },
|
||||
{ height:4 },
|
||||
{ type:'h', c:[
|
||||
Button('Back', { common:halfWidthButton, onTouch:() => gotoScreen('DetailSelectionScreen') }),
|
||||
Button('Preview', { common:halfWidthButton, onTouch:() => gotoScreen('ThemePreviewScreen') })
|
||||
], filly:1 },
|
||||
]
|
||||
});
|
||||
|
||||
ScreenSet['ThemePreviewScreen'] = new Layout({
|
||||
type:'v', c:[
|
||||
Label('Theme Preview', { common:legible, bold:true, filly:1 }),
|
||||
{ type:'h', c:[
|
||||
Label('Normal', { common:MainLabel }),
|
||||
ColorDemo(' Test ',{ common:StdFont, pad:2, id:'NormalTest' }),
|
||||
] },
|
||||
{ type:'h', c:[
|
||||
Label('Accented', { common:MainLabel }),
|
||||
ColorDemo(' Test ',{ common:StdFont, pad:2, id:'AccentedTest' }),
|
||||
] },
|
||||
{ type:'h', c:[
|
||||
Label('Hilighted', { common:MainLabel }),
|
||||
ColorDemo(' Test ',{ common:StdFont, pad:2, id:'HilitedTest' }),
|
||||
] },
|
||||
{ height:4 },
|
||||
{ type:'h', c:[
|
||||
Button('Back', { common:legible, pad:4, onTouch:() => gotoScreen('ColorSelectionScreen') })
|
||||
], filly:1 }
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
/**** applyChanges ****/
|
||||
|
||||
function applyChanges () {
|
||||
let pendingBg = pendingTheme.bg;
|
||||
let R = ((pendingBg >> 11) & 0b11111) / 0b11111;
|
||||
let G = ((pendingBg >> 5) & 0b111111) / 0b111111;
|
||||
let B = (pendingBg & 0b11111) / 0b11111;
|
||||
pendingTheme.dark = (0.2126*R + 0.7152*G + 0.0722*B < 0.5);
|
||||
|
||||
activeTheme = Object.assign(activeTheme,pendingTheme);
|
||||
|
||||
let globalSettings = Object.assign(
|
||||
require('Storage').readJSON('setting.json', true) || {},
|
||||
{ theme:activeTheme }
|
||||
);
|
||||
require('Storage').writeJSON('setting.json', globalSettings);
|
||||
}
|
||||
|
||||
/**** configureDetail ****/
|
||||
|
||||
function configureDetail (Detail) {
|
||||
chosenDetail = Detail;
|
||||
gotoScreen('ColorSelectionScreen');
|
||||
}
|
||||
|
||||
/**** updateColorSelection ****/
|
||||
|
||||
function updateColorSelection () {
|
||||
let selectedColor = pendingTheme[chosenDetail];
|
||||
|
||||
for (let Key in normalizedColorSet) {
|
||||
if (normalizedColorSet.hasOwnProperty(Key)) {
|
||||
activeLayout[Key].selected = (selectedColor === normalizedColorSet[Key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**** selectColor ****/
|
||||
|
||||
function selectColor (R,G,B) {
|
||||
let selectedColor = g.toColor(R,G,B);
|
||||
pendingTheme[chosenDetail] = selectedColor;
|
||||
|
||||
updateColorSelection();
|
||||
g.clear();
|
||||
activeLayout.render();
|
||||
}
|
||||
|
||||
/**** gotoScreen ****/
|
||||
|
||||
let activeLayout;
|
||||
|
||||
function gotoScreen (ScreenName) {
|
||||
activeLayout = ScreenSet[ScreenName];
|
||||
|
||||
switch (ScreenName) {
|
||||
case 'MainScreen':
|
||||
activeLayout['NormalDemo'].fg = activeTheme.fg;
|
||||
activeLayout['NormalDemo'].bg = activeTheme.bg;
|
||||
activeLayout['AccentedDemo'].fg = activeTheme.fg2;
|
||||
activeLayout['AccentedDemo'].bg = activeTheme.bg2;
|
||||
activeLayout['HilitedDemo'].fg = activeTheme.fgH;
|
||||
activeLayout['HilitedDemo'].bg = activeTheme.bgH;
|
||||
break;
|
||||
case 'DetailSelectionScreen':
|
||||
activeLayout['fgView'].col = pendingTheme.fg;
|
||||
activeLayout['bgView'].col = pendingTheme.bg;
|
||||
activeLayout['fg2View'].col = pendingTheme.fg2;
|
||||
activeLayout['bg2View'].col = pendingTheme.bg2;
|
||||
activeLayout['fgHView'].col = pendingTheme.fgH;
|
||||
activeLayout['bgHView'].col = pendingTheme.bgH;
|
||||
break;
|
||||
case 'ColorSelectionScreen':
|
||||
updateColorSelection();
|
||||
break;
|
||||
case 'ThemePreviewScreen':
|
||||
activeLayout['NormalTest'].fg = pendingTheme.fg;
|
||||
activeLayout['NormalTest'].bg = pendingTheme.bg;
|
||||
activeLayout['AccentedTest'].fg = pendingTheme.fg2;
|
||||
activeLayout['AccentedTest'].bg = pendingTheme.bg2;
|
||||
activeLayout['HilitedTest'].fg = pendingTheme.fgH;
|
||||
activeLayout['HilitedTest'].bg = pendingTheme.bgH;
|
||||
}
|
||||
|
||||
g.setColor('#000000'); g.setBgColor('#FFFFFF'); // assert legibility
|
||||
g.clear();
|
||||
|
||||
activeLayout.render();
|
||||
}
|
||||
gotoScreen('MainScreen');
|
||||
|