2022-02-17 01:42:21 +00:00
//Clock renders date, time and pre,current,next week calender view
class TimeCalClock {
DATE _FONT _SIZE ( ) { return 20 ; }
TIME _FONT _SIZE ( ) { return 40 ; }
2021-11-24 10:43:38 +00:00
2022-02-17 01:42:21 +00:00
/ * *
* @ param { Date } date optional the date ( e . g . for testing )
* @ param { Settings } settings optional settings to use e . g . for testing
* /
constructor ( date , settings ) {
if ( date )
this . date = date ;
if ( settings )
this . _settings = settings ;
else
this . _settings = require ( "Storage" ) . readJSON ( "timecal.settings.json" , 1 ) || { } ;
const defaults = {
shwDate : 1 , //0:none, 1:locale, 2:month, 3:monthshort.year #week
wdStrt : 0 , //identical to getDay() 0->Su, 1->Mo, ... //Issue #1154: weekstart So/Mo, -1 for use today
tdyNumClr : 3 , //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E
tdyMrkr : 0 , //0:none, 1:circle, 2:rectangle, 3:filled
tdyMrkClr : 2 , //1:red=#E00, 2:green=#0E0, 3:blue=#00E
tdyMrkPxl : 3 , //px
suClr : 1 , //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E
//phColor:"#E00", //public holiday
calBrdr : false
} ;
for ( const k in this . _settings ) if ( ! defaults . hasOwnProperty ( k ) ) delete this . _settings [ k ] ; //remove invalid settings
for ( const k in defaults ) if ( ! this . _settings . hasOwnProperty ( k ) ) this . _settings [ k ] = defaults [ k ] ; //assign missing defaults
g . clear ( ) ;
Bangle . setUI ( "clock" ) ;
Bangle . loadWidgets ( ) ;
Bangle . drawWidgets ( ) ;
this . centerX = Bangle . appRect . w / 2 ;
this . nrgb = [ g . theme . fg , "#E00" , "#0E0" , "#00E" ] ; //fg, r ,g , b
this . ABR _DAY = [ ] ;
if ( require ( "locale" ) && require ( "locale" ) . dow )
for ( let d = 0 ; d <= 6 ; d ++ ) {
var refDay = new Date ( ) ;
refDay . setFullYear ( 1972 ) ;
refDay . setMonth ( 0 ) ;
refDay . setDate ( 2 + d ) ;
this . ABR _DAY . push ( require ( "locale" ) . dow ( refDay ) ) ;
2021-11-24 10:43:38 +00:00
2022-02-17 01:42:21 +00:00
}
else
this . ABR _DAY = [ "Sun" , "Mon" , "Tue" , "Wed" , "Thu" , "Fri" , "Sat" ] ;
}
/ * *
* @ returns { Object } current settings object
* /
settings ( ) {
return this . _settings ;
}
/ *
* Run forest run
* * /
draw ( ) {
this . drawTime ( ) ;
if ( this . TZOffset === undefined || this . TZOffset !== d . getTimezoneOffset ( ) )
this . drawDateAndCal ( ) ;
2021-11-24 10:43:38 +00:00
}
2022-02-17 01:42:21 +00:00
/ * *
* draw given or current time from date
* overwatch timezone changes
* schedules itself to update
* /
drawTime ( ) {
d = this . date ? this . date : new Date ( ) ;
const Y = Bangle . appRect . y + this . DATE _FONT _SIZE ( ) + 10 ;
d = d ? d : new Date ( ) ;
g . setFontAlign ( 0 , - 1 ) . setFont ( "Vector" , this . TIME _FONT _SIZE ( ) ) . setColor ( g . theme . fg )
. clearRect ( Bangle . appRect . x , Y , Bangle . appRect . x2 , Y + this . TIME _FONT _SIZE ( ) - 7 )
. drawString ( ( "0" + require ( "locale" ) . time ( d , 1 ) ) . slice ( - 5 ) , this . centerX , Y , true ) ;
//.drawRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+this.TIME_FONT_SIZE()-7); //DEV-Option
setTimeout ( this . draw . bind ( this ) , 60000 - ( d . getSeconds ( ) * 1000 ) - d . getMilliseconds ( ) ) ;
2021-11-24 10:43:38 +00:00
}
2022-02-17 01:42:21 +00:00
/ * *
* draws given date and cal
* @ param { Date } d provide date or uses today
* /
drawDateAndCal ( ) {
d = this . date ? this . date : new Date ( ) ;
this . TZOffset = d . getTimezoneOffset ( ) ;
this . drawDate ( ) ;
this . drawCal ( ) ;
if ( this . tOutD ) //abort exisiting
clearTimeout ( this . tOutD ) ;
this . tOutD = setTimeout ( this . drawDateAndCal . bind ( this ) , 86400000 - ( d . getHours ( ) * 24 * 60 * 1000 ) - ( d . getMinutes ( ) * 60 * 1000 ) - d . getSeconds ( ) - d . getMilliseconds ( ) ) ;
2021-11-24 10:43:38 +00:00
}
2022-02-17 01:42:21 +00:00
/ * *
* draws given date as defiend in settings
* /
drawDate ( ) {
d = this . date ? this . date : new Date ( ) ;
const FONT _SIZE = 20 ;
const Y = Bangle . appRect . y ;
var render = false ;
var dateStr = "" ;
if ( this . settings ( ) . shwDate > 0 ) { //skip if exactly -none
const dateSttngs = [ "" , "l" , "M" , "m.Y #W" ] ;
for ( let c of dateSttngs [ this . settings ( ) . shwDate ] ) { //add part as configured
switch ( c ) {
case "l" : { //locale
render = true ;
dateStr += require ( "locale" ) . date ( d , 1 ) ;
break ;
}
case "m" : { //month e.g. Jan.
render = true ;
dateStr += require ( "locale" ) . month ( d , 1 ) ;
break ;
}
case "M" : { //month e.g. January
render = true ;
dateStr += require ( "locale" ) . month ( d , 0 ) ;
break ;
}
case "y" : { //year e.g. 22
render = true ;
dateStr += d . getFullYear ( ) . slice ( - 2 ) ;
break ;
}
case "Y" : { //year e.g. 2022
render = true ;
dateStr += d . getFullYear ( ) ;
break ;
}
case "w" : { //week e.g. #2
dateStr += ( this . ISO8601calWeek ( d ) ) ;
break ;
}
case "W" : { //week e.g. #02
dateStr += ( "0" + this . ISO8601calWeek ( d ) ) . slice ( - 2 ) ;
break ;
}
default : //append c
dateStr += c ;
render = dateStr . length > 0 ;
break ; //noop
}
}
}
if ( render ) {
g . setFont ( "Vector" , FONT _SIZE ) . setColor ( g . theme . fg ) . setFontAlign ( 0 , - 1 ) . clearRect ( Bangle . appRect . x , Y , Bangle . appRect . x2 , Y + FONT _SIZE - 3 ) . drawString ( dateStr , this . centerX , Y ) ;
}
//g.drawRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+FONT_SIZE-3); //DEV-Option
2021-11-24 10:43:38 +00:00
}
2022-02-17 01:42:21 +00:00
/ * *
* draws calender week view ( - 1 , 0 , 1 ) for given date
* /
drawCal ( ) {
d = this . date ? this . date : new Date ( ) ;
const DAY _NAME _FONT _SIZE = 10 ;
const CAL _Y = Bangle . appRect . y + this . DATE _FONT _SIZE ( ) + 10 + this . TIME _FONT _SIZE ( ) + 3 ;
const CAL _AREA _H = Bangle . appRect . h - CAL _Y + 24 ; //+24: top widegtes only
const CELL _W = Bangle . appRect . w / 7 ; //cell width
const CELL _H = ( CAL _AREA _H - DAY _NAME _FONT _SIZE ) / 3 ; //cell heigth
const DAY _NUM _FONT _SIZE = Math . min ( CELL _H - 1 , 15 ) ; //size down, max 15
2021-11-24 10:43:38 +00:00
2022-02-17 01:42:21 +00:00
g . setFont ( "Vector" , DAY _NAME _FONT _SIZE ) . setColor ( g . theme . fg ) . setFontAlign ( - 1 , - 1 ) . clearRect ( Bangle . appRect . x , CAL _Y , Bangle . appRect . x2 , CAL _Y + CAL _AREA _H ) ;
//draw grid & Headline
const dNames = this . ABR _DAY . map ( ( a ) => a . length <= 2 ? a : a . substr ( 0 , 2 ) ) ; //force shrt 2
for ( var dNo = 0 ; dNo < dNames . length ; dNo ++ ) {
const dIdx = this . settings ( ) . wdStrt >= 0 ? ( dNo + this . settings ( ) . wdStrt ) % 7 : ( dNo + d . getDay ( ) + 4 ) % 7 ;
const dName = dNames [ dIdx ] ;
if ( dNo > 0 )
g . drawLine ( dNo * CELL _W , CAL _Y , dNo * CELL _W , CAL _Y + CAL _AREA _H - 1 ) ;
if ( dIdx == 0 ) g . setColor ( this . nrgb [ this . settings ( ) . suClr ] ) ; //sunday maybe colorize txt
g . drawString ( dName , dNo * CELL _W + ( CELL _W - g . stringWidth ( dName ) ) / 2 + 2 , CAL _Y + 1 ) . setColor ( g . theme . fg ) ;
}
var nextY = CAL _Y + DAY _NAME _FONT _SIZE ;
for ( i = 0 ; i < 3 ; i ++ ) {
const y = nextY + i * CELL _H ;
g . drawLine ( Bangle . appRect . x , y , Bangle . appRect . x2 , y ) ;
}
g . setFont ( "Vector" , DAY _NUM _FONT _SIZE ) ;
//write days
const tdyDate = d . getDate ( ) ;
const days = this . settings ( ) . wdStrt >= 0 ? 7 + ( ( 7 + d . getDay ( ) - this . settings ( ) . wdStrt ) % 7 ) : 10 ; //start day (week before=7 days + days in this week realtive to week start) or fixed 7+3 days
var rD = new Date ( d . getTime ( ) ) ;
rD . setDate ( rD . getDate ( ) - days ) ;
var rDate = rD . getDate ( ) ;
for ( var y = 0 ; y < 3 ; y ++ ) {
for ( var x = 0 ; x < dNames . length ; x ++ ) {
if ( rDate === tdyDate ) { //today
g . setColor ( this . nrgb [ this . settings ( ) . tdyMrkClr ] ) ; //today marker color or fg color
switch ( this . settings ( ) . tdyMrkr ) { //0:none, 1:circle, 2:rectangle, 3:filled
case 1 :
for ( m = 1 ; m <= this . settings ( ) . tdyMrkPxl && m < CELL _H - 1 && m < CELL _W - 1 ; m ++ )
g . drawCircle ( x * CELL _W + ( CELL _W / 2 ) + 1 , nextY + ( CELL _H * y ) + ( CELL _H / 2 ) + 1 , Math . min ( ( CELL _W - m ) / 2 , ( CELL _H - m ) / 2 ) - 2 ) ;
break ;
case 2 :
for ( m = 1 ; m <= this . settings ( ) . tdyMrkPxl && m < CELL _H - 1 && m < CELL _W - 1 ; m ++ )
g . drawRect ( x * CELL _W + m , nextY + CELL _H + m , x * CELL _W + CELL _W - m , nextY + CELL _H + CELL _H - m ) ;
break ;
case 3 :
g . fillRect ( x * CELL _W + 1 , nextY + CELL _H + 1 , x * CELL _W + CELL _W - 1 , nextY + CELL _H + CELL _H - 1 ) ;
break ;
default :
break ;
}
g . setColor ( this . nrgb [ this . settings ( ) . tdyNumClr ] ) ; //today color or fg color
} else if ( this . settings ( ) . suClr && rD . getDay ( ) == 0 ) { //sundays
g . setColor ( this . nrgb [ this . settings ( ) . suClr ] ) ;
} else { //default
g . setColor ( g . theme . fg ) ;
}
g . drawString ( rDate , x * CELL _W + ( ( CELL _W - g . stringWidth ( rDate ) ) / 2 ) + 2 , nextY + ( ( CELL _H - DAY _NUM _FONT _SIZE + 2 ) / 2 ) + ( CELL _H * y ) ) ;
rD . setDate ( rDate + 1 ) ;
rDate = rD . getDate ( ) ;
2021-11-24 10:43:38 +00:00
}
2022-02-17 01:42:21 +00:00
}
if ( this . settings ( ) . calBrdr ) {
g . setColor ( g . theme . fg ) . drawRect ( Bangle . appRect . x , CAL _Y , Bangle . appRect . x2 , CAL _Y + CAL _AREA _H - 1 ) ;
2021-11-24 10:43:38 +00:00
}
}
2022-02-17 01:42:21 +00:00
/ * *
* calculates current ISO8601 week number e . g . 2
* @ param { Date } date for the date
* @ returns { Number } } e . g . 2
* /
ISO8601calWeek ( date ) { //copied from: https://gist.github.com/IamSilviu/5899269#gistcomment-3035480
var tdt = new Date ( date . valueOf ( ) ) ;
var dayn = ( date . getDay ( ) + 6 ) % 7 ;
tdt . setDate ( tdt . getDate ( ) - dayn + 3 ) ;
var firstThursday = tdt . valueOf ( ) ;
tdt . setMonth ( 0 , 1 ) ;
if ( tdt . getDay ( ) !== 4 ) {
tdt . setMonth ( 0 , 1 + ( ( 4 - tdt . getDay ( ) ) + 7 ) % 7 ) ;
}
return Number ( 1 + Math . ceil ( ( firstThursday - tdt ) / 604800000 ) ) ;
}
2021-11-24 10:43:38 +00:00
}
2022-02-17 01:42:21 +00:00
timeCalClock = new TimeCalClock ( ) ; timeCalClock . draw ( ) ;
//hook on settime to redraw immediatly
var _setTime = setTime ;
var setTime = function ( t ) {
_setTime ( t ) ;
timeCalClock . draw ( true ) ;
} ;