diff --git a/resources/library/applications/Horloge.wgt/config.xml b/resources/library/applications/Horloge.wgt/config.xml new file mode 100644 index 00000000..5c055751 --- /dev/null +++ b/resources/library/applications/Horloge.wgt/config.xml @@ -0,0 +1,13 @@ + + + Horloge + fbocquet@laposte.net + + + diff --git a/resources/library/applications/Horloge.wgt/icon.png b/resources/library/applications/Horloge.wgt/icon.png new file mode 100644 index 00000000..1b069c30 Binary files /dev/null and b/resources/library/applications/Horloge.wgt/icon.png differ diff --git a/resources/library/applications/Horloge.wgt/index.html b/resources/library/applications/Horloge.wgt/index.html new file mode 100644 index 00000000..9e809d48 --- /dev/null +++ b/resources/library/applications/Horloge.wgt/index.html @@ -0,0 +1,60 @@ + + + + Horloge + + + + + + + + + + + +
+
+
+ + + Horloge + +
+ + + diff --git a/resources/library/applications/Horloge.wgt/station-clock.js b/resources/library/applications/Horloge.wgt/station-clock.js new file mode 100644 index 00000000..b5550059 --- /dev/null +++ b/resources/library/applications/Horloge.wgt/station-clock.js @@ -0,0 +1,488 @@ +/*! + * station-clock.js + * + * Copyright (c) 2010 Ruediger Appel + * ludi at mac dot com + * + * Date: 2016-02-16 + * Version: 1.0.1 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Known Issues: + * + * Shadows for some second hands is not on one layer + * + * Thanks to Paul Schröfl for the Wiener Würfeluhr + */ + +// clock body (Uhrgehäuse) +StationClock.NoBody = 0; +StationClock.SmallWhiteBody = 1; +StationClock.RoundBody = 2; +StationClock.RoundGreenBody = 3; +StationClock.SquareBody = 4; +StationClock.ViennaBody = 5; + +// stroke dial (Zifferblatt) +StationClock.NoDial = 0; +StationClock.GermanHourStrokeDial = 1; +StationClock.GermanStrokeDial = 2; +StationClock.AustriaStrokeDial = 3; +StationClock.SwissStrokeDial = 4; +StationClock.ViennaStrokeDial = 5; + +//clock hour hand (Stundenzeiger) +StationClock.PointedHourHand = 1; +StationClock.BarHourHand = 2; +StationClock.SwissHourHand = 3; +StationClock.ViennaHourHand = 4; + +//clock minute hand (Minutenzeiger) +StationClock.PointedMinuteHand = 1; +StationClock.BarMinuteHand = 2; +StationClock.SwissMinuteHand = 3; +StationClock.ViennaMinuteHand = 4; + +//clock second hand (Sekundenzeiger) +StationClock.NoSecondHand = 0; +StationClock.BarSecondHand = 1; +StationClock.HoleShapedSecondHand = 2; +StationClock.NewHoleShapedSecondHand = 3; +StationClock.SwissSecondHand = 4; + +// clock boss (Zeigerabdeckung) +StationClock.NoBoss = 0; +StationClock.BlackBoss = 1; +StationClock.RedBoss = 2; +StationClock.ViennaBoss = 3; + +// minute hand behavoir +StationClock.CreepingMinuteHand = 0; +StationClock.BouncingMinuteHand = 1; +StationClock.ElasticBouncingMinuteHand = 2; + +// second hand behavoir +StationClock.CreepingSecondHand = 0; +StationClock.BouncingSecondHand = 1; +StationClock.ElasticBouncingSecondHand = 2; +StationClock.OverhastySecondHand = 3; + + +function StationClock(clockId) { + this.clockId = clockId; + this.radius = 0; + + // hour offset + this.hourOffset = 0; + + // clock body + this.body = StationClock.RoundBody; + this.bodyShadowColor = "rgba(0,0,0,0.5)"; + this.bodyShadowOffsetX = 0.03; + this.bodyShadowOffsetY = 0.03; + this.bodyShadowBlur = 0.06; + + // body dial + this.dial = StationClock.GermanStrokeDial; + this.dialColor = 'rgb(60,60,60)'; + + // clock hands + this.hourHand = StationClock.PointedHourHand; + this.minuteHand = StationClock.PointedMinuteHand; + this.secondHand = StationClock.HoleShapedSecondHand; + this.handShadowColor = 'rgba(0,0,0,0.3)'; + this.handShadowOffsetX = 0.03; + this.handShadowOffsetY = 0.03; + this.handShadowBlur = 0.04; + + // clock colors + this.hourHandColor = 'rgb(0,0,0)'; + this.minuteHandColor = 'rgb(0,0,0)'; + this.secondHandColor = 'rgb(200,0,0)'; + + // clock boss + this.boss = StationClock.NoBoss; + this.bossShadowColor = "rgba(0,0,0,0.2)"; + this.bossShadowOffsetX = 0.02; + this.bossShadowOffsetY = 0.02; + this.bossShadowBlur = 0.03; + + // hand behavoir + this.minuteHandBehavoir = StationClock.CreepingMinuteHand; + this.secondHandBehavoir = StationClock.OverhastySecondHand; + + // hand animation + this.minuteHandAnimationStep = 0; + this.secondHandAnimationStep = 0; + this.lastMinute = 0; + this.lastSecond = 0; +}; + +StationClock.prototype.draw = function() { + var clock = document.getElementById(this.clockId); + if (clock) { + var context = clock.getContext('2d'); + if (context) { + this.radius = 0.75 * (Math.min(clock.width, clock.height) / 2); + + // clear canvas and set new origin + context.clearRect(0, 0, clock.width, clock.height); + context.save(); + context.translate(clock.width / 2, clock.height / 2); + + // draw body + if (this.body != StationClock.NoStrokeBody) { + context.save(); + switch (this.body) { + case StationClock.SmallWhiteBody: + this.fillCircle(context, "rgb(255,255,255)", 0, 0, 1); + break; + case StationClock.RoundBody: + this.fillCircle(context, "rgb(255,255,255)", 0, 0, 1.1); + context.save(); + this.setShadow(context, this.bodyShadowColor, this.bodyShadowOffsetX, this.bodyShadowOffsetY, this.bodyShadowBlur); + this.strokeCircle(context, "rgb(0,0,0)", 0, 0, 1.1, 0.07); + context.restore(); + break; + case StationClock.RoundGreenBody: + this.fillCircle(context, "rgb(235,236,212)", 0, 0, 1.1); + context.save(); + this.setShadow(context, this.bodyShadowColor, this.bodyShadowOffsetX, this.bodyShadowOffsetY, this.bodyShadowBlur); + this.strokeCircle(context, "rgb(180,180,180)", 0, 0, 1.1, 0.2); + context.restore(); + this.strokeCircle(context, "rgb(29,84,31)", 0, 0, 1.15, 0.1); + context.save(); + this.setShadow(context, "rgba(235,236,212,100)", -0.02, -0.02, 0.09); + this.strokeCircle(context, 'rgb(76,128,110)', 0, 0, 1.1, 0.08); + context.restore(); + break; + case StationClock.SquareBody: + context.save(); + this.setShadow(context, this.bodyShadowColor, this.bodyShadowOffsetX, this.bodyShadowOffsetY, this.bodyShadowBlur); + this.fillSquare(context, 'rgb(237,235,226)', 0, 0, 2.4); + this.strokeSquare(context, 'rgb(38,106,186)', 0, 0, 2.32, 0.16); + context.restore(); + context.save(); + this.setShadow(context, this.bodyShadowColor, this.bodyShadowOffsetX, this.bodyShadowOffsetY, this.bodyShadowBlur); + this.strokeSquare(context, 'rgb(42,119,208)', 0, 0, 2.24, 0.08); + context.restore(); + break; + case StationClock.ViennaBody: + context.save(); + this.fillSymmetricPolygon(context, 'rgb(156,156,156)', [[-1.2,1.2],[-1.2,-1.2]],0.1); + this.fillPolygon(context, 'rgb(156,156,156)', 0,1.2 , 1.2,1.2 , 1.2,0); + this.fillCircle(context, 'rgb(255,255,255)', 0, 0, 1.05, 0.08); + this.strokeCircle(context, 'rgb(0,0,0)', 0, 0, 1.05, 0.01); + this.strokeCircle(context, 'rgb(100,100,100)', 0, 0, 1.1, 0.01); + this.fillPolygon(context, 'rgb(100,100,100)', 0.45,1.2 , 1.2,1.2 , 1.2,0.45); + this.fillPolygon(context, 'rgb(170,170,170)', 0.45,-1.2 , 1.2,-1.2 , 1.2,-0.45); + this.fillPolygon(context, 'rgb(120,120,120)', -0.45,1.2 , -1.2,1.2 , -1.2,0.45); + this.fillPolygon(context, 'rgb(200,200,200)', -0.45,-1.2 , -1.2,-1.2 , -1.2,-0.45); + this.strokeSymmetricPolygon(context, 'rgb(156,156,156)', [[-1.2,1.2],[-1.2,-1.2]],0.01); + this.fillPolygon(context, 'rgb(255,0,0)', 0.05,-0.6 , 0.15,-0.6 , 0.15,-0.45 , 0.05,-0.45); + this.fillPolygon(context, 'rgb(255,0,0)', -0.05,-0.6 , -0.15,-0.6 , -0.15,-0.45 , -0.05,-0.45); + this.fillPolygon(context, 'rgb(255,0,0)', 0.05,-0.35 , 0.15,-0.35 , 0.15,-0.30 , 0.10,-0.20 , 0.05,-0.20); + this.fillPolygon(context, 'rgb(255,0,0)', -0.05,-0.35 , -0.15,-0.35 , -0.15,-0.30 , -0.10,-0.20 , -0.05,-0.20); + context.restore(); + break; + } + context.restore(); + } + + // draw dial + for (var i = 0; i < 60; i++) { + context.save(); + context.rotate(i * Math.PI / 30); + switch (this.dial) { + case StationClock.SwissStrokeDial: + if ((i % 5) == 0) { + this.strokeLine(context, this.dialColor, 0.0, -1.0, 0.0, -0.75, 0.07); + } else { + this.strokeLine(context, this.dialColor, 0.0, -1.0, 0.0, -0.92, 0.026); + } + break; + case StationClock.AustriaStrokeDial: + if ((i % 5) == 0) { + this.fillPolygon(context, this.dialColor, -0.04, -1.0, 0.04, -1.0, 0.03, -0.78, -0.03, -0.78); + } else { + this.strokeLine(context, this.dialColor, 0.0, -1.0, 0.0, -0.94, 0.02); + } + break; + case StationClock.GermanStrokeDial: + if ((i % 15) == 0) { + this.strokeLine(context, this.dialColor, 0.0, -1.0, 0.0, -0.70, 0.08); + } else if ((i % 5) == 0) { + this.strokeLine(context, this.dialColor, 0.0, -1.0, 0.0, -0.76, 0.08); + } else { + this.strokeLine(context, this.dialColor, 0.0, -1.0, 0.0, -0.92, 0.036); + } + break; + case StationClock.GermanHourStrokeDial: + if ((i % 15) == 0) { + this.strokeLine(context, this.dialColor, 0.0, -1.0, 0.0, -0.70, 0.10); + } else if ((i % 5) == 0) { + this.strokeLine(context, this.dialColor, 0.0, -1.0, 0.0, -0.74, 0.08); + } + break; + case StationClock.ViennaStrokeDial: + if ((i % 15) == 0) { + this.fillPolygon(context, this.dialColor, 0.7,-0.1, 0.6,0, 0.7,0.1, 1,0.03, 1,-0.03); + } else if ((i % 5) == 0) { + this.fillPolygon(context, this.dialColor, 0.85,-0.06, 0.78,0, 0.85,0.06, 1,0.03, 1,-0.03); + } + this.fillCircle(context, this.dialColor, 0.0, -1.0, 0.03); + break; + } + context.restore(); + } + + // get current time + var time = new Date(); + var millis = time.getMilliseconds() / 1000.0; + var seconds = time.getSeconds(); + var minutes = time.getMinutes(); + var hours = time.getHours() + this.hourOffset; + + // draw hour hand + context.save(); + context.rotate(hours * Math.PI / 6 + minutes * Math.PI / 360); + this.setShadow(context, this.handShadowColor, this.handShadowOffsetX, this.handShadowOffsetY, this.handShadowBlur); + switch (this.hourHand) { + case StationClock.BarHourHand: + this.fillPolygon(context, this.hourHandColor, -0.05, -0.6, 0.05, -0.6, 0.05, 0.15, -0.05, 0.15); + break; + case StationClock.PointedHourHand: + this.fillPolygon(context, this.hourHandColor, 0.0, -0.6, 0.065, -0.53, 0.065, 0.19, -0.065, 0.19, -0.065, -0.53); + break; + case StationClock.SwissHourHand: + this.fillPolygon(context, this.hourHandColor, -0.05, -0.6, 0.05, -0.6, 0.065, 0.26, -0.065, 0.26); + break; + case StationClock.ViennaHourHand: + this.fillSymmetricPolygon(context, this.hourHandColor, [[-0.02,-0.72],[-0.08,-0.56],[-0.15,-0.45],[-0.06,-0.30],[-0.03,0],[-0.1,0.2],[-0.05,0.23],[-0.03,0.2]]); + } + context.restore(); + + // draw minute hand + context.save(); + switch (this.minuteHandBehavoir) { + case StationClock.CreepingMinuteHand: + context.rotate((minutes + seconds / 60) * Math.PI / 30); + break; + case StationClock.BouncingMinuteHand: + context.rotate(minutes * Math.PI / 30); + break; + case StationClock.ElasticBouncingMinuteHand: + if (this.lastMinute != minutes) { + this.minuteHandAnimationStep = 3; + this.lastMinute = minutes; + } + context.rotate((minutes + this.getAnimationOffset(this.minuteHandAnimationStep)) * Math.PI / 30); + this.minuteHandAnimationStep--; + break; + } + this.setShadow(context, this.handShadowColor, this.handShadowOffsetX, this.handShadowOffsetY, this.handShadowBlur); + switch (this.minuteHand) { + case StationClock.BarMinuteHand: + this.fillPolygon(context, this.minuteHandColor, -0.05, -0.9, 0.035, -0.9, 0.035, 0.23, -0.05, 0.23); + break; + case StationClock.PointedMinuteHand: + this.fillPolygon(context, this.minuteHandColor, 0.0, -0.93, 0.045, -0.885, 0.045, 0.23, -0.045, 0.23, -0.045, -0.885); + break; + case StationClock.SwissMinuteHand: + this.fillPolygon(context, this.minuteHandColor, -0.035, -0.93, 0.035, -0.93, 0.05, 0.25, -0.05, 0.25); + break; + case StationClock.ViennaMinuteHand: + this.fillSymmetricPolygon(context, this.minuteHandColor, [[-0.02,-0.98],[-0.09,-0.7],[-0.03,0],[-0.05,0.2],[-0.01,0.4]]); + } + context.restore(); + + // draw second hand + context.save(); + switch (this.secondHandBehavoir) { + case StationClock.OverhastySecondHand: + context.rotate(Math.min((seconds + millis) * (60.0 / 58.5), 60.0) * Math.PI / 30); + break; + case StationClock.CreepingSecondHand: + context.rotate((seconds + millis) * Math.PI / 30); + break; + case StationClock.BouncingSecondHand: + context.rotate(seconds * Math.PI / 30); + break; + case StationClock.ElasticBouncingSecondHand: + if (this.lastSecond != seconds) { + this.secondHandAnimationStep = 3; + this.lastSecond = seconds; + } + context.rotate((seconds + this.getAnimationOffset(this.secondHandAnimationStep)) * Math.PI / 30); + this.secondHandAnimationStep--; + break; + } + this.setShadow(context, this.handShadowColor, this.handShadowOffsetX, this.handShadowOffsetY, this.handShadowBlur); + switch (this.secondHand) { + case StationClock.BarSecondHand: + this.fillPolygon(context, this.secondHandColor, -0.006, -0.92, 0.006, -0.92, 0.028, 0.23, -0.028, 0.23); + break; + case StationClock.HoleShapedSecondHand: + this.fillPolygon(context, this.secondHandColor, 0.0, -0.9, 0.011, -0.889, 0.01875, -0.6, -0.01875, -0.6, -0.011, -0.889); + this.fillPolygon(context, this.secondHandColor, 0.02, -0.4, 0.025, 0.22, -0.025, 0.22, -0.02, -0.4); + this.strokeCircle(context, this.secondHandColor, 0, -0.5, 0.083, 0.066); + break; + case StationClock.NewHoleShapedSecondHand: + this.fillPolygon(context, this.secondHandColor, 0.0, -0.95, 0.015, -0.935, 0.0187, -0.65, -0.0187, -0.65, -0.015, -0.935); + this.fillPolygon(context, this.secondHandColor, 0.022, -0.45, 0.03, 0.27, -0.03, 0.27, -0.022, -0.45); + this.strokeCircle(context, this.secondHandColor, 0, -0.55, 0.085, 0.07); + break; + case StationClock.SwissSecondHand: + this.strokeLine(context, this.secondHandColor, 0.0, -0.6, 0.0, 0.35, 0.026); + this.fillCircle(context, this.secondHandColor, 0, -0.64, 0.1); + break; + case StationClock.ViennaSecondHand: + this.strokeLine(context, this.secondHandColor, 0.0, -0.6, 0.0, 0.35, 0.026); + this.fillCircle(context, this.secondHandColor, 0, -0.64, 0.1); + break; + } + context.restore(); + + // draw clock boss + if (this.boss != StationClock.NoBoss) { + context.save(); + this.setShadow(context, this.bossShadowColor, this.bossShadowOffsetX, this.bossShadowOffsetY, this.bossShadowBlur); + switch (this.boss) { + case StationClock.BlackBoss: + this.fillCircle(context, 'rgb(0,0,0)', 0, 0, 0.1); + break; + case StationClock.RedBoss: + this.fillCircle(context, 'rgb(220,0,0)', 0, 0, 0.06); + break; + case StationClock.ViennaBoss: + this.fillCircle(context, 'rgb(0,0,0)', 0, 0, 0.07); + break; + } + context.restore(); + } + + context.restore(); + } + } +}; + +StationClock.prototype.getAnimationOffset = function(animationStep) { + switch (animationStep) { + case 3: return 0.2; + case 2: return -0.1; + case 1: return 0.05; + } + return 0; +}; + +StationClock.prototype.setShadow = function(context, color, offsetX, offsetY, blur) { + if (color) { + context.shadowColor = color; + context.shadowOffsetX = this.radius * offsetX; + context.shadowOffsetY = this.radius * offsetY; + context.shadowBlur = this.radius * blur; + } +}; + +StationClock.prototype.fillCircle = function(context, color, x, y, radius) { + if (color) { + context.beginPath(); + context.fillStyle = color; + context.arc(x * this.radius, y * this.radius, radius * this.radius, 0, 2 * Math.PI, true); + context.fill(); + } +}; + +StationClock.prototype.strokeCircle = function(context, color, x, y, radius, lineWidth) { + if (color) { + context.beginPath(); + context.strokeStyle = color; + context.lineWidth = lineWidth * this.radius; + context.arc(x * this.radius, y * this.radius, radius * this.radius, 0, 2 * Math.PI, true); + context.stroke(); + } +}; + +StationClock.prototype.fillSquare = function(context, color, x, y, size) { + if (color) { + context.fillStyle = color; + context.fillRect((x - size / 2) * this.radius, (y -size / 2) * this.radius, size * this.radius, size * this.radius); + } +}; + +StationClock.prototype.strokeSquare = function(context, color, x, y, size, lineWidth) { + if (color) { + context.strokeStyle = color; + context.lineWidth = lineWidth * this.radius; + context.strokeRect((x - size / 2) * this.radius, (y -size / 2) * this.radius, size * this.radius, size * this.radius); + } +}; + +StationClock.prototype.strokeLine = function(context, color, x1, y1, x2, y2, width) { + if (color) { + context.beginPath(); + context.strokeStyle = color; + context.moveTo(x1 * this.radius, y1 * this.radius); + context.lineTo(x2 * this.radius, y2 * this.radius); + context.lineWidth = width * this.radius; + context.stroke(); + } +}; + +StationClock.prototype.fillPolygon = function(context, color, x1, y1, x2, y2, x3, y3, x4, y4, x5, y5) { + if (color) { + context.beginPath(); + context.fillStyle = color; + context.moveTo(x1 * this.radius, y1 * this.radius); + context.lineTo(x2 * this.radius, y2 * this.radius); + context.lineTo(x3 * this.radius, y3 * this.radius); + context.lineTo(x4 * this.radius, y4 * this.radius); + if ((x5 != undefined) && (y5 != undefined)) { + context.lineTo(x5 * this.radius, y5 * this.radius); + } + context.lineTo(x1 * this.radius, y1 * this.radius); + context.fill(); + } +}; + +StationClock.prototype.fillSymmetricPolygon = function(context, color, points) { + context.beginPath(); + context.fillStyle = color; + context.moveTo(points[0][0] * this.radius, points[0][1] * this.radius); + for (var i = 1; i < points.length; i++) { + context.lineTo(points[i][0] * this.radius, points[i][1] * this.radius); + } + for (var i = points.length - 1; i >= 0; i--) { + context.lineTo(0 - points[i][0] * this.radius, points[i][1] * this.radius); + } + context.lineTo(points[0][0] * this.radius, points[0][1] * this.radius); + context.fill(); +}; + +StationClock.prototype.strokeSymmetricPolygon = function(context, color, points, width) { + context.beginPath(); + context.strokeStyle = color; + context.moveTo(points[0][0] * this.radius, points[0][1] * this.radius); + for (var i = 1; i < points.length; i++) { + context.lineTo(points[i][0] * this.radius, points[i][1] * this.radius); + } + for (var i = points.length - 1; i >= 0; i--) { + context.lineTo(0 - points[i][0] * this.radius, points[i][1] * this.radius); + } + context.lineTo(points[0][0] * this.radius, points[0][1] * this.radius); + context.lineWidth = width * this.radius; + context.stroke(); +}; + +