1
0
Fork 0

Merge pull request #2035 from awkirk71/master

Matrix Clock: Fixing non dark color themes
master
Gordon Williams 2022-07-11 10:19:30 +01:00 committed by GitHub
commit ae06a5d696
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 210 additions and 62 deletions

View File

@ -1,4 +1,5 @@
0.01: Initial Release
0.02: Support for Bangle 2
0.03: Keep the date from being overwritten, use correct colour from theme for clearing
0.04: Removed "wake LCD on face-up"-feature: A watch-face should not set things like "wake LCD on face-up".
0.04: Removed "wake LCD on face-up"-feature: A watch-face should not set things like "wake LCD on face-up".
0.05: Added support to other color themes (other then black)

View File

@ -2,6 +2,24 @@
![](app.png)
## Settings
Please use the setting->App->Matrix Clock Menu to change the settings
| Setting | Description |
|-----------|--------------------------------------------------------------------------------------------------------------------|
| Color | by default set to **'theme'** to follow the theme colors. Selector also offers a selection of other colour schemes |
| Intensity | Changes the number of matrix streams that are falling |
## Colour Themes
Some of the colours schemes that are available from the settings screen
| ![](matrix_green_on_black.jpg) | ![](matrix_black_on_white.jpg) | ![](matrix_white_on_gray.jpg) |
|-------------------------------|-------------------------------|-----|
| green on black | white on black | white on gray |
## Requests
Please reach out to adrian@adriankirk.com if you have feature requests or notice bugs.

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -3,24 +3,100 @@
*
* Matrix Clock
*
* A simple clock inspired by the movie.
* Text shards move down the screen as a background to the
* A simple clock inspired by the movie.
* Text shards move down the screen as a background to the
* time and date
**/
const Locale = require('locale');
const SHARD_COLOR =[0,1.0,0];
const PREFERENCE_FILE = "matrixclock.settings.json";
const settings = Object.assign({color: "theme", intensity: 'light'},
require('Storage').readJSON(PREFERENCE_FILE, true) || {});
const colors = {
'gray' :[0.5,0.5,0.5],
'green': [0,1.0,0],
'red' : [1.0,0.0,0.0],
'blue' : [0.0,0.0,1.0],
'black': [0.0,0.0,0.0],
'purple': [1.0,0.0,1.0],
'white': [1.0,1.0,1.0],
'yellow': [1.0,1.0,0.0]
};
const color_schemes = {
'black on white': ['white','black'],
'green on white' : ['white','green'],
'green on black' : ['black','green'],
'red on black' : ['black', 'red'],
'red on white' : ['white', 'red'],
'white on gray' : ['gray', 'white'],
'white on red' : ['red', 'white'],
'white on blue': ['blue','white'],
'white on purple': ['purple', 'white']
};
function int2Color(color_int){
var blue_int = color_int & 31;
var blue = (blue_int)/31.0;
var green_int = (color_int >> 5) & 31;
var green = (green_int)/31.0;
var red_int = (color_int >> 11) & 31;
var red = red_int/ 31.0;
return [red,green,blue];
}
var fg_color = colors.black;
var bg_color = colors.white;
// now lets deal with the settings
if(settings.color === "theme"){
bg_color = int2Color(g.theme.bg);
if(g.theme.bg === 0) {
fg_color = colors.green;
} else {
fg_color = int2Color(g.theme.fg);
}
} else {
var color_scheme = color_schemes[settings.color];
bg_color = colors[color_scheme[0]];
fg_color = colors[color_scheme[1]];
g.setBgColor(bg_color[0],bg_color[1],bg_color[2]);
}
if(fg_color === undefined)
fg_color = colors.black;
if(bg_color === undefined)
bg_color = colors.white;
const intensity_schemes = {
'light': 3,
'medium': 4,
'high': 5
};
var noShards = intensity_schemes.light;
if(settings.intensity !== undefined){
noShards = intensity_schemes[settings.intensity];
}
if(noShards === undefined){
noShards = intensity_schemes.light;
}
const SHARD_FONT_SIZE = 12;
const SHARD_Y_START = 30;
const w = g.getWidth();
/**
* The text shard object is responsible for creating the
* shards of text that move down the screen. As the
* shard moves down the screen the latest character added
* is brightest with characters being coloured darker and darker
* going back to the eldest
*/
* The text shard object is responsible for creating the
* shards of text that move down the screen. As the
* shard moves down the screen the latest character added
* is brightest with characters being coloured darker and darker
* going back to the eldest
*/
class TextShard {
constructor(x,y,length){
@ -34,44 +110,46 @@ class TextShard {
this.txt = [];
}
/**
* The add method call adds another random character to
* the chain
*/
* The add method call adds another random character to
* the chain
*/
add(){
this.txt.push(randomChar());
}
/**
* The show method displays the latest shard image to the
* screen with the following rules:
* - latest addition is brightest, oldest is darker
* - display up to defined length of characters only
* of the shard to save cpu
*/
* The show method displays the latest shard image to the
* screen with the following rules:
* - latest addition is brightest, oldest is darker
* - display up to defined length of characters only
* of the shard to save cpu
*/
show(){
g.setFontAlign(-1,-1,0);
for(var i=0; i<Math.min(this.txt.length, this.length + 1) ; i++){
idx = this.txt.length - i - 1;
var idx = this.txt.length - i - 1;
var color_strength=1 - i/this.length;
if(i > this.length - 2){
color_strength = 0;
}
g.setColor(color_strength*SHARD_COLOR[0],
color_strength*SHARD_COLOR[1],
color_strength*SHARD_COLOR[2]);
}
var bg_color_strength = 1 - color_strength;
g.setColor(Math.abs(color_strength*fg_color[0] - bg_color_strength*bg_color[0]),
Math.abs(color_strength*fg_color[1] - bg_color_strength*bg_color[1]),
Math.abs(color_strength*fg_color[2] - bg_color_strength*bg_color[2])
);
g.setFont("Vector",SHARD_FONT_SIZE);
g.drawString(this.txt[idx], this.x, this.y + idx*SHARD_FONT_SIZE);
g.drawString(this.txt[idx], this.x, this.y + idx*SHARD_FONT_SIZE);
}
}
/**
* Method tests to see if any part of the shard chain is still
* visible on the screen
*/
* Method tests to see if any part of the shard chain is still
* visible on the screen
*/
isVisible(){
return (this.y + (this.txt.length - this.length - 2)*SHARD_FONT_SIZE < g.getHeight());
return (this.y + (this.txt.length - this.length - 2)*SHARD_FONT_SIZE < g.getHeight());
}
/**
* resets the shard back to the top of the screen
*/
* resets the shard back to the top of the screen
*/
reset(){
this.y = SHARD_Y_START;
this.txt = [];
@ -79,8 +157,8 @@ class TextShard {
}
/**
* random character chooser to be called by the shard when adding characters
*/
* random character chooser to be called by the shard when adding characters
*/
const CHAR_CODE_START = 33;
const CHAR_CODE_LAST = 126;
const CHAR_CODE_LENGTH = CHAR_CODE_LAST - CHAR_CODE_START;
@ -90,11 +168,10 @@ function randomChar(){
// Now set up the shards
// we are going to have a limited no of shards (to save cpu)
// but randomize the x value and length every reset to make it look as if there
// but randomize the x value and length every reset to make it look as if there
// are more
var shards = [];
const NO_SHARDS = 3;
const channel_width = g.getWidth()/NO_SHARDS;
const channel_width = g.getWidth()/noShards;
function shard_x(i){
return i*channel_width + Math.random() * channel_width;
@ -104,7 +181,7 @@ function shard_length(){
return Math.floor(Math.random()*5) + 3;
}
for(var i=0; i<NO_SHARDS; i++){
for(var i=0; i<noShards; i++){
shards.push(new TextShard(shard_x(i),50 + Math.random()*100,shard_length()) );
}
@ -112,14 +189,13 @@ var timeStr = "";
var dateStr = "";
var last_draw_time = null;
const TIME_X_COORD = 20;
const TIME_Y_COORD = g.getHeight() / 2;
const DATE_X_COORD = 170;
const DATE_Y_COORD = 30;
const RESET_PROBABILITY = 0.5;
/**
* main loop to draw the clock face
*/
* main loop to draw the clock face
*/
function draw_clock(){
// first move all the shards down the screen
for(var i=0; i<this.shards.length; i++){
@ -147,22 +223,22 @@ function draw_clock(){
g.setFont("Vector", g.getWidth() / 5);
g.setFontAlign(0,-1);
if(last_draw_time == null || now.getMinutes() != last_draw_time.getMinutes()){
g.setColor(g.theme.bg);
g.setColor(bg_color[0],bg_color[1],bg_color[2]);
g.drawString(timeStr, w/2, TIME_Y_COORD);
timeStr = format_time(now);
}
g.setColor(SHARD_COLOR[0], SHARD_COLOR[1], SHARD_COLOR[2]);
g.drawString(timeStr, w/2, TIME_Y_COORD);
g.setColor(fg_color[0], fg_color[1], fg_color[2]);
g.drawString(timeStr, w/2, TIME_Y_COORD);
//
// draw date when it changes
g.setFont("Vector",15);
g.setFontAlign(0,-1,0);
if(last_draw_time == null || now.getDate() != last_draw_time.getDate()){
g.setColor(g.theme.bg);
g.setColor(bg_color[0],bg_color[1],bg_color[2]);
g.drawString(dateStr, w/2, DATE_Y_COORD);
dateStr = format_date(now);
}
g.setColor(SHARD_COLOR[0], SHARD_COLOR[1], SHARD_COLOR[2]);
g.setColor(fg_color[0], fg_color[1], fg_color[2]);
g.drawString(dateStr, w/2, DATE_Y_COORD);
last_draw_time = now;
}
@ -180,7 +256,7 @@ function format_time(now){
}
var am_pm;
if(time.getHours() < 12){
am_pm = "AM";
am_pm = "AM";
} else {
am_pm = "PM";
}
@ -188,13 +264,13 @@ function format_time(now){
}
function format00(num){
var value = (num | 0);
if(value > 99 || value < 0)
throw "must be between in range 0-99";
if(value < 10)
return "0" + value.toString();
else
return value.toString();
var value = (num | 0);
if(value > 99 || value < 0)
throw "must be between in range 0-99";
if(value < 10)
return "0" + value.toString();
else
return value.toString();
}
// The interval reference for updating the clock
@ -215,12 +291,12 @@ function startTimers(){
clearTimers();
if (Bangle.isLCDOn()) {
intervalRef = setInterval(() => {
if (!shouldRedraw()) {
//console.log("draw clock callback - skipped redraw");
} else {
draw_clock();
}
}, 100
if (!shouldRedraw()) {
//console.log("draw clock callback - skipped redraw");
} else {
draw_clock();
}
}, 100
);
draw_clock();
} else {

View File

@ -0,0 +1,51 @@
(function(back) {
const PREFERENCE_FILE = "matrixclock.settings.json";
var settings = Object.assign({color : "theme", intensity: "light"},
require('Storage').readJSON(PREFERENCE_FILE, true) || {});
console.log("loaded:" + JSON.stringify(settings));
function writeSettings() {
console.log("saving:" + JSON.stringify(settings));
require('Storage').writeJSON(PREFERENCE_FILE, settings);
}
// Helper method which uses int-based menu item for set of string values
function stringItems(startvalue, writer, values) {
return {
value: (startvalue === undefined ? 0 : values.indexOf(startvalue)),
format: v => values[v],
min: 0,
max: values.length - 1,
wrap: true,
step: 1,
onchange: v => {
writer(values[v]);
writeSettings();
}
};
}
// Helper method which breaks string set settings down to local settings object
function stringInSettings(name, values) {
return stringItems(settings[name], v => settings[name] = v, values);
}
// Show the menu
E.showMenu({
"" : { "title" : "Matrix Clock" },
"< Back" : () => back(),
"Colour": stringInSettings("color", ['theme',
'black on white',
'green on white',
'green on black',
'red on white',
'white on gray',
'white on red',
'white on blue'
]),
"Intensity": stringInSettings("intensity", ['light',
'medium',
'high'])
});
})

View File

@ -1,10 +1,10 @@
{
"id": "matrixclock",
"name": "Matrix Clock",
"version": "0.04",
"version": "0.05",
"description": "inspired by The Matrix, a clock of the same style",
"icon": "matrixclock.png",
"screenshots": [{"url":"screenshot_matrix.png"}],
"screenshots": [{"url":"matrix_green_on_black.jpg"}],
"type": "clock",
"tags": "clock",
"supports": ["BANGLEJS","BANGLEJS2"],
@ -12,6 +12,8 @@
"allow_emulator": true,
"storage": [
{"name":"matrixclock.app.js","url":"matrixclock.js"},
{ "name":"matrixclock.settings.js","url":"matrixclock.settings.js"},
{"name":"matrixclock.img","url":"matrixclock-icon.js","evaluate":true}
]
],
"data": [{"name": "matrixclock.settings.json"}]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB