commit a552952ad73a7e1e361080fe73f256b7cdfa9b97 Author: Evgenii Alekseev Date: Thu Oct 9 14:37:45 2025 +0300 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e660fd9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +bin/ diff --git a/manifest.xml b/manifest.xml new file mode 100644 index 0000000..b3fa4e0 --- /dev/null +++ b/manifest.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + eng + + + + + \ No newline at end of file diff --git a/monkey.jungle b/monkey.jungle new file mode 100755 index 0000000..87796c7 --- /dev/null +++ b/monkey.jungle @@ -0,0 +1 @@ +project.manifest = manifest.xml diff --git a/resources/drawables/drawables.xml b/resources/drawables/drawables.xml new file mode 100755 index 0000000..6302154 --- /dev/null +++ b/resources/drawables/drawables.xml @@ -0,0 +1,3 @@ + + + diff --git a/resources/drawables/launcher_icon.svg b/resources/drawables/launcher_icon.svg new file mode 100755 index 0000000..e80aa20 --- /dev/null +++ b/resources/drawables/launcher_icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/resources/settings/properties.xml b/resources/settings/properties.xml new file mode 100755 index 0000000..ca0d9ef --- /dev/null +++ b/resources/settings/properties.xml @@ -0,0 +1,7 @@ + + + 0x000000 + 0xFF0000 + false + + diff --git a/resources/settings/settings.xml b/resources/settings/settings.xml new file mode 100755 index 0000000..47f6c80 --- /dev/null +++ b/resources/settings/settings.xml @@ -0,0 +1,25 @@ + + + + + @Strings.ColorBlack + @Strings.ColorDarkGray + @Strings.ColorLightGray + @Strings.ColorWhite + + + + + + @Strings.ColorBlack + @Strings.ColorBlue + @Strings.ColorRed + @Strings.ColorWhite + + + + + + + + diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml new file mode 100644 index 0000000..1754403 --- /dev/null +++ b/resources/strings/strings.xml @@ -0,0 +1,16 @@ + + + wf + + Background Color + Foreground Color + Military Format for 24 Hour Time + + Black + Dark Gray + Light Gray + White + Blue + Red + + diff --git a/source/Background/IBackground.mc b/source/Background/IBackground.mc new file mode 100644 index 0000000..d647889 --- /dev/null +++ b/source/Background/IBackground.mc @@ -0,0 +1,20 @@ +import Toybox.Graphics; +import Toybox.Lang; +import Toybox.WatchUi; + +class IBackground extends Drawable { + + typedef BackgroundParams as { + :Identifier as Object, + }; + + function initialize(options as BackgroundParams) { + Drawable.initialize({:identifier => options[:Identifier]}); + } + + function draw(dc as Dc) as Void { + drawBackground(dc); + } + + function drawBackground(dc as Dc) as Void {} +} diff --git a/source/Background/SolidBackground.mc b/source/Background/SolidBackground.mc new file mode 100644 index 0000000..e83f983 --- /dev/null +++ b/source/Background/SolidBackground.mc @@ -0,0 +1,24 @@ +import Toybox.Graphics; +import Toybox.Lang; +import Toybox.WatchUi; + +class SolidBackground extends IBackground { + + var Color as ColorType; + + typedef SolidBackgroundParams as { + :BackgroundParams as IBackground.BackgroundParams, + :Color as ColorType, + }; + + function initialize(options as SolidBackgroundParams) { + IBackground.initialize(getOrElse(options[:BackgroundParams], {})); + + Color = getOrElse(options[:Color], Graphics.COLOR_BLACK); + } + + function drawBackground(dc as Dc) as Void { + dc.setColor(Graphics.COLOR_TRANSPARENT, Color); + dc.clear(); + } +} \ No newline at end of file diff --git a/source/Hands/IHands.mc b/source/Hands/IHands.mc new file mode 100644 index 0000000..757b642 --- /dev/null +++ b/source/Hands/IHands.mc @@ -0,0 +1,51 @@ + import Toybox.Graphics; + import Toybox.Lang; + import Toybox.System; + import Toybox.WatchUi; + + class IHands extends Drawable { + + var CenterShift as [Float, Float]; + var Radius as Float; + + enum HandType { + HOURS, + MINUTES, + SECONDS, + } + + typedef HandsParams as { + :CenterShift as [Float, Float], + :Identifier as Object, + :Radius as Float, + }; + + function initialize(options as HandsParams) { + Drawable.initialize({:identifier => options[:Identifier]}); + + CenterShift = getOrElse(options[:CenterShift], [0.0, 0.0]); + Radius = getOrElse(options[:Radius], 0.9); + } + + function draw(dc as Dc) as Void { + var now = System.getClockTime(); + + var center = getCenter(dc); + var length = Radius * min(center[0], center[1]); + + var hourAngle = (now.hour % 12 + now.min / 60.0) * 30.0; + drawHand(dc, center[0], center[1], hourAngle, length, HOURS); + + var minutesAngle = now.min * 6.0; + drawHand(dc, center[0], center[1], minutesAngle, length, MINUTES); + + var secondsAngle = now.sec * 6.0; + drawHand(dc, center[0], center[1], secondsAngle, length, SECONDS); + } + + function drawHand(dc as Dc, x as Float, y as Float, angle as Float, length as Float, handType as HandType) as Void {} + + function getCenter(dc as Dc) as [Float, Float] { + return [dc.getWidth() / 2.0 + CenterShift[0], dc.getHeight() / 2.0 + CenterShift[1]]; + } + } \ No newline at end of file diff --git a/source/Hands/SimpleHands.mc b/source/Hands/SimpleHands.mc new file mode 100644 index 0000000..78a2e1f --- /dev/null +++ b/source/Hands/SimpleHands.mc @@ -0,0 +1,48 @@ +import Toybox.Graphics; +import Toybox.Lang; + +class SimpleHands extends IHands { + + var Color as ColorType; + var SecondsColor as ColorType; + + typedef SimpleHandsParams as { + :HandsParams as IHands.HandsParams, + :Color as ColorType, + :SecondsColor as ColorType, + }; + + function initialize(options as SimpleHandsParams) { + IHands.initialize(getOrElse(options[:HandsParams], {})); + + Color = getOrElse(options[:Color], Graphics.COLOR_WHITE); + SecondsColor = getOrElse(options[:SecondsColor], Graphics.COLOR_RED); + } + + function drawHand(dc as Dc, x as Float, y as Float, angle as Float, length as Float, handType as IHands.HandType) as Void { + var rad = (angle - 90) * Math.PI / 180.0; + var color = getColor(handType); + length *= getLenght(handType); + + dc.setColor(color, color); + dc.drawLine(x, y, x + length * Math.cos(rad), y + length * Math.sin(rad)); + } + + private function getColor(handType as IHands.HandType) as ColorType { + switch (handType) { + case IHands.SECONDS: + return SecondsColor; + default: + return Color; + } + } + + private function getLenght(handType as IHands.HandType) as Float { + switch (handType) { + case IHands.HOURS: + return 0.7; + default: + return 1.0; + } + } +} \ No newline at end of file diff --git a/source/Utils.mc b/source/Utils.mc new file mode 100644 index 0000000..24834ce --- /dev/null +++ b/source/Utils.mc @@ -0,0 +1,20 @@ +import Toybox.Lang; + +typedef Numeric as Number or Float or Long or Double; + +// no types here, because this is generic, which are not supported by language +function getOrElse(value, defaultValue) { + if (value == null) { + return defaultValue; + } else { + return value; + } +} + +function min(left as Numeric, right as Numeric) as Numeric { + if (left < right) { + return left; + } else { + return right; + } +} \ No newline at end of file diff --git a/source/wfApp.mc b/source/wfApp.mc new file mode 100644 index 0000000..eacfada --- /dev/null +++ b/source/wfApp.mc @@ -0,0 +1,33 @@ +import Toybox.Application; +import Toybox.Lang; +import Toybox.WatchUi; + +class wfApp extends Application.AppBase { + + function initialize() { + AppBase.initialize(); + } + + // onStart() is called on application start up + function onStart(state as Dictionary?) as Void { + } + + // onStop() is called when your application is exiting + function onStop(state as Dictionary?) as Void { + } + + // Return the initial view of your application here + function getInitialView() as [Views] or [Views, InputDelegates] { + return [ new wfView() ]; + } + + // New app settings have been received so trigger a UI update + function onSettingsChanged() as Void { + WatchUi.requestUpdate(); + } + +} + +function getApp() as wfApp { + return Application.getApp() as wfApp; +} \ No newline at end of file diff --git a/source/wfView.mc b/source/wfView.mc new file mode 100644 index 0000000..f0badb2 --- /dev/null +++ b/source/wfView.mc @@ -0,0 +1,49 @@ +import Toybox.Application; +import Toybox.Graphics; +import Toybox.Lang; +import Toybox.System; +import Toybox.WatchUi; + +class wfView extends WatchUi.WatchFace { + + private var hands as IHands; + private var background as IBackground; + + function initialize() { + WatchFace.initialize(); + + hands = new SimpleHands({}); + background = new SolidBackground({}); + } + + // Load your resources here + function onLayout(dc as Dc) as Void { + } + + // Called when this View is brought to the foreground. Restore + // the state of this View and prepare it to be shown. This includes + // loading resources into memory. + function onShow() as Void { + } + + // Update the view + function onUpdate(dc as Dc) as Void { + background.draw(dc); + hands.draw(dc); + } + + // Called when this View is removed from the screen. Save the + // state of this View here. This includes freeing resources from + // memory. + function onHide() as Void { + } + + // The user has just looked at their watch. Timers and animations may be started here. + function onExitSleep() as Void { + } + + // Terminate any active timers and prepare for slow updates. + function onEnterSleep() as Void { + } + +}