mirror of https://github.com/espruino/BangleApps
Update to use Bangle.setUI instead of setWatch
parent
0abc0ae213
commit
03ee6aea83
24
apps.json
24
apps.json
|
@ -4,7 +4,7 @@
|
|||
"tags": "tool,system,b2",
|
||||
"type":"bootloader",
|
||||
"icon": "bootloader.png",
|
||||
"version":"0.26",
|
||||
"version":"0.27",
|
||||
"description": "This is needed by Bangle.js to automatically load the clock, menu, widgets and settings",
|
||||
"storage": [
|
||||
{"name":".boot0","url":"boot0.js"},
|
||||
|
@ -1030,7 +1030,7 @@
|
|||
{ "id": "bclock",
|
||||
"name": "Binary Clock",
|
||||
"icon": "clock-binary.png",
|
||||
"version":"0.02",
|
||||
"version":"0.03",
|
||||
"description": "A simple binary clock watch face",
|
||||
"tags": "clock",
|
||||
"type":"clock",
|
||||
|
@ -1106,9 +1106,9 @@
|
|||
"name": "Large Digit Blob Clock",
|
||||
"shortName" : "Blob Clock",
|
||||
"icon": "clock-blob.png",
|
||||
"version":"0.05",
|
||||
"version":"0.06",
|
||||
"description": "A clock with big digits",
|
||||
"tags": "clock",
|
||||
"tags": "clock,b2",
|
||||
"type":"clock",
|
||||
"allow_emulator":true,
|
||||
"storage": [
|
||||
|
@ -1155,7 +1155,7 @@
|
|||
{ "id": "berlinc",
|
||||
"name": "Berlin Clock",
|
||||
"icon": "berlin-clock.png",
|
||||
"version":"0.03",
|
||||
"version":"0.04",
|
||||
"description": "Berlin Clock (see https://en.wikipedia.org/wiki/Mengenlehreuhr)",
|
||||
"tags": "clock",
|
||||
"type":"clock",
|
||||
|
@ -1313,7 +1313,7 @@
|
|||
{ "id": "barclock",
|
||||
"name": "Bar Clock",
|
||||
"icon": "clock-bar.png",
|
||||
"version":"0.06",
|
||||
"version":"0.07",
|
||||
"description": "A simple digital clock showing seconds as a bar",
|
||||
"tags": "clock",
|
||||
"type":"clock",
|
||||
|
@ -1572,7 +1572,7 @@
|
|||
"name": "Numerals Clock",
|
||||
"shortName": "Numerals Clock",
|
||||
"icon": "numerals.png",
|
||||
"version":"0.08",
|
||||
"version":"0.09",
|
||||
"description": "A simple big numerals clock",
|
||||
"tags": "numerals,clock",
|
||||
"type":"clock",
|
||||
|
@ -1986,7 +1986,7 @@
|
|||
"id": "beebclock",
|
||||
"name": "Beeb Clock",
|
||||
"icon": "beebclock.png",
|
||||
"version":"0.03",
|
||||
"version":"0.04",
|
||||
"description": "Clock face that may be coincidentally familiar to BBC viewers",
|
||||
"tags": "clock",
|
||||
"type": "clock",
|
||||
|
@ -2114,7 +2114,7 @@
|
|||
"name": "Binary Clock",
|
||||
"shortName":"Binary Clock",
|
||||
"icon": "app.png",
|
||||
"version":"0.02",
|
||||
"version":"0.03",
|
||||
"description": "A binary clock with hours and minutes. BTN1 toggles a digital clock.",
|
||||
"tags": "clock,binary",
|
||||
"type": "clock",
|
||||
|
@ -2755,7 +2755,7 @@
|
|||
{ "id": "astral",
|
||||
"name": "Astral Clock",
|
||||
"icon": "app-icon.png",
|
||||
"version":"0.02",
|
||||
"version":"0.03",
|
||||
"readme": "README.md",
|
||||
"description": "Clock that calculates and displays Alt Az positions of all planets, Sun as well as several other astronomy targets (customizable) and current Moon phase. Coordinates are calculated by GPS & time and onscreen compass assists orienting. See Readme before using.",
|
||||
"tags": "clock",
|
||||
|
@ -3223,7 +3223,7 @@
|
|||
"name": "Bat Clock",
|
||||
"shortName":"Bat Clock",
|
||||
"icon": "bat-clock.png",
|
||||
"version":"0.01",
|
||||
"version":"0.02",
|
||||
"description": "Morphing Clock, with an awesome \"The Dark Knight\" themed logo.",
|
||||
"tags": "clock",
|
||||
"type": "clock",
|
||||
|
@ -3278,7 +3278,7 @@
|
|||
{ "id": "mysticdock",
|
||||
"name": "Mystic Dock",
|
||||
"icon": "mystic-dock.png",
|
||||
"version":"1.0",
|
||||
"version":"1.00",
|
||||
"description": "A retro-inspired dockface that displays the current time and battery charge while plugged in, and which features an interactive mode that shows the time, date, and a rotating data display line.",
|
||||
"tags": "dock",
|
||||
"type":"dock",
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
0.01: Create astral clock app
|
||||
0.02: Fixed Whirlpool galaxy RA/DA, larger compass display, fixed moonphase overlapping battery widget
|
||||
0.03: Update to use Bangle.setUI instead of setWatch
|
||||
|
|
|
@ -503,8 +503,8 @@ function coord_to_horizon(utc, ra, dec, lat, lon, h) {
|
|||
}
|
||||
|
||||
//
|
||||
// "mean_sidereal_time" returns the Mean Sidereal Time in units of degrees.
|
||||
// Use lon = 0 to get the Greenwich MST.
|
||||
// "mean_sidereal_time" returns the Mean Sidereal Time in units of degrees.
|
||||
// Use lon = 0 to get the Greenwich MST.
|
||||
// East longitudes are positive; West longitudes are negative
|
||||
//
|
||||
// returns: time in degrees
|
||||
|
@ -523,7 +523,7 @@ function mean_sidereal_time(lon) {
|
|||
var c = Math.floor(365.25 * year);
|
||||
var da = Math.floor(30.6001 * (month + 1));
|
||||
|
||||
// days since J2000.0
|
||||
// days since J2000.0
|
||||
var jd = b + c + da - 730550.5 + day
|
||||
+ (hour + mins / 60.0 + secs / 3600.0) / 24.0;
|
||||
|
||||
|
@ -796,10 +796,11 @@ Bangle.on('lcdPower', on => {
|
|||
Bangle.setCompassPower(1);
|
||||
Bangle.setGPSPower(1);
|
||||
|
||||
// Buttons
|
||||
setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" });
|
||||
// Show launcher when button pressed
|
||||
Bangle.setClockMode();
|
||||
|
||||
setWatch(function () {
|
||||
Bangle.setUI("clockupdown", btn => {
|
||||
if (btn==0) {
|
||||
if (!processing) {
|
||||
if (!modeswitch) {
|
||||
modeswitch = true;
|
||||
|
@ -809,12 +810,11 @@ setWatch(function () {
|
|||
else
|
||||
modeswitch = false;
|
||||
}
|
||||
}, BTN3, { repeat: true });
|
||||
|
||||
setWatch(function () {
|
||||
} else {
|
||||
if (!processing)
|
||||
ready_to_compute = true;
|
||||
}, BTN1, { repeat: true });
|
||||
}
|
||||
});
|
||||
|
||||
setWatch(function () {
|
||||
if (!astral_settings.astral_default) {
|
||||
|
|
|
@ -3,4 +3,5 @@
|
|||
0.03: Fix dates drawing over each other at midnight
|
||||
0.04: Small bugfix
|
||||
0.05: Clock does not start if app Languages is not installed
|
||||
0.06: Improve accuracy
|
||||
0.06: Improve accuracy
|
||||
0.07: Update to use Bangle.setUI instead of setWatch
|
||||
|
|
|
@ -2,170 +2,168 @@
|
|||
/**
|
||||
* A simple digital clock showing seconds as a bar
|
||||
**/
|
||||
{
|
||||
// Check settings for what type our clock should be
|
||||
const is12Hour = (require('Storage').readJSON('setting.json', 1) || {})['12hour']
|
||||
let locale = require('locale')
|
||||
{ // add some more info to locale
|
||||
let date = new Date()
|
||||
date.setFullYear(1111)
|
||||
date.setMonth(1, 3) // februari: months are zero-indexed
|
||||
const localized = locale.date(date, true)
|
||||
locale.dayFirst = /3.*2/.test(localized)
|
||||
// Check settings for what type our clock should be
|
||||
const is12Hour = (require('Storage').readJSON('setting.json', 1) || {})['12hour']
|
||||
let locale = require('locale')
|
||||
{ // add some more info to locale
|
||||
let date = new Date()
|
||||
date.setFullYear(1111)
|
||||
date.setMonth(1, 3) // februari: months are zero-indexed
|
||||
const localized = locale.date(date, true)
|
||||
locale.dayFirst = /3.*2/.test(localized)
|
||||
|
||||
locale.hasMeridian = false
|
||||
if(typeof locale.meridian === 'function') { // function does not exists if languages app is not installed
|
||||
locale.hasMeridian = (locale.meridian(date) !== '')
|
||||
}
|
||||
|
||||
}
|
||||
const screen = {
|
||||
width: g.getWidth(),
|
||||
height: g.getWidth(),
|
||||
middle: g.getWidth() / 2,
|
||||
center: g.getHeight() / 2,
|
||||
locale.hasMeridian = false
|
||||
if(typeof locale.meridian === 'function') { // function does not exists if languages app is not installed
|
||||
locale.hasMeridian = (locale.meridian(date) !== '')
|
||||
}
|
||||
|
||||
// hardcoded "settings"
|
||||
const settings = {
|
||||
time: {
|
||||
}
|
||||
const screen = {
|
||||
width: g.getWidth(),
|
||||
height: g.getWidth(),
|
||||
middle: g.getWidth() / 2,
|
||||
center: g.getHeight() / 2,
|
||||
}
|
||||
|
||||
// hardcoded "settings"
|
||||
const settings = {
|
||||
time: {
|
||||
color: -1,
|
||||
font: '6x8',
|
||||
size: (is12Hour && locale.hasMeridian) ? 6 : 8,
|
||||
middle: screen.middle,
|
||||
center: screen.center,
|
||||
ampm: {
|
||||
color: -1,
|
||||
font: '6x8',
|
||||
size: (is12Hour && locale.hasMeridian) ? 6 : 8,
|
||||
middle: screen.middle,
|
||||
center: screen.center,
|
||||
ampm: {
|
||||
color: -1,
|
||||
font: '6x8',
|
||||
size: 2,
|
||||
},
|
||||
size: 2,
|
||||
},
|
||||
date: {
|
||||
color: -1,
|
||||
font: 'Vector',
|
||||
size: 20,
|
||||
middle: screen.height - 20, // at bottom of screen
|
||||
center: screen.center,
|
||||
},
|
||||
bar: {
|
||||
color: -1,
|
||||
top: 155, // just below time
|
||||
thickness: 6, // matches 24h time "pixel" size
|
||||
},
|
||||
}
|
||||
|
||||
const SECONDS_PER_MINUTE = 60
|
||||
|
||||
const timeText = function (date) {
|
||||
if (!is12Hour) {
|
||||
return locale.time(date, true)
|
||||
}
|
||||
const date12 = new Date(date.getTime())
|
||||
const hours = date12.getHours()
|
||||
if (hours === 0) {
|
||||
date12.setHours(12)
|
||||
} else if (hours > 12) {
|
||||
date12.setHours(hours - 12)
|
||||
}
|
||||
return locale.time(date12, true)
|
||||
}
|
||||
const ampmText = function (date) {
|
||||
return is12Hour ? locale.meridian(date) : ''
|
||||
}
|
||||
|
||||
const dateText = function (date) {
|
||||
const dayName = locale.dow(date, true),
|
||||
month = locale.month(date, true),
|
||||
day = date.getDate()
|
||||
const dayMonth = locale.dayFirst ? `${day} ${month}` : `${month} ${day}`
|
||||
return `${dayName} ${dayMonth}`
|
||||
}
|
||||
|
||||
const drawDateTime = function (date) {
|
||||
const t = settings.time
|
||||
g.setColor(t.color)
|
||||
g.setFont(t.font, t.size)
|
||||
g.setFontAlign(0, 0) // centered
|
||||
g.drawString(timeText(date), t.center, t.middle, true)
|
||||
if (is12Hour && locale.hasMeridian) {
|
||||
const a = settings.time.ampm
|
||||
g.setColor(a.color)
|
||||
g.setFont(a.font, a.size)
|
||||
g.setFontAlign(1, -1) // right top
|
||||
// at right edge of screen, aligned with time bottom
|
||||
const left = screen.width - a.size * 2,
|
||||
top = t.middle + t.size - a.size
|
||||
g.drawString(ampmText(date), left, top, true)
|
||||
}
|
||||
|
||||
const d = settings.date
|
||||
g.setColor(d.color)
|
||||
g.setFont(d.font, d.size)
|
||||
g.setFontAlign(0, 0) // centered
|
||||
g.drawString(dateText(date), d.center, d.middle, true)
|
||||
}
|
||||
|
||||
const drawBar = function (date) {
|
||||
const b = settings.bar
|
||||
const seconds = date.getSeconds()
|
||||
if (seconds === 0) {
|
||||
// zero-size rect stills draws one line of pixels, we don't want that
|
||||
return
|
||||
}
|
||||
const fraction = seconds / SECONDS_PER_MINUTE,
|
||||
width = fraction * screen.width
|
||||
g.setColor(b.color)
|
||||
g.fillRect(0, b.top, width, b.top + b.thickness)
|
||||
}
|
||||
|
||||
const clearScreen = function () {
|
||||
g.setColor(0)
|
||||
const timeTop = settings.time.middle - (settings.time.size * 4)
|
||||
g.fillRect(0, timeTop, screen.width, screen.height)
|
||||
}
|
||||
|
||||
let lastSeconds, tTick
|
||||
const tick = function () {
|
||||
g.reset()
|
||||
const date = new Date()
|
||||
const seconds = date.getSeconds()
|
||||
if (lastSeconds > seconds) {
|
||||
// new minute
|
||||
clearScreen()
|
||||
drawDateTime(date)
|
||||
}
|
||||
// the bar only gets larger, so drawing on top of the previous one is fine
|
||||
drawBar(date)
|
||||
lastSeconds = seconds
|
||||
// schedule next update
|
||||
const millis = date.getMilliseconds()
|
||||
tTick = setTimeout(tick, 1000-millis)
|
||||
}
|
||||
|
||||
const start = function () {
|
||||
lastSeconds = 99 // force redraw
|
||||
tick()
|
||||
}
|
||||
const stop = function () {
|
||||
if (tTick) {
|
||||
clearTimeout(tTick)
|
||||
tTick = undefined
|
||||
}
|
||||
}
|
||||
|
||||
// clean app screen
|
||||
g.clear()
|
||||
Bangle.loadWidgets()
|
||||
Bangle.drawWidgets()
|
||||
// Show launcher when middle button pressed
|
||||
setWatch(Bangle.showLauncher, BTN2, {repeat: false, edge: 'falling'})
|
||||
|
||||
Bangle.on('lcdPower', function (on) {
|
||||
if (on) {
|
||||
start()
|
||||
} else {
|
||||
stop()
|
||||
}
|
||||
})
|
||||
start()
|
||||
},
|
||||
date: {
|
||||
color: -1,
|
||||
font: 'Vector',
|
||||
size: 20,
|
||||
middle: screen.height - 20, // at bottom of screen
|
||||
center: screen.center,
|
||||
},
|
||||
bar: {
|
||||
color: -1,
|
||||
top: 155, // just below time
|
||||
thickness: 6, // matches 24h time "pixel" size
|
||||
},
|
||||
}
|
||||
|
||||
const SECONDS_PER_MINUTE = 60
|
||||
|
||||
const timeText = function (date) {
|
||||
if (!is12Hour) {
|
||||
return locale.time(date, true)
|
||||
}
|
||||
const date12 = new Date(date.getTime())
|
||||
const hours = date12.getHours()
|
||||
if (hours === 0) {
|
||||
date12.setHours(12)
|
||||
} else if (hours > 12) {
|
||||
date12.setHours(hours - 12)
|
||||
}
|
||||
return locale.time(date12, true)
|
||||
}
|
||||
const ampmText = function (date) {
|
||||
return is12Hour ? locale.meridian(date) : ''
|
||||
}
|
||||
|
||||
const dateText = function (date) {
|
||||
const dayName = locale.dow(date, true),
|
||||
month = locale.month(date, true),
|
||||
day = date.getDate()
|
||||
const dayMonth = locale.dayFirst ? `${day} ${month}` : `${month} ${day}`
|
||||
return `${dayName} ${dayMonth}`
|
||||
}
|
||||
|
||||
const drawDateTime = function (date) {
|
||||
const t = settings.time
|
||||
g.setColor(t.color)
|
||||
g.setFont(t.font, t.size)
|
||||
g.setFontAlign(0, 0) // centered
|
||||
g.drawString(timeText(date), t.center, t.middle, true)
|
||||
if (is12Hour && locale.hasMeridian) {
|
||||
const a = settings.time.ampm
|
||||
g.setColor(a.color)
|
||||
g.setFont(a.font, a.size)
|
||||
g.setFontAlign(1, -1) // right top
|
||||
// at right edge of screen, aligned with time bottom
|
||||
const left = screen.width - a.size * 2,
|
||||
top = t.middle + t.size - a.size
|
||||
g.drawString(ampmText(date), left, top, true)
|
||||
}
|
||||
|
||||
const d = settings.date
|
||||
g.setColor(d.color)
|
||||
g.setFont(d.font, d.size)
|
||||
g.setFontAlign(0, 0) // centered
|
||||
g.drawString(dateText(date), d.center, d.middle, true)
|
||||
}
|
||||
|
||||
const drawBar = function (date) {
|
||||
const b = settings.bar
|
||||
const seconds = date.getSeconds()
|
||||
if (seconds === 0) {
|
||||
// zero-size rect stills draws one line of pixels, we don't want that
|
||||
return
|
||||
}
|
||||
const fraction = seconds / SECONDS_PER_MINUTE,
|
||||
width = fraction * screen.width
|
||||
g.setColor(b.color)
|
||||
g.fillRect(0, b.top, width, b.top + b.thickness)
|
||||
}
|
||||
|
||||
const clearScreen = function () {
|
||||
g.setColor(0)
|
||||
const timeTop = settings.time.middle - (settings.time.size * 4)
|
||||
g.fillRect(0, timeTop, screen.width, screen.height)
|
||||
}
|
||||
|
||||
let lastSeconds, tTick
|
||||
const tick = function () {
|
||||
g.reset()
|
||||
const date = new Date()
|
||||
const seconds = date.getSeconds()
|
||||
if (lastSeconds > seconds) {
|
||||
// new minute
|
||||
clearScreen()
|
||||
drawDateTime(date)
|
||||
}
|
||||
// the bar only gets larger, so drawing on top of the previous one is fine
|
||||
drawBar(date)
|
||||
lastSeconds = seconds
|
||||
// schedule next update
|
||||
const millis = date.getMilliseconds()
|
||||
tTick = setTimeout(tick, 1000-millis)
|
||||
}
|
||||
|
||||
const start = function () {
|
||||
lastSeconds = 99 // force redraw
|
||||
tick()
|
||||
}
|
||||
const stop = function () {
|
||||
if (tTick) {
|
||||
clearTimeout(tTick)
|
||||
tTick = undefined
|
||||
}
|
||||
}
|
||||
|
||||
// clean app screen
|
||||
g.clear()
|
||||
Bangle.loadWidgets()
|
||||
Bangle.drawWidgets()
|
||||
// Show launcher when button pressed
|
||||
Bangle.setUI("clock");
|
||||
|
||||
Bangle.on('lcdPower', function (on) {
|
||||
if (on) {
|
||||
start()
|
||||
} else {
|
||||
stop()
|
||||
}
|
||||
})
|
||||
start()
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
0.01: App Created!
|
||||
0.02: Update to use Bangle.setUI instead of setWatch
|
||||
|
|
|
@ -256,8 +256,5 @@ Bangle.drawWidgets();
|
|||
timeInterval = setInterval(showTime, 1000);
|
||||
showTime();
|
||||
|
||||
// Show launcher when middle button pressed
|
||||
setWatch(Bangle.showLauncher, BTN2, {
|
||||
repeat: false,
|
||||
edge: "falling"
|
||||
});
|
||||
// Show launcher when button pressed
|
||||
Bangle.setUI("clock");
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
0.02: Modified for use with new bootloader and firmware
|
||||
0.03: Update to use Bangle.setUI instead of setWatch
|
||||
|
|
|
@ -105,5 +105,5 @@ Bangle.loadWidgets();
|
|||
Bangle.drawWidgets();
|
||||
setInterval(() => { drawClock(); }, 1000);
|
||||
drawClock();
|
||||
// Show launcher when middle button pressed
|
||||
setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"});
|
||||
// Show launcher when button pressed
|
||||
Bangle.setUI("clock");
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
0.01: Initial commit. Not very efficient, and widgets not working for some reason.
|
||||
0.02: Fixes; widget support
|
||||
0.03: Remove hardcoded hour buzz (you can install widchime if you miss it)
|
||||
0.04: Update to use Bangle.setUI instead of setWatch
|
||||
|
|
|
@ -51,341 +51,332 @@ Graphics.prototype.drawRotLine = function (sina, cosa, cx, cy, r1, r2) {
|
|||
);
|
||||
};
|
||||
|
||||
// Display modes
|
||||
//
|
||||
// 0: full-screen
|
||||
// 1: with widgets
|
||||
// 2: centred on Bangle (v.1), no widgets or time/date
|
||||
// 3: centred with time above
|
||||
// 4: centred with date above
|
||||
// 5: centred with time and date above
|
||||
let mode;
|
||||
|
||||
(function(g) {
|
||||
// Display modes
|
||||
//
|
||||
// 0: full-screen
|
||||
// 1: with widgets
|
||||
// 2: centred on Bangle (v.1), no widgets or time/date
|
||||
// 3: centred with time above
|
||||
// 4: centred with date above
|
||||
// 5: centred with time and date above
|
||||
let mode;
|
||||
// R1, R2: Outer and inner radii of hour marks
|
||||
// RC1, RC2: Outer and inner radii of hub
|
||||
// CX, CY: Centre location, relative to buffer (not screen, necessarily)
|
||||
// HW2, MW2: Half-width of hour and minute hand
|
||||
// HR, MR: Length of hour and minute hand, relative to CX,CY
|
||||
// M: Half-width of gap in hour marks
|
||||
// HSCALE: Half-width of hour mark as function(0<h<13)
|
||||
let R1, R2, RC1, RC2, CX, CY, HW2, MW2, HR, MR, M, HSCALE;
|
||||
|
||||
// R1, R2: Outer and inner radii of hour marks
|
||||
// RC1, RC2: Outer and inner radii of hub
|
||||
// CX, CY: Centre location, relative to buffer (not screen, necessarily)
|
||||
// HW2, MW2: Half-width of hour and minute hand
|
||||
// HR, MR: Length of hour and minute hand, relative to CX,CY
|
||||
// M: Half-width of gap in hour marks
|
||||
// HSCALE: Half-width of hour mark as function(0<h<13)
|
||||
let R1, R2, RC1, RC2, CX, CY, HW2, MW2, HR, MR, M, HSCALE;
|
||||
// Screen size
|
||||
const GW = g.getWidth();
|
||||
const GH = g.getHeight();
|
||||
|
||||
// Screen size
|
||||
const GW = g.getWidth();
|
||||
const GH = g.getHeight();
|
||||
// Top margin: the gap taken from the top of the buffer, except when
|
||||
// in mode 0 (full screen)
|
||||
let TM;
|
||||
|
||||
// Top margin: the gap taken from the top of the buffer, except when
|
||||
// in mode 0 (full screen)
|
||||
let TM;
|
||||
// Buffer image. undefined means it needs regenerating
|
||||
let faceImg;
|
||||
|
||||
// Buffer image. undefined means it needs regenerating
|
||||
let faceImg;
|
||||
// with_seconds flag determines whether the face is updated every
|
||||
// second or every minute, and to draw the hand or not.
|
||||
let with_seconds = true;
|
||||
|
||||
// with_seconds flag determines whether the face is updated every
|
||||
// second or every minute, and to draw the hand or not.
|
||||
let with_seconds = true;
|
||||
// Display flags, determined from `mode` by setMode()
|
||||
let with_widgets = false;
|
||||
let with_digital_time = true;
|
||||
let with_digital_date = true;
|
||||
|
||||
// Display flags, determined from `mode` by setMode()
|
||||
let with_widgets = false;
|
||||
let with_digital_time = true;
|
||||
let with_digital_date = true;
|
||||
// Create offscreen buffer for the once-per-minute face draw
|
||||
const G1 = Graphics.createArrayBuffer(g.getWidth(), g.getHeight(), 1, {msb:true});
|
||||
|
||||
// Create offscreen buffer for the once-per-minute face draw
|
||||
const G1 = Graphics.createArrayBuffer(g.getWidth(), g.getHeight(), 1, {msb:true});
|
||||
// Precalculate sin/cos for the hour marks. Might be premature
|
||||
// optimisation, but might as well.
|
||||
let ss = [], cs = [];
|
||||
for (let h=1; h<=12; h++) {
|
||||
const a = Math.PI * h / 6;
|
||||
ss[h] = Math.sin(a);
|
||||
cs[h] = Math.cos(a);
|
||||
}
|
||||
|
||||
// Precalculate sin/cos for the hour marks. Might be premature
|
||||
// optimisation, but might as well.
|
||||
let ss = [], cs = [];
|
||||
// Draw the face with hour and minute hand. Ideally, we'd separate
|
||||
// the face from the hands and double-buffer, but memory is limited,
|
||||
// so we buffer once and minute, and draw the second hand dynamically
|
||||
// (with a bit of flicker)
|
||||
const drawFace = (G) => {
|
||||
const fw = R1 * 2;
|
||||
const fh = R1 * 2;
|
||||
const fw2 = R1;
|
||||
const fh2 = R1;
|
||||
let hs = [];
|
||||
|
||||
// Wipe the image and start with white
|
||||
G.clear();
|
||||
G.setColor(1,1,1);
|
||||
|
||||
// Draw the hour marks.
|
||||
for (let h=1; h<=12; h++) {
|
||||
const a = Math.PI * h / 6;
|
||||
ss[h] = Math.sin(a);
|
||||
cs[h] = Math.cos(a);
|
||||
hs[h] = HSCALE(h);
|
||||
G.fillRotRect(ss[h], cs[h], CX, CY, -hs[h], hs[h], R2, R1);
|
||||
|
||||
}
|
||||
|
||||
// Draw the face with hour and minute hand. Ideally, we'd separate
|
||||
// the face from the hands and double-buffer, but memory is limited,
|
||||
// so we buffer once and minute, and draw the second hand dynamically
|
||||
// (with a bit of flicker)
|
||||
const drawFace = (G) => {
|
||||
const fw = R1 * 2;
|
||||
const fh = R1 * 2;
|
||||
const fw2 = R1;
|
||||
const fh2 = R1;
|
||||
let hs = [];
|
||||
// Draw the hub
|
||||
G.fillCircle(CX, CY, RC1);
|
||||
|
||||
// Wipe the image and start with white
|
||||
G.clear();
|
||||
G.setColor(1,1,1);
|
||||
// Black
|
||||
G.setColor(0,0,0);
|
||||
|
||||
// Draw the hour marks.
|
||||
for (let h=1; h<=12; h++) {
|
||||
hs[h] = HSCALE(h);
|
||||
G.fillRotRect(ss[h], cs[h], CX, CY, -hs[h], hs[h], R2, R1);
|
||||
// Clear the centre of the hub
|
||||
G.fillCircle(CX, CY, RC2);
|
||||
|
||||
// Draw the gap in the hour marks
|
||||
for (let h=1; h<=12; h++) {
|
||||
G.fillRotRect(ss[h], cs[h], CX, CY, -M, M, R2-1, R1+1);
|
||||
}
|
||||
|
||||
// Back to white for future draw operations
|
||||
G.setColor(1,1,1);
|
||||
|
||||
// While the buffer remains full-screen, we may trim out the
|
||||
// bottom of the image so we can shift the whole thing down for
|
||||
// widgets.
|
||||
const img = {width:GW,height:GH-TM,buffer:G.buffer};
|
||||
return img;
|
||||
};
|
||||
|
||||
let hours, minutes, seconds, date;
|
||||
|
||||
// Schedule event for calling at the start of the next second
|
||||
const inOneSecond = (cb) => {
|
||||
let now = new Date();
|
||||
clearTimeout();
|
||||
setTimeout(cb, 1000 - now.getMilliseconds());
|
||||
};
|
||||
|
||||
// Schedule event for calling at the start of the next minute
|
||||
const inOneMinute = (cb) => {
|
||||
let now = new Date();
|
||||
clearTimeout();
|
||||
setTimeout(cb, 60000 - (now.getSeconds() * 1000 + now.getMilliseconds()));
|
||||
};
|
||||
|
||||
// Draw a fat hour/minute hand
|
||||
const drawHand = (G, a, w2, r1, r2) =>
|
||||
G.fillRotRect(Math.sin(a), Math.cos(a), CX, CY, -w2, w2, r1, r2);
|
||||
|
||||
// Redraw function
|
||||
const drawAll = (force) => {
|
||||
let now = new Date();
|
||||
|
||||
if (!faceImg) force = true;
|
||||
|
||||
let face_changed = force;
|
||||
let date_changed = false;
|
||||
|
||||
tmp = hours;
|
||||
hours = now.getHours();
|
||||
if (tmp !== hours)
|
||||
face_changed = true;
|
||||
|
||||
tmp = minutes;
|
||||
minutes = now.getMinutes();
|
||||
if (tmp !== minutes)
|
||||
face_changed = true;
|
||||
|
||||
// If the face has been updated and/or needs a redraw,
|
||||
// face_changed is true.
|
||||
|
||||
let time_changed = face_changed;
|
||||
|
||||
// If the screen needs an update, regardless of whether the face
|
||||
// needs a redraw, time_changed is true.
|
||||
|
||||
if (with_seconds) {
|
||||
// If we're going by second, we always need an update.
|
||||
seconds = now.getSeconds();
|
||||
time_changed = true;
|
||||
}
|
||||
|
||||
if (with_digital_date) {
|
||||
// See if the date has changed. If it has, then we need a
|
||||
// full-blown redraw of the screen and the face, plus text.
|
||||
tmp = date;
|
||||
date = now.getDate();
|
||||
if (tmp !== date) {
|
||||
date_changed = true;
|
||||
face_changed = true; // Should have changed anyway with hour/minute rollover
|
||||
}
|
||||
}
|
||||
|
||||
if (face_changed) {
|
||||
// Redraw the face and hands onto the buffer G1.
|
||||
faceImg = drawFace(G1);
|
||||
drawHand(G1, Math.PI*hours/6, HW2, RC1, HR);
|
||||
drawHand(G1, Math.PI*minutes/30, MW2, RC1, MR);
|
||||
}
|
||||
|
||||
// Has the time updated? If so, we'll need to draw something.
|
||||
if (time_changed) {
|
||||
|
||||
// Are we adding text?
|
||||
if (with_digital_date || with_digital_time) {
|
||||
|
||||
// Construct the date/time text to add above the face
|
||||
let d = now.toString();
|
||||
let da = d.toString().split(" ");
|
||||
let txt;
|
||||
|
||||
if (with_digital_time) {
|
||||
txt = da[4].substr(0, 5);
|
||||
if (with_digital_date)
|
||||
G1.drawStringDH(txt+',', 24, 0, 'L', GW);
|
||||
else
|
||||
G1.drawStringDH(txt, 0, 0, 'C', GW);
|
||||
}
|
||||
|
||||
if (with_digital_date) {
|
||||
let txt = [da[0], da[1], da[2]].join(" ");
|
||||
if (with_digital_time)
|
||||
G1.drawStringDH(txt, -24, 0, 'R', GW);
|
||||
else
|
||||
G1.drawStringDH(txt, 0, 0, 'C', GW);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the hub
|
||||
G.fillCircle(CX, CY, RC1);
|
||||
|
||||
// Black
|
||||
G.setColor(0,0,0);
|
||||
|
||||
// Clear the centre of the hub
|
||||
G.fillCircle(CX, CY, RC2);
|
||||
|
||||
// Draw the gap in the hour marks
|
||||
for (let h=1; h<=12; h++) {
|
||||
G.fillRotRect(ss[h], cs[h], CX, CY, -M, M, R2-1, R1+1);
|
||||
}
|
||||
|
||||
// Back to white for future draw operations
|
||||
G.setColor(1,1,1);
|
||||
|
||||
// While the buffer remains full-screen, we may trim out the
|
||||
// bottom of the image so we can shift the whole thing down for
|
||||
// widgets.
|
||||
const img = {width:GW,height:GH-TM,buffer:G.buffer};
|
||||
return img;
|
||||
};
|
||||
|
||||
let hours, minutes, seconds, date;
|
||||
|
||||
// Schedule event for calling at the start of the next second
|
||||
const inOneSecond = (cb) => {
|
||||
let now = new Date();
|
||||
clearTimeout();
|
||||
setTimeout(cb, 1000 - now.getMilliseconds());
|
||||
};
|
||||
|
||||
// Schedule event for calling at the start of the next minute
|
||||
const inOneMinute = (cb) => {
|
||||
let now = new Date();
|
||||
clearTimeout();
|
||||
setTimeout(cb, 60000 - (now.getSeconds() * 1000 + now.getMilliseconds()));
|
||||
};
|
||||
|
||||
// Draw a fat hour/minute hand
|
||||
const drawHand = (G, a, w2, r1, r2) =>
|
||||
G.fillRotRect(Math.sin(a), Math.cos(a), CX, CY, -w2, w2, r1, r2);
|
||||
|
||||
// Redraw function
|
||||
const drawAll = (force) => {
|
||||
let now = new Date();
|
||||
|
||||
if (!faceImg) force = true;
|
||||
|
||||
let face_changed = force;
|
||||
let date_changed = false;
|
||||
|
||||
tmp = hours;
|
||||
hours = now.getHours();
|
||||
if (tmp !== hours)
|
||||
face_changed = true;
|
||||
|
||||
tmp = minutes;
|
||||
minutes = now.getMinutes();
|
||||
if (tmp !== minutes)
|
||||
face_changed = true;
|
||||
|
||||
// If the face has been updated and/or needs a redraw,
|
||||
// face_changed is true.
|
||||
|
||||
let time_changed = face_changed;
|
||||
|
||||
// If the screen needs an update, regardless of whether the face
|
||||
// needs a redraw, time_changed is true.
|
||||
// If the time has updated, we need to _at least_ draw the
|
||||
// image to the screen.
|
||||
g.setColor(1,1,1);
|
||||
g.drawImage({width:GW,
|
||||
height:GH-TM,
|
||||
buffer:G1.buffer}, 0, TM);
|
||||
|
||||
// and possibly add the second hand
|
||||
if (with_seconds) {
|
||||
// If we're going by second, we always need an update.
|
||||
seconds = now.getSeconds();
|
||||
time_changed = true;
|
||||
let a = 2.0 * Math.PI * seconds / 60.0;
|
||||
g.drawRotLine(Math.sin(a), Math.cos(a), CX, CY+TM, RC1, R1);
|
||||
}
|
||||
|
||||
if (with_digital_date) {
|
||||
// See if the date has changed. If it has, then we need a
|
||||
// full-blown redraw of the screen and the face, plus text.
|
||||
tmp = date;
|
||||
date = now.getDate();
|
||||
if (tmp !== date) {
|
||||
date_changed = true;
|
||||
face_changed = true; // Should have changed anyway with hour/minute rollover
|
||||
}
|
||||
}
|
||||
// And draw widgets if we're in that mode
|
||||
if (with_widgets)
|
||||
Bangle.drawWidgets();
|
||||
}
|
||||
|
||||
if (face_changed) {
|
||||
// Redraw the face and hands onto the buffer G1.
|
||||
faceImg = drawFace(G1);
|
||||
drawHand(G1, Math.PI*hours/6, HW2, RC1, HR);
|
||||
drawHand(G1, Math.PI*minutes/30, MW2, RC1, MR);
|
||||
}
|
||||
// Schedule to repeat this. A `setTimeout(1000)` isn't good
|
||||
// enough, as all the above might've taken some milliseconds and
|
||||
// we don't want to drift.
|
||||
if (with_seconds)
|
||||
inOneSecond(drawAll);
|
||||
else
|
||||
inOneMinute(drawAll);
|
||||
};
|
||||
|
||||
// Has the time updated? If so, we'll need to draw something.
|
||||
if (time_changed) {
|
||||
const setButtons = () => {
|
||||
// Show launcher when button pressed
|
||||
Bangle.setUI("clockupdown", btn=> {
|
||||
if (btn==0) changeSeconds();
|
||||
if (btn==1) { ++mode; setMode(); drawAll(true); }
|
||||
});
|
||||
};
|
||||
|
||||
// Are we adding text?
|
||||
if (with_digital_date || with_digital_time) {
|
||||
// Load display parameters based on `mode`
|
||||
const setMode = () => {
|
||||
// Normalize mode to 0 <= mode <= 5
|
||||
mode = (6+mode) % 6;
|
||||
|
||||
// Construct the date/time text to add above the face
|
||||
let d = now.toString();
|
||||
let da = d.toString().split(" ");
|
||||
let txt;
|
||||
// [R1, R2, RC1, RC2, HW2, MW3, HR, MR, M, HSCALE] =
|
||||
const scales = [
|
||||
[120, 84, 17, 12.4, 4.6, 2.2, 8, 2, 1, h => (3.0 + Math.ceil(h/1.5)) ],
|
||||
[102, 70, 14.6, 10.7, 3.88, 1.8, 8, 2, 1, h => (2.4 + Math.ceil(h/1.6)) ],
|
||||
];
|
||||
|
||||
if (with_digital_time) {
|
||||
txt = da[4].substr(0, 5);
|
||||
if (with_digital_date)
|
||||
G1.drawStringDH(txt+',', 24, 0, 'L', GW);
|
||||
else
|
||||
G1.drawStringDH(txt, 0, 0, 'C', GW);
|
||||
}
|
||||
if (mode < 3) {
|
||||
// Face without time/date text. Might have widgets though.
|
||||
with_digital_time = with_digital_date = false;
|
||||
with_widgets = (mode == 1);
|
||||
}
|
||||
else {
|
||||
// Face with time/date text, but no widgets
|
||||
with_digital_time = (mode-2)&1;
|
||||
with_digital_date = (mode-2)&2;
|
||||
with_widgets = false;
|
||||
}
|
||||
|
||||
if (with_digital_date) {
|
||||
let txt = [da[0], da[1], da[2]].join(" ");
|
||||
if (with_digital_time)
|
||||
G1.drawStringDH(txt, -24, 0, 'R', GW);
|
||||
else
|
||||
G1.drawStringDH(txt, 0, 0, 'C', GW);
|
||||
}
|
||||
}
|
||||
// Destructure the array to the global display parameters
|
||||
let arr = scales[mode > 0 ? 1 : 0];
|
||||
R1 = arr[0];
|
||||
R2 = arr[1];
|
||||
RC1 = arr[2];
|
||||
RC2 = arr[3];
|
||||
HW2 = arr[4];
|
||||
MW2 = arr[5];
|
||||
HR = R2 - arr[6];
|
||||
MR = R1 - arr[7];
|
||||
M = arr[8];
|
||||
HSCALE = arr[9];
|
||||
TM = with_widgets ? 36 : 0;
|
||||
|
||||
// If the time has updated, we need to _at least_ draw the
|
||||
// image to the screen.
|
||||
g.setColor(1,1,1);
|
||||
g.drawImage({width:GW,
|
||||
height:GH-TM,
|
||||
buffer:G1.buffer}, 0, TM);
|
||||
CX = GW/2;
|
||||
CY = R1;
|
||||
|
||||
// and possibly add the second hand
|
||||
if (with_seconds) {
|
||||
let a = 2.0 * Math.PI * seconds / 60.0;
|
||||
g.drawRotLine(Math.sin(a), Math.cos(a), CX, CY+TM, RC1, R1);
|
||||
}
|
||||
// If we're in the small-face + text regime, we're going to buffer
|
||||
// the full screen but draw the clock face further down to give
|
||||
// space for the text.
|
||||
//
|
||||
// Compare with modes 0 (full-screen) and 1 (with_widgets==true)
|
||||
// where the face is drawn at the top of the buffer, but drawn
|
||||
// lower down the screen (so CY doesn't move)
|
||||
if (mode > 1) {
|
||||
CY += 36;
|
||||
}
|
||||
|
||||
// And draw widgets if we're in that mode
|
||||
if (with_widgets)
|
||||
Bangle.drawWidgets();
|
||||
}
|
||||
// We only don't bother redrawing the face from modes 2 to 5, as
|
||||
// they're the same.
|
||||
if (!faceImg || mode<3) {
|
||||
faceImg = undefined;
|
||||
}
|
||||
|
||||
// Schedule to repeat this. A `setTimeout(1000)` isn't good
|
||||
// enough, as all the above might've taken some milliseconds and
|
||||
// we don't want to drift.
|
||||
if (with_seconds)
|
||||
inOneSecond(drawAll);
|
||||
else
|
||||
inOneMinute(drawAll);
|
||||
};
|
||||
|
||||
const setButtons = () => {
|
||||
const opts = { repeat: true, edge:'rising', debounce:30};
|
||||
|
||||
// BTN1: enable/disable second hand
|
||||
setWatch(changeSeconds, BTN1, opts);
|
||||
|
||||
// BTN2: return to launcher
|
||||
setWatch(Bangle.showLauncher, BTN2, { repeat:false, edge:'falling' });
|
||||
|
||||
// BTN3: change display mode
|
||||
setWatch(function () { ++mode; setMode(); drawAll(true); }, BTN3, opts);
|
||||
};
|
||||
|
||||
// Load display parameters based on `mode`
|
||||
const setMode = () => {
|
||||
// Normalize mode to 0 <= mode <= 5
|
||||
mode = (6+mode) % 6;
|
||||
|
||||
// [R1, R2, RC1, RC2, HW2, MW3, HR, MR, M, HSCALE] =
|
||||
const scales = [
|
||||
[120, 84, 17, 12.4, 4.6, 2.2, 8, 2, 1, h => (3.0 + Math.ceil(h/1.5)) ],
|
||||
[102, 70, 14.6, 10.7, 3.88, 1.8, 8, 2, 1, h => (2.4 + Math.ceil(h/1.6)) ],
|
||||
];
|
||||
|
||||
if (mode < 3) {
|
||||
// Face without time/date text. Might have widgets though.
|
||||
with_digital_time = with_digital_date = false;
|
||||
with_widgets = (mode == 1);
|
||||
}
|
||||
else {
|
||||
// Face with time/date text, but no widgets
|
||||
with_digital_time = (mode-2)&1;
|
||||
with_digital_date = (mode-2)&2;
|
||||
with_widgets = false;
|
||||
}
|
||||
|
||||
// Destructure the array to the global display parameters
|
||||
let arr = scales[mode > 0 ? 1 : 0];
|
||||
R1 = arr[0];
|
||||
R2 = arr[1];
|
||||
RC1 = arr[2];
|
||||
RC2 = arr[3];
|
||||
HW2 = arr[4];
|
||||
MW2 = arr[5];
|
||||
HR = R2 - arr[6];
|
||||
MR = R1 - arr[7];
|
||||
M = arr[8];
|
||||
HSCALE = arr[9];
|
||||
TM = with_widgets ? 36 : 0;
|
||||
|
||||
CX = GW/2;
|
||||
CY = R1;
|
||||
|
||||
// If we're in the small-face + text regime, we're going to buffer
|
||||
// the full screen but draw the clock face further down to give
|
||||
// space for the text.
|
||||
//
|
||||
// Compare with modes 0 (full-screen) and 1 (with_widgets==true)
|
||||
// where the face is drawn at the top of the buffer, but drawn
|
||||
// lower down the screen (so CY doesn't move)
|
||||
if (mode > 1) {
|
||||
CY += 36;
|
||||
}
|
||||
|
||||
// We only don't bother redrawing the face from modes 2 to 5, as
|
||||
// they're the same.
|
||||
if (!faceImg || mode<3) {
|
||||
faceImg = undefined;
|
||||
}
|
||||
|
||||
// Store the settings for next time
|
||||
try {
|
||||
storage.writeJSON(filename, [mode,with_seconds]);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
// Clear the screen: we need to make sure all parts are cleaned off.
|
||||
g.clear();
|
||||
};
|
||||
|
||||
const changeSeconds = () => {
|
||||
with_seconds = !with_seconds;
|
||||
drawAll(true);
|
||||
};
|
||||
|
||||
Bangle.loadWidgets();
|
||||
|
||||
// Restore mode
|
||||
// Store the settings for next time
|
||||
try {
|
||||
conf = storage.readJSON(filename);
|
||||
mode = conf[0];
|
||||
with_seconds = conf[1];
|
||||
storage.writeJSON(filename, [mode,with_seconds]);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
mode = 1;
|
||||
}
|
||||
|
||||
setButtons();
|
||||
setMode();
|
||||
drawAll();
|
||||
// Clear the screen: we need to make sure all parts are cleaned off.
|
||||
g.clear();
|
||||
};
|
||||
|
||||
Bangle.on('lcdPower', (on) => {
|
||||
if (on) {
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
drawAll();
|
||||
} else {
|
||||
clearTimeout();
|
||||
}
|
||||
});
|
||||
const changeSeconds = () => {
|
||||
with_seconds = !with_seconds;
|
||||
drawAll(true);
|
||||
};
|
||||
|
||||
})(g);
|
||||
Bangle.loadWidgets();
|
||||
|
||||
// Restore mode
|
||||
try {
|
||||
conf = storage.readJSON(filename);
|
||||
mode = conf[0];
|
||||
with_seconds = conf[1];
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
mode = 1;
|
||||
}
|
||||
|
||||
setButtons();
|
||||
setMode();
|
||||
drawAll();
|
||||
|
||||
Bangle.on('lcdPower', (on) => {
|
||||
if (on) {
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
drawAll();
|
||||
} else {
|
||||
clearTimeout();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
0.02: Modified for use with new bootloader and firmware
|
||||
0.03: Shrinked size to avoid cut-off edges on the physical device. BTN3: show date. BTN1: show time in decimal.
|
||||
0.04: Update to use Bangle.setUI instead of setWatch
|
||||
|
|
|
@ -16,7 +16,7 @@ time_digit = [];
|
|||
function drawBerlinClock() {
|
||||
g.clear();
|
||||
var now = new Date();
|
||||
|
||||
|
||||
// show date below the clock
|
||||
if (show_date) {
|
||||
var yr = now.getFullYear();
|
||||
|
@ -28,7 +28,7 @@ function drawBerlinClock() {
|
|||
g.setFontAlign(-1,-1);
|
||||
g.drawString(dateString, ( g.getWidth() - strWidth ) / 2, height + offset + 4);
|
||||
}
|
||||
|
||||
|
||||
rowlights[0] = Math.floor(now.getHours() / 5);
|
||||
rowlights[1] = now.getHours() % 5;
|
||||
rowlights[2] = Math.floor(now.getMinutes() / 5);
|
||||
|
@ -62,7 +62,7 @@ function drawBerlinClock() {
|
|||
} else {
|
||||
g.setColor(1, 0, 0);
|
||||
}
|
||||
g.fillRect(x1 + 2, y1 + 2, x2 - 2, y2 - 2);
|
||||
g.fillRect(x1 + 2, y1 + 2, x2 - 2, y2 - 2);
|
||||
}
|
||||
if (row == 3 && show_time) {
|
||||
g.setColor(1,1,1);
|
||||
|
@ -100,9 +100,11 @@ g.clear();
|
|||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
drawBerlinClock();
|
||||
// Toggle date display, when BTN3 is pressed
|
||||
setWatch(toggleTime,BTN1, { repeat : true, edge: "falling"});
|
||||
// Toggle date display, when BTN3 is pressed
|
||||
setWatch(toggleDate,BTN3, { repeat : true, edge: "falling"});
|
||||
// Show launcher when middle button pressed
|
||||
setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" });
|
||||
if (BTN3) {
|
||||
// Toggle date display, when BTN3 is pressed
|
||||
setWatch(toggleTime,BTN1, { repeat : true, edge: "falling"});
|
||||
// Toggle date display, when BTN3 is pressed
|
||||
setWatch(toggleDate,BTN3, { repeat : true, edge: "falling"});
|
||||
}
|
||||
// Show launcher when button pressed
|
||||
Bangle.setUI("clock");
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
0.01: New App!
|
||||
0.02: Fixed bug where screen didn't clear so incorrect time displayed.
|
||||
0.03: Update to use Bangle.setUI instead of setWatch
|
||||
|
|
|
@ -23,17 +23,17 @@ function drawTime(d) {
|
|||
}
|
||||
|
||||
function updateHourArray(hours){
|
||||
|
||||
|
||||
var j;
|
||||
for(j=0;j<hourLED.length;j++){
|
||||
prevHour[j] = hourLED[j];
|
||||
}
|
||||
|
||||
|
||||
var i;
|
||||
for(i = 0;i < hourLED.length;i++){
|
||||
hourLED[i]=0;
|
||||
hourLED[i]=0;
|
||||
}
|
||||
|
||||
|
||||
if(hours > 15){
|
||||
hourLED[0] = 1;
|
||||
hours = hours - 16;
|
||||
|
@ -53,9 +53,9 @@ function updateHourArray(hours){
|
|||
if(hours > 0){
|
||||
hourLED[4] = 1;
|
||||
}
|
||||
|
||||
|
||||
return hourLED;
|
||||
|
||||
|
||||
}
|
||||
|
||||
function updateMinuteArray(minutes){
|
||||
|
@ -63,12 +63,12 @@ function updateMinuteArray(minutes){
|
|||
for(j=0;j<minuteLED.length;j++){
|
||||
prevMinute[j] = minuteLED[j];
|
||||
}
|
||||
|
||||
|
||||
var i;
|
||||
for(i = 0;i < minuteLED.length;i++){
|
||||
minuteLED[i]=0;
|
||||
minuteLED[i]=0;
|
||||
}
|
||||
|
||||
|
||||
if(minutes > 31){
|
||||
minuteLED[0] = 1;
|
||||
minutes = minutes - 32;
|
||||
|
@ -92,20 +92,20 @@ function updateMinuteArray(minutes){
|
|||
if(minutes > 0){
|
||||
minuteLED[5] = 1;
|
||||
}
|
||||
|
||||
|
||||
return minuteLED;
|
||||
|
||||
|
||||
}
|
||||
|
||||
function draw(){
|
||||
|
||||
|
||||
// work out how to display the current time
|
||||
var d = new Date();
|
||||
var h = d.getHours(), m = d.getMinutes();
|
||||
|
||||
|
||||
updateHourArray(h);
|
||||
updateMinuteArray(m);
|
||||
|
||||
|
||||
var i;
|
||||
//Draw hour circles
|
||||
for(i=0; i<hourLED.length; i++){
|
||||
|
@ -118,10 +118,10 @@ function draw(){
|
|||
g.fillCircle(24+i*48,50,10);
|
||||
g.setColor(colour);
|
||||
g.drawCircle(24+i*48,50,10);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for(i=0; i<minuteLED.length; i++){
|
||||
if(prevMinute[i] == minuteLED[i]){
|
||||
if(minuteLED[i] == 1){
|
||||
|
@ -132,21 +132,21 @@ function draw(){
|
|||
g.fillCircle(20+i*40,100,10);
|
||||
g.setColor(colour);
|
||||
g.drawCircle(20+i*40,100,10);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// draw the date, in a normal font
|
||||
g.setFont("6x8");
|
||||
g.setFontAlign(0,1); // align center bottom
|
||||
// pad the date - this clears the background if the date were to change length
|
||||
var dateStr = " "+require("locale").date(d)+" ";
|
||||
g.drawString(dateStr, g.getWidth()/2, 130, true /*clear background*/);
|
||||
|
||||
|
||||
if(displayTime){
|
||||
drawTime(d);
|
||||
}else{
|
||||
g.clearRect(0,240,240,130);
|
||||
g.clearRect(0,240,240,130);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -167,12 +167,12 @@ Bangle.on('lcdPower',on=>{
|
|||
// Load widgets
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
// Show launcher when middle button pressed
|
||||
setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" });
|
||||
setWatch(function() {
|
||||
// Show launcher when button pressed
|
||||
Bangle.setUI("clockupdown", btn=>{
|
||||
if (btn!=1) return;
|
||||
if(displayTime == 0){
|
||||
displayTime = 1;
|
||||
} else{
|
||||
displayTime = 0;
|
||||
displayTime = 0;
|
||||
}
|
||||
}, BTN, {edge:"rising", debounce:50, repeat:true});
|
||||
});
|
||||
|
|
|
@ -4,3 +4,4 @@
|
|||
0.03: Modified for use with new bootloader and firmware
|
||||
0.04: Modified to account for changes in the behavior of Graphics.fillPoly
|
||||
0.05: Slight increase to draw speed after LCD on
|
||||
0.06: Update to use Bangle.setUI instead of setWatch, allow themes and different size screens
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
const buf = Graphics.createArrayBuffer(144,200,1,{msb:true});
|
||||
let big = g.getHeight() > 200;
|
||||
const buf = Graphics.createArrayBuffer(big ? 144 : 120, big ? 180 : 150,1,{msb:true});
|
||||
// TODO: convert these to Polys -> much faster and cleaner!
|
||||
const NUMBERS = [
|
||||
[1,1,1,1,3,1,1,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1],//0
|
||||
[0,1,1,1,3,0,0,1,1,1,0,0,1,1,1,0,0,1,1,1,0,0,1,1,1],//1
|
||||
|
@ -14,8 +16,10 @@ const NUMBERS = [
|
|||
let intervalRef = null;
|
||||
let digits = [-1,-1,-1,-1,-1,-1];
|
||||
function flip() {
|
||||
g.setColor(1,1,1);
|
||||
g.drawImage({width:buf.getWidth(),height:buf.getHeight(),buffer:buf.buffer},55,26);
|
||||
g.reset();
|
||||
g.drawImage({width:buf.getWidth(),height:buf.getHeight(),buffer:buf.buffer},
|
||||
(g.getWidth() - buf.getWidth())/2,
|
||||
26 + (g.getHeight() - (buf.getHeight()+24))/2);
|
||||
}
|
||||
function drawPixel(ox,oy,x,y,r,p) {
|
||||
let x1 = ox+x*(r*2);
|
||||
|
@ -53,26 +57,31 @@ function redraw() {
|
|||
|
||||
let newDigits = [Math.floor(hours/10),hours%10,Math.floor(mins/10),mins%10,Math.floor(secs/10),secs%10];
|
||||
|
||||
let s = big?6:5; // size of main digits
|
||||
let y2 = big?72:55;
|
||||
let y3 = big?144:110;
|
||||
|
||||
|
||||
for (var p = 0;p<25;p++) {
|
||||
var px = p%5;
|
||||
var py = Math.floor(p/5);
|
||||
if (digits[0] === -1 || NUMBERS[newDigits[0]][p] !== NUMBERS[digits[0]][p] ) {
|
||||
drawPixel(0,20,px,py,6,NUMBERS[newDigits[0]][p]);
|
||||
drawPixel(0,0,px,py,s,NUMBERS[newDigits[0]][p]);
|
||||
}
|
||||
if (digits[1] === -1 || NUMBERS[newDigits[1]][p] !== NUMBERS[digits[1]][p] ) {
|
||||
drawPixel(78,20,px,py,6,NUMBERS[newDigits[1]][p]);
|
||||
drawPixel(13*s,0,px,py,s,NUMBERS[newDigits[1]][p]);
|
||||
}
|
||||
if (digits[2] === -1 || NUMBERS[newDigits[2]][p] !== NUMBERS[digits[2]][p] ) {
|
||||
drawPixel(0,92,px,py,6,NUMBERS[newDigits[2]][p]);
|
||||
drawPixel(0,y2,px,py,s,NUMBERS[newDigits[2]][p]);
|
||||
}
|
||||
if (digits[3] === -1 || NUMBERS[newDigits[3]][p] !== NUMBERS[digits[3]][p] ) {
|
||||
drawPixel(78,92,px,py,6,NUMBERS[newDigits[3]][p]);
|
||||
drawPixel(13*s,y2,px,py,s,NUMBERS[newDigits[3]][p]);
|
||||
}
|
||||
if (digits[4] === -1 || NUMBERS[newDigits[4]][p] !== NUMBERS[digits[4]][p] ) {
|
||||
drawPixel(69,164,px,py,3,NUMBERS[newDigits[4]][p]);
|
||||
drawPixel(17*s - 3*12,y3,px,py,3,NUMBERS[newDigits[4]][p]);
|
||||
}
|
||||
if (digits[5] === -1 || NUMBERS[newDigits[5]][p] !== NUMBERS[digits[5]][p] ) {
|
||||
drawPixel(108,164,px,py,3,NUMBERS[newDigits[5]][p]);
|
||||
drawPixel(17*s,y3,px,py,3,NUMBERS[newDigits[5]][p]);
|
||||
}
|
||||
}
|
||||
digits = newDigits;
|
||||
|
@ -99,5 +108,5 @@ Bangle.on('lcdPower',function(on) {
|
|||
clearTimers();
|
||||
}
|
||||
});
|
||||
// Show launcher when middle button pressed
|
||||
setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"});
|
||||
// Show launcher when button pressed
|
||||
Bangle.setUI("clock");
|
||||
|
|
|
@ -25,3 +25,4 @@
|
|||
0.24: Add Bangle.setUI polyfill
|
||||
0.25: Fix error in 'no clock app' message
|
||||
0.26: Remove buzz in setUI polyfill (#750)
|
||||
0.27: Update polyfill for most recent changes
|
||||
|
|
|
@ -3,6 +3,7 @@ recalculates, but this avoids us doing a whole bunch of reconfiguration most
|
|||
of the time. */
|
||||
E.showMessage("Updating boot0...");
|
||||
var s = require('Storage').readJSON('setting.json',1)||{};
|
||||
var isB2 = process.env.HWVERSION; // Is Bangle.js 2
|
||||
var boot = "";
|
||||
var CRC = E.CRC32(require('Storage').read('setting.json'))+E.CRC32(require('Storage').list(/\.boot\.js/));
|
||||
boot += `if (E.CRC32(require('Storage').read('setting.json'))+E.CRC32(require('Storage').list(/\.boot\.js/))!=${CRC}) { eval(require('Storage').read('bootupdate.js'));} else {\n`;
|
||||
|
@ -81,9 +82,9 @@ if (s.passkey!==undefined && s.passkey.length==6) boot+=`NRF.setSecurity({passke
|
|||
if (s.whitelist) boot+=`NRF.on('connect', function(addr) { if (!(require('Storage').readJSON('setting.json',1)||{}).whitelist.includes(addr)) NRF.disconnect(); });\n`;
|
||||
// Pre-2v10 firmwares without a theme/setUI
|
||||
if (!g.theme) {
|
||||
boot += `g.theme={fg:-1,bg:0,fg2:-1,bg2:7,fgH:-1,bgH:0x02F7};\n`;
|
||||
boot += `g.theme={fg:-1,bg:0,fg2:-1,bg2:7,fgH:-1,bgH:0x02F7,dark:true};\n`;
|
||||
}
|
||||
if (!Bangle.setUI) {
|
||||
if (!Bangle.setUI) { // assume this is just for F18 - Q3 should already have it
|
||||
boot += `Bangle.setUI=function(mode, cb) {
|
||||
if (Bangle.btnWatches) {
|
||||
Bangle.btnWatches.forEach(clearWatch);
|
||||
|
@ -114,6 +115,18 @@ else if (mode=="updown") {
|
|||
Bangle.on("swipe", Bangle.swipeHandler);
|
||||
Bangle.touchHandler = d => {cb();};
|
||||
Bangle.on("touch", Bangle.touchHandler);
|
||||
} else if (mode=="clock") {
|
||||
Bangle.CLOCK=1;
|
||||
Bangle.btnWatches = [
|
||||
setWatch(Bangle.showLauncher, BTN2, {repeat:1,edge:"falling"})
|
||||
];
|
||||
} else if (mode=="clockupdown") {
|
||||
Bangle.CLOCK=1;
|
||||
Bangle.btnWatches = [
|
||||
setWatch(function() { cb(-1); }, BTN1, {repeat:1}),
|
||||
setWatch(function() { cb(1); }, BTN3, {repeat:1}),
|
||||
setWatch(Bangle.showLauncher, BTN2, {repeat:1,edge:"falling"})
|
||||
];
|
||||
} else
|
||||
throw new Error("Unknown UI mode");
|
||||
};\n`;
|
||||
|
|
|
@ -6,3 +6,4 @@
|
|||
0.06: Improve rendering of Numeral 1, fix issue with alarms not showing up
|
||||
0.07: Add date on touch and some improvements (see settings and readme)
|
||||
0.08: Add new draw styles, tidy up draw functionality
|
||||
0.09: Tweak for faster rendering
|
||||
|
|
|
@ -22,16 +22,17 @@ var _12hour = (require("Storage").readJSON("setting.json",1)||{})["12hour"]||fal
|
|||
var _hCol = ["#ff5555","#ffff00","#FF9901","#2F00FF"];
|
||||
var _mCol = ["#55ff55","#ffffff","#00EFEF","#FFBF00"];
|
||||
var _rCol = 0;
|
||||
var scale = g.getWidth()/240;
|
||||
var interval = 0;
|
||||
const REFRESH_RATE = 10E3;
|
||||
var drawFuncs = {
|
||||
fill : function(poly,isHole){
|
||||
if (isHole) g.setColor(0);
|
||||
if (isHole) g.setColor(g.theme.bg);
|
||||
g.fillPoly(poly,true);
|
||||
},
|
||||
framefill : function(poly,isHole){
|
||||
var c = g.getColor();
|
||||
g.setColor(isHole ? 0 : ((c&0b1111011111011110)>>1)); // 16 bit half bright
|
||||
g.setColor(isHole ? g.theme.bg : ((c&0b1111011111011110)>>1)); // 16 bit half bright
|
||||
g.fillPoly(poly,true);
|
||||
g.setColor(c);
|
||||
g.drawPoly(poly,true);
|
||||
|
@ -48,7 +49,8 @@ var drawFuncs = {
|
|||
};
|
||||
|
||||
function translate(tx, ty, p){
|
||||
return p.map((x, i)=> x+((i&1)?ty:tx));
|
||||
//return p.map((x, i)=> x+((i&1)?ty:tx));
|
||||
return g.transformVertices(p, {x:tx,y:ty,scale:scale});
|
||||
}
|
||||
|
||||
|
||||
|
@ -57,15 +59,14 @@ if (!settings) {
|
|||
settings = {
|
||||
color:0,
|
||||
drawMode:"fill",
|
||||
menuButton:24,
|
||||
showDate:0
|
||||
};
|
||||
}
|
||||
|
||||
function drawNum(num,col,x,y,func,funcName){
|
||||
g.setColor(col);
|
||||
let tx = x*100+25;
|
||||
let ty = y*104+32;
|
||||
let tx = (x*100+25) * scale;
|
||||
let ty = (y*104+32) * scale;
|
||||
for (let i=0;i<numerals[num].length;i++){
|
||||
g.setColor(col);
|
||||
func(translate(tx,ty,numerals[num][i]), i>0);
|
||||
|
@ -98,9 +99,9 @@ function setUpdateInt(set){
|
|||
if (set) interval=setInterval(draw, REFRESH_RATE);
|
||||
}
|
||||
|
||||
Bangle.setLCDMode();
|
||||
g.reset().clear();
|
||||
setWatch(Bangle.showLauncher, settings.menuButton, {repeat:false,edge:"falling"});
|
||||
g.clear(1);
|
||||
// Show launcher when button pressed
|
||||
Bangle.setUI("clock");
|
||||
if (settings.color>0) _rCol=settings.color-1;
|
||||
setUpdateInt(1);
|
||||
draw();
|
||||
|
|
|
@ -6,14 +6,12 @@
|
|||
numeralsSettings = {
|
||||
color:0,
|
||||
drawMode:"fill",
|
||||
menuButton:22,
|
||||
showDate:0
|
||||
};
|
||||
updateSettings();
|
||||
}
|
||||
let numeralsSettings = storage.readJSON('numerals.json',1);
|
||||
if (!numeralsSettings) resetSettings();
|
||||
if (numeralsSettings.menuButton===undefined) numeralsSettings.menuButton=22;
|
||||
let dm = ["fill","frame","framefill","thickframe"];
|
||||
let col = ["rnd","r/g","y/w","o/c","b/y"];
|
||||
let btn = [[24,"BTN1"],[22,"BTN2"],[23,"BTN3"],[11,"BTN4"],[16,"BTN5"]];
|
||||
|
@ -31,12 +29,6 @@
|
|||
format: v=>dm[v],
|
||||
onchange: v=> { numeralsSettings.drawMode=dm[v]; updateSettings();}
|
||||
},
|
||||
"Menu button": {
|
||||
value: btn.findIndex(e=>e[0]==numeralsSettings.menuButton),
|
||||
min:0,max:btn.length-1,
|
||||
format: v=>btn[v][1],
|
||||
onchange: v=> { numeralsSettings.menuButton=btn[v][0]; updateSettings();}
|
||||
},
|
||||
"Date on touch": {
|
||||
value: 0|numeralsSettings.showDate,
|
||||
min:0,max:1,
|
||||
|
|
Loading…
Reference in New Issue