diff --git a/apps.json b/apps.json index 980eabc40..cdecd3e90 100644 --- a/apps.json +++ b/apps.json @@ -242,8 +242,8 @@ { "id": "sweepclock", "name": "Sweep Clock", "icon": "sweepclock.png", - "version":"0.02", - "description": "Smooth sweep secondhand with single hour numeral. Use button1 to toggle the numeral font and button3 to change the colour theme", + "version":"0.03", + "description": "Smooth sweep secondhand with single hour numeral. Use button1 to toggle the numeral font, button 3 to change the colour theme and button 4 to change the date placement", "tags": "clock", "type":"clock", "allow_emulator":true, diff --git a/apps/sweepclock/ChangeLog b/apps/sweepclock/ChangeLog index d5cf3753c..8eeb95c09 100644 --- a/apps/sweepclock/ChangeLog +++ b/apps/sweepclock/ChangeLog @@ -1,2 +1,3 @@ 0.01: Initial Release 0.02: Added Colour Themes +0.03: Added Date diff --git a/apps/sweepclock/README.md b/apps/sweepclock/README.md index 8ddb7decb..cbdb2a3f8 100644 --- a/apps/sweepclock/README.md +++ b/apps/sweepclock/README.md @@ -23,7 +23,12 @@ Button 3 (bottom right button) is used to change the colour | ---- | ---- | ---- | | ![](./color-01.jpg) | ![](color-02.jpg) | ![](color-03.jpg) | +### Button 4 +Button 4 (bottom left of screen) is used to change the date positioning (or to remove from the screen) +| Top Right | Bottom Right | Bottom Left | Top Left | +| ---- | ---- | ---- | ---- | +| ![](./date-01.jpg) | ![](date-02.jpg) | ![](date-03.jpg) | ![](date-04.jpg) | ## Further Details @@ -35,4 +40,4 @@ Reach out to adrian@adriankirk.com if you have feature requests or notice bugs. ## Creator -Made by [Adrian Kirk](mailto:adrian@adriankirk.com) +Made by [Adrian Kirk](mailto:adrian@adriankirk.com) \ No newline at end of file diff --git a/apps/sweepclock/date-01.jpg b/apps/sweepclock/date-01.jpg new file mode 100644 index 000000000..79d12e75b Binary files /dev/null and b/apps/sweepclock/date-01.jpg differ diff --git a/apps/sweepclock/date-02.jpg b/apps/sweepclock/date-02.jpg new file mode 100644 index 000000000..14a64980c Binary files /dev/null and b/apps/sweepclock/date-02.jpg differ diff --git a/apps/sweepclock/date-03.jpg b/apps/sweepclock/date-03.jpg new file mode 100644 index 000000000..e30a01932 Binary files /dev/null and b/apps/sweepclock/date-03.jpg differ diff --git a/apps/sweepclock/date-04.jpg b/apps/sweepclock/date-04.jpg new file mode 100644 index 000000000..6e65a148f Binary files /dev/null and b/apps/sweepclock/date-04.jpg differ diff --git a/apps/sweepclock/sweepclock.js b/apps/sweepclock/sweepclock.js index 9c53efa55..df6b09e3d 100644 --- a/apps/sweepclock/sweepclock.js +++ b/apps/sweepclock/sweepclock.js @@ -6,6 +6,7 @@ const screen_center_x = g.getWidth()/2; const screen_center_y = 10 + g.getHeight()/2; +const TWO_PI = 2*Math.PI; require("FontCopasetic40x58Numeric").add(Graphics); @@ -101,14 +102,14 @@ class ThinHand extends Hand { // and then call the predicate to see if a redraw is needed this.draw_test(this.angle,this.last_draw_time) ){ // rub out the old hand line - background = color_schemes[color_scheme_index].background; + var background = color_schemes[color_scheme_index].background; g.setColor(background[0],background[1],background[2]); g.drawLine(this.centerX, this.centerY, this.last_x, this.last_y); // Now draw the new hand line - hand_color = color_schemes[color_scheme_index][this.color_theme]; + var hand_color = color_schemes[color_scheme_index][this.color_theme]; g.setColor(hand_color[0],hand_color[1],hand_color[2]); - x2 = this.centerX + this.length*Math.sin(angle); - y2 = this.centerY - this.length*Math.cos(angle); + var x2 = this.centerX + this.length*Math.sin(angle); + var y2 = this.centerY - this.length*Math.cos(angle); g.drawLine(this.centerX, this.centerY, x2, y2); // and store the last draw details for the next call this.last_x = x2; @@ -170,7 +171,7 @@ class ThickHand extends Hand { // method to move the hand to a new angle moveTo(angle){ if(Math.abs(angle - this.angle) > this.tolerance || this.draw_test(this.angle - this.delta_base,this.angle + this.delta_base ,this.last_draw_time) ){ - background = color_schemes[color_scheme_index].background; + var background = color_schemes[color_scheme_index].background; g.setColor(background[0],background[1],background[2]); g.fillPoly([this.last_x1, this.last_y1, @@ -182,20 +183,20 @@ class ThickHand extends Hand { this.last_y4 ]); // bottom left - x1 = this.centerX + + var x1 = this.centerX + this.vertex_radius_base*Math.sin(angle - this.delta_base); - y1 = this.centerY - this.vertex_radius_base*Math.cos(angle - this.delta_base); + var y1 = this.centerY - this.vertex_radius_base*Math.cos(angle - this.delta_base); // bottom right - x2 = this.centerX + + var x2 = this.centerX + this.vertex_radius_base*Math.sin(angle + this.delta_base); - y2 = this.centerY - this.vertex_radius_base*Math.cos(angle + this.delta_base); + var y2 = this.centerY - this.vertex_radius_base*Math.cos(angle + this.delta_base); // top right - x3 = this.centerX + this.vertex_radius_top*Math.sin(angle + this.delta_top); - y3 = this.centerY - this.vertex_radius_top*Math.cos(angle + this.delta_top); + var x3 = this.centerX + this.vertex_radius_top*Math.sin(angle + this.delta_top); + var y3 = this.centerY - this.vertex_radius_top*Math.cos(angle + this.delta_top); // top left - x4 = this.centerX + this.vertex_radius_top*Math.sin(angle - this.delta_top); - y4 = this.centerY - this.vertex_radius_top*Math.cos(angle - this.delta_top); - hand_color = color_schemes[color_scheme_index][this.color_theme]; + var x4 = this.centerX + this.vertex_radius_top*Math.sin(angle - this.delta_top); + var y4 = this.centerY - this.vertex_radius_top*Math.cos(angle - this.delta_top); + var hand_color = color_schemes[color_scheme_index][this.color_theme]; g.setColor(hand_color[0],hand_color[1],hand_color[2]); g.fillPoly([x1,y1, x2,y2, @@ -222,25 +223,27 @@ class ThickHand extends Hand { let force_redraw = false; // The seconds hand is the main focus and is set to redraw on every cycle let seconds_hand = new ThinHand(screen_center_x, - screen_center_y, - 95, - 0, - (angle, last_draw_time) => false, - "second_hand"); + screen_center_y, + 95, + 0, + (angle, last_draw_time) => false, + "second_hand"); + // The minute hand is set to redraw at a 250th of a circle, // when the second hand is ontop or slighly overtaking // or when a force_redraw is called let minutes_hand_redraw = function(angle, last_draw_time){ return force_redraw || (seconds_hand.angle > angle && - Math.abs(seconds_hand.angle - angle) <2*Math.PI/25 && + Math.abs(seconds_hand.angle - angle) 500); }; -let minutes_hand = new ThinHand(screen_center_x, - screen_center_y, - 80, - 2*Math.PI/250, - minutes_hand_redraw, - "minute_hand"); +let minutes_hand = new ThinHand(screen_center_x, + screen_center_y, + 80, + TWO_PI/250, + minutes_hand_redraw, + "minute_hand" +); // The hour hand is a thick hand so we have to redraw when the minute hand // overlaps from its behind andle coverage to its ahead angle coverage. let hour_hand_redraw = function(angle_from, angle_to, last_draw_time){ @@ -249,48 +252,107 @@ let hour_hand_redraw = function(angle_from, angle_to, last_draw_time){ new Date().getTime() - last_draw_time.getTime() > 500); }; let hours_hand = new ThickHand(screen_center_x, - screen_center_y, - 40, - 2*Math.PI/600, - hour_hand_redraw, - "hour_hand", - 5, - 4); + screen_center_y, + 40, + TWO_PI/600, + hour_hand_redraw, + "hour_hand", + 5, + 4); function draw_clock(){ - date = new Date(); + var date = new Date(); draw_background(); draw_hour_digit(date); draw_seconds(date); draw_mins(date); draw_hours(date); + draw_date(date); force_redraw = false; } + +var local = require('locale'); +var last_date = null; +var last_datestr = null; +var last_coords = null; +var date_coords = [ + { name: "topright", coords:[180,30]}, + { name: "bottomright", coords:[180,220]}, + { name: "bottomleft", coords: [5,220]}, + { name: "topleft", coords:[5,30]}, + { name: "offscreen", coords: [240,30]} +]; +var date_coord_index = 0; + +function draw_date(date){ + if(force_redraw || last_date == null || last_date.getDate() != date.getDate()){ + //console.log("redrawing date"); + g.setFontAlign(-1,-1,0); + g.setFont("Vector",15); + if(last_coords != null && last_datestr != null) { + var background = color_schemes[color_scheme_index].background; + g.setColor(background[0], background[1], background[2]); + g.drawString(last_datestr, last_coords[0], last_coords[1]); + } + var coords = date_coords[date_coord_index].coords; + if(coords != null) { + var date_format = local.dow(date,1) + " " + date.getDate(); + var numeral_color = color_schemes[color_scheme_index].numeral; + g.setColor(numeral_color[0], numeral_color[1], numeral_color[2]); + g.drawString(date_format, coords[0], coords[1]); + last_date = date; + last_datestr = date_format; + last_coords = coords; + } + } +} + +function next_datecoords() { + date_coord_index = date_coord_index + 1; + if (date_coord_index >= date_coords.length) { + date_coord_index = 0; + } + //console.log("date coord index->" + date_coord_index); + force_redraw = true; +} + +function set_datecoords(date_name){ + console.log("setting date:" + date_name); + for (var i=0; i < date_coords.length; i++) { + if(date_coords[i].getName() == date_name){ + date_coord_index = i; + force_redraw = true; + console.log("date match"); + break; + } + } +} + // drawing the second the millisecond as we need the fine gradation // for the sweep second hand. function draw_seconds(date){ - seconds = date.getSeconds() + date.getMilliseconds()/1000; - seconds_frac = seconds / 60; - seconds_angle = 2*Math.PI*seconds_frac; + var seconds = date.getSeconds() + date.getMilliseconds()/1000; + var seconds_frac = seconds / 60; + var seconds_angle = TWO_PI*seconds_frac; seconds_hand.moveTo(seconds_angle); } // drawing the minute includes the second and millisec to make the // movement as continuous as possible. function draw_mins(date,seconds_angle){ - mins = date.getMinutes() + date.getSeconds()/60 + date.getMilliseconds()/(60*1000); - mins_frac = mins / 60; - mins_angle = 2*Math.PI*mins_frac; - redraw = minutes_hand.moveTo(mins_angle); + var mins = date.getMinutes() + date.getSeconds()/60 + date.getMilliseconds()/(60*1000); + var mins_frac = mins / 60; + var mins_angle = TWO_PI*mins_frac; + var redraw = minutes_hand.moveTo(mins_angle); if(redraw){ //console.log("redraw mins"); } } function draw_hours(date){ - hours = (date.getHours() % 12) + date.getMinutes()/60 + date.getSeconds()/3600; - hours_frac = hours / 12; - hours_angle = 2*Math.PI*hours_frac; - redraw = hours_hand.moveTo(hours_angle); + var hours = (date.getHours() % 12) + date.getMinutes()/60 + date.getSeconds()/3600; + var hours_frac = hours / 12; + var hours_angle = TWO_PI*hours_frac; + var redraw = hours_hand.moveTo(hours_angle); if(redraw){ //console.log("redraw hours"); } @@ -363,6 +425,7 @@ class CopasetFont extends NumeralFont{ x,y+dim[1] ]); g.setColor(1.0,1.0,1.0);*/ + g.setFontAlign(-1,-1,0); g.setFontCopasetic40x58Numeric(); g.drawString(hour_txt,x,y); } @@ -408,6 +471,7 @@ class RomanNumeralFont extends NumeralFont{ getDimensions(hour){ return this.dimension_map[hour];} hour_txt(hour){ return this.txt_map[hour]; } draw(hour_txt,x,y){ + g.setFontAlign(-1,-1,0); g.setFont("Vector",40); g.drawString(hour_txt,x,y); } @@ -426,7 +490,7 @@ function reifyasin(x,y,asin_angle){ } else if(x < 0 && y < 0){ return Math.PI - asin_angle; } else { - return 2*Math.PI + asin_angle; + return TWO_PI + asin_angle; } } @@ -434,7 +498,7 @@ function reifyasin(x,y,asin_angle){ // rather than 0 to 2PI function rebaseNegative(angle){ if(angle > Math.PI){ - return angle - 2*Math.PI; + return angle - TWO_PI; } else { return angle; } @@ -444,7 +508,7 @@ function rebaseNegative(angle){ // rather than -pi to pi function rebasePositive(angle){ if(angle < 0){ - return angle + 2*Math.PI; + return angle + TWO_PI; } else { return angle; } @@ -471,48 +535,48 @@ class HourScriber { this.numeral_font = numeral_font; } drawHour(hours){ - changed = false; + var changed = false; if(this.curr_hours != hours || this.curr_numeral_font !=this.numeral_font){ - background = color_schemes[color_scheme_index].background; + var background = color_schemes[color_scheme_index].background; g.setColor(background[0],background[1],background[2]); this.curr_numeral_font.draw(this.curr_hour_str, this.curr_hour_x, this.curr_hour_y); //console.log("erasing old hour"); - hours_frac = hours / 12; - angle = 2*Math.PI*hours_frac; - dimensions = this.numeral_font.getDimensions(hours); + var hours_frac = hours / 12; + var angle = TWO_PI*hours_frac; + var dimensions = this.numeral_font.getDimensions(hours); // we set the radial coord to be in the middle // of the drawn text. - width = dimensions[0]; - height = dimensions[1]; - delta_center_x = this.radius*Math.sin(angle) - width/2; - delta_center_y = this.radius*Math.cos(angle) + height/2; + var width = dimensions[0]; + var height = dimensions[1]; + var delta_center_x = this.radius*Math.sin(angle) - width/2; + var delta_center_y = this.radius*Math.cos(angle) + height/2; this.curr_hour_x = screen_center_x + delta_center_x; this.curr_hour_y = screen_center_y - delta_center_y; this.curr_hour_str = this.numeral_font.hour_txt(hours); // now work out the angle of the beginning and the end of the // text box so we know when to redraw // bottom left angle - x1 = delta_center_x; - y1 = delta_center_y; - r1 = Math.sqrt(x1*x1 + y1*y1); - angle1 = reifyasin(x1,y1,Math.asin(x1/r1)); + var x1 = delta_center_x; + var y1 = delta_center_y; + var r1 = Math.sqrt(x1*x1 + y1*y1); + var angle1 = reifyasin(x1,y1,Math.asin(x1/r1)); // bottom right angle - x2 = delta_center_x; - y2 = delta_center_y - height; - r2 = Math.sqrt(x2*x2 + y2*y2); - angle2 = reifyasin(x2,y2,Math.asin(x2/r2)); + var x2 = delta_center_x; + var y2 = delta_center_y - height; + var r2 = Math.sqrt(x2*x2 + y2*y2); + var angle2 = reifyasin(x2,y2,Math.asin(x2/r2)); // top left angle - x3 = delta_center_x + width; - y3 = delta_center_y; - r3 = Math.sqrt(x3*x3 + y3*y3); - angle3 = reifyasin(x3,y3, Math.asin(x3/r3)); + var x3 = delta_center_x + width; + var y3 = delta_center_y; + var r3 = Math.sqrt(x3*x3 + y3*y3); + var angle3 = reifyasin(x3,y3, Math.asin(x3/r3)); // top right angle - x4 = delta_center_x + width; - y4 = delta_center_y - height; - r4 = Math.sqrt(x4*x4 + y4*y4); - angle4 = reifyasin(x4,y4,Math.asin(x4/r4)); + var x4 = delta_center_x + width; + var y4 = delta_center_y - height; + var r4 = Math.sqrt(x4*x4 + y4*y4); + var angle4 = reifyasin(x4,y4,Math.asin(x4/r4)); if(Math.min(angle1,angle2,angle3,angle4) < Math.PI && Math.max(angle1,angle2,angle3,angle4) > 1.5*Math.PI){ angle1 = rebaseNegative(angle1); angle2 = rebaseNegative(angle2); @@ -532,7 +596,7 @@ class HourScriber { } if(changed || this.draw_test(this.angle_from, this.angle_to, this.last_draw_time) ){ - numeral_color = color_schemes[color_scheme_index].numeral; + var numeral_color = color_schemes[color_scheme_index].numeral; g.setColor(numeral_color[0],numeral_color[1],numeral_color[2]); this.numeral_font.draw(this.curr_hour_str,this.curr_hour_x,this.curr_hour_y); this.last_draw_time = new Date(); @@ -547,18 +611,18 @@ let numeral_fonts_index = 0; * predicate for deciding when the digit has to be redrawn */ let hour_numeral_redraw = function(angle_from, angle_to, last_draw_time){ - seconds_hand_angle = seconds_hand.angle; + var seconds_hand_angle = seconds_hand.angle; // we have to cope with the 12 problem where the // left side of the box has a value almost 2PI and the right // side has a small positive value. The values are rebased so // that they can be compared if(angle_from > angle_to && angle_from > 1.5*Math.PI){ - angle_from = angle_from - 2*Math.PI; + angle_from = angle_from - TWO_PI; if(seconds_hand_angle > Math.PI) - seconds_hand_angle = seconds_hand_angle - 2*Math.PI; + seconds_hand_angle = seconds_hand_angle - TWO_PI; } //console.log("initial:" + angle_from + "/" + angle_to + " seconds " + seconds_hand_angle); - redraw = force_redraw || + var redraw = force_redraw || (seconds_hand_angle >= angle_from && seconds_hand_angle <= angle_to) || (minutes_hand.last_draw_time.getTime() > last_draw_time.getTime()); if(redraw){ @@ -585,8 +649,8 @@ function next_font(){ } function draw_hour_digit(date){ - hours = date.getHours() % 12; - mins = date.getMinutes(); + var hours = date.getHours() % 12; + var mins = date.getMinutes(); if(mins > 30){ hours = (hours +1) % 12; } @@ -598,7 +662,7 @@ function draw_hour_digit(date){ function draw_background(){ if(force_redraw){ - background = color_schemes[color_scheme_index].background; + var background = color_schemes[color_scheme_index].background; g.setColor(background[0],background[1],background[2]); g.fillPoly([0,25, 0,240, @@ -625,7 +689,7 @@ function set_colorscheme(colorscheme_name){ if(color_schemes[i].name == colorscheme_name){ color_scheme_index = i; force_redraw = true; - console.log("match"); + console.log("color scheme match"); break; } } @@ -641,7 +705,7 @@ function set_font(font_name){ if(numeral_fonts[i].getName() == font_name){ numeral_fonts_index = i; force_redraw = true; - console.log("match"); + console.log("font match"); hour_scriber.setNumeralFont(numeral_fonts[numeral_fonts_index]); break; } @@ -653,7 +717,7 @@ function set_font(font_name){ */ function load_settings(){ try{ - settings = require("Storage").readJSON("sweepclock.settings.json"); + var settings = require("Storage").readJSON("sweepclock.settings.json"); if(settings != null){ console.log("loaded:" + JSON.stringify(settings)); if(settings.color_scheme != null){ @@ -662,6 +726,9 @@ function load_settings(){ if(settings.font != null){ set_font(settings.font); } + if(settings.date != null){ + set_datecoords(settings.date); + } } else { console.log("no settings to load"); } @@ -674,9 +741,10 @@ function load_settings(){ * Called on button press to save down the last preference settings */ function save_settings(){ - settings = { + var settings = { font : numeral_fonts[numeral_fonts_index].getName(), color_scheme : color_schemes[color_scheme_index].name, + date: date_coords[date_coord_index].name }; console.log("saving:" + JSON.stringify(settings)); require("Storage").writeJSON("sweepclock.settings.json",settings); @@ -753,9 +821,17 @@ function button3pressed(){ save_settings(); } +function button4pressed(){ + //console.log("button 4 pressed"); + next_datecoords(); + save_settings(); +} + // Handle button 1 being pressed setWatch(button1pressed, BTN1,{repeat:true,edge:"falling"}); // Handle button 3 being pressed setWatch(button3pressed, BTN3,{repeat:true,edge:"falling"}); +// Handle button 3 being pressed +setWatch(button4pressed, BTN4,{repeat:true,edge:"falling"});