initial commit
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
bin/
|
||||
37
manifest.xml
Normal file
37
manifest.xml
Normal file
@ -0,0 +1,37 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This is a generated file. It is highly recommended that you DO NOT edit this file. -->
|
||||
<iq:manifest version="3" xmlns:iq="http://www.garmin.com/xml/connectiq">
|
||||
<!--
|
||||
Use "Monkey C: Edit Application" from the Visual Studio Code command palette
|
||||
to update the application attributes.
|
||||
-->
|
||||
<iq:application id="87cf1f68-dcef-4751-bf6f-9337d59b08dd" type="watchface" name="@Strings.AppName" entry="wfApp" launcherIcon="@Drawables.LauncherIcon" minApiLevel="5.2.0">
|
||||
<!--
|
||||
Use the following from the Visual Studio Code comand palette to edit
|
||||
the build targets:
|
||||
"Monkey C: Set Products by Product Category" - Lets you add all products
|
||||
that belong to the same product category
|
||||
"Monkey C: Edit Products" - Lets you add or remove any product
|
||||
-->
|
||||
<iq:products>
|
||||
<iq:product id="fenix8pro47mm"/>
|
||||
</iq:products>
|
||||
<!--
|
||||
Use "Monkey C: Edit Permissions" from the Visual Studio Code command
|
||||
palette to update permissions.
|
||||
-->
|
||||
<iq:permissions/>
|
||||
<!--
|
||||
Use "Monkey C: Edit Languages" from the Visual Studio Code command
|
||||
palette to edit your compatible language list.
|
||||
-->
|
||||
<iq:languages>
|
||||
<iq:language>eng</iq:language>
|
||||
</iq:languages>
|
||||
<!--
|
||||
Use "Monkey C: Configure Monkey Barrel" from the Visual Studio Code
|
||||
command palette to edit the included barrels.
|
||||
-->
|
||||
<iq:barrels/>
|
||||
</iq:application>
|
||||
</iq:manifest>
|
||||
1
monkey.jungle
Executable file
1
monkey.jungle
Executable file
@ -0,0 +1 @@
|
||||
project.manifest = manifest.xml
|
||||
3
resources/drawables/drawables.xml
Executable file
3
resources/drawables/drawables.xml
Executable file
@ -0,0 +1,3 @@
|
||||
<drawables xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://developer.garmin.com/downloads/connect-iq/resources.xsd">
|
||||
<bitmap id="LauncherIcon" filename="launcher_icon.svg" dithering="none" />
|
||||
</drawables>
|
||||
5
resources/drawables/launcher_icon.svg
Executable file
5
resources/drawables/launcher_icon.svg
Executable file
@ -0,0 +1,5 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="24" height="24" fill="#000000"/>
|
||||
<path d="M12.1941 10.8471L16.1353 7.30588L16.9235 8.17646L13.1059 11.6059C13.1471 11.7294 13.1765 11.8588 13.1765 12C13.1765 12.6471 12.6471 13.1765 12 13.1765C11.701 13.1765 11.4272 13.0634 11.219 12.878L5.90332 15.9461L5.60926 15.4367L10.8899 12.3888C10.8469 12.2669 10.8235 12.1361 10.8235 12C10.8235 11.9824 10.8265 11.9662 10.8294 11.95C10.8324 11.9338 10.8353 11.9176 10.8353 11.9L8.12353 10.0471L8.78235 9.07058L11.5059 10.9353C11.6588 10.8647 11.8235 10.8235 12 10.8235C12.0647 10.8235 12.1294 10.8353 12.1941 10.8471Z" fill="#F4F4F4"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12ZM11.4118 20.2146V18.4706H12.5882V20.2146C16.6676 19.9267 19.9267 16.6676 20.2146 12.5882H18.4706V11.4118H20.2146C19.9267 7.33237 16.6676 4.07329 12.5882 3.78539V5.52941H11.4118V3.78539C7.33237 4.07329 4.07329 7.33237 3.78539 11.4118H5.52941V12.5882H3.78539C4.07329 16.6676 7.33237 19.9267 11.4118 20.2146Z" fill="#F4F4F4"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
24
resources/settings/properties.xml
Executable file
24
resources/settings/properties.xml
Executable file
@ -0,0 +1,24 @@
|
||||
<properties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://developer.garmin.com/downloads/connect-iq/resources.xsd">
|
||||
|
||||
<property id="BackgroundColor" type="number">0x000000</property>
|
||||
<property id="ForegroundColor" type="number">0xFF0000</property>
|
||||
<property id="UseMilitaryFormat" type="boolean">false</property>
|
||||
|
||||
<!-- main hands marks -->
|
||||
<!-- start mark -->
|
||||
<property id="Main/Marks/0/Type" type="number">2</property>
|
||||
<property id="Main/Marks/0/Color" type="number">0xFFFFFF</property>
|
||||
|
||||
<!-- primary mark -->
|
||||
<property id="Main/Marks/1/Type" type="number">1</property>
|
||||
<property id="Main/Marks/1/Color" type="number">0xFFFFFF</property>
|
||||
|
||||
<!-- secondary mark -->
|
||||
<property id="Main/Marks/2/Type" type="number">1</property>
|
||||
<property id="Main/Marks/2/Color" type="number">0xFFFFFF</property>
|
||||
|
||||
<!-- tertiary mark -->
|
||||
<property id="Main/Marks/3/Type" type="number">1</property>
|
||||
<property id="Main/Marks/3/Color" type="number">0xFFFFFF</property>
|
||||
|
||||
</properties>
|
||||
25
resources/settings/settings.xml
Executable file
25
resources/settings/settings.xml
Executable file
@ -0,0 +1,25 @@
|
||||
<settings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://developer.garmin.com/downloads/connect-iq/resources.xsd">
|
||||
|
||||
<setting propertyKey="@Properties.BackgroundColor" title="@Strings.BackgroundColorTitle">
|
||||
<settingConfig type="list">
|
||||
<listEntry value="0x000000">@Strings.ColorBlack</listEntry>
|
||||
<listEntry value="0x555555">@Strings.ColorDarkGray</listEntry>
|
||||
<listEntry value="0xAAAAAA">@Strings.ColorLightGray</listEntry>
|
||||
<listEntry value="0xFFFFFF">@Strings.ColorWhite</listEntry>
|
||||
</settingConfig>
|
||||
</setting>
|
||||
|
||||
<setting propertyKey="@Properties.ForegroundColor" title="@Strings.ForegroundColorTitle">
|
||||
<settingConfig type="list">
|
||||
<listEntry value="0x000000">@Strings.ColorBlack</listEntry>
|
||||
<listEntry value="0x0000FF">@Strings.ColorBlue</listEntry>
|
||||
<listEntry value="0xFF0000">@Strings.ColorRed</listEntry>
|
||||
<listEntry value="0xFFFFFF">@Strings.ColorWhite</listEntry>
|
||||
</settingConfig>
|
||||
</setting>
|
||||
|
||||
<setting propertyKey="@Properties.UseMilitaryFormat" title="@Strings.MilitaryFormatTitle">
|
||||
<settingConfig type="boolean" />
|
||||
</setting>
|
||||
|
||||
</settings>
|
||||
16
resources/strings/strings.xml
Normal file
16
resources/strings/strings.xml
Normal file
@ -0,0 +1,16 @@
|
||||
<strings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://developer.garmin.com/downloads/connect-iq/resources.xsd">
|
||||
|
||||
<string id="AppName">wf</string>
|
||||
|
||||
<string id="BackgroundColorTitle">Background Color</string>
|
||||
<string id="ForegroundColorTitle">Foreground Color</string>
|
||||
<string id="MilitaryFormatTitle">Military Format for 24 Hour Time</string>
|
||||
|
||||
<string id="ColorBlack">Black</string>
|
||||
<string id="ColorDarkGray">Dark Gray</string>
|
||||
<string id="ColorLightGray">Light Gray</string>
|
||||
<string id="ColorWhite">White</string>
|
||||
<string id="ColorBlue">Blue</string>
|
||||
<string id="ColorRed">Red</string>
|
||||
|
||||
</strings>
|
||||
56
source/Background/IBackground.mc
Normal file
56
source/Background/IBackground.mc
Normal file
@ -0,0 +1,56 @@
|
||||
import Toybox.Application.Properties;
|
||||
import Toybox.Graphics;
|
||||
import Toybox.Lang;
|
||||
import Toybox.WatchUi;
|
||||
|
||||
class IBackground extends Drawable {
|
||||
|
||||
var Marks as Array<IMark> = [];
|
||||
|
||||
typedef BackgroundParams as {
|
||||
:Identifier as Object,
|
||||
:Color as ColorType,
|
||||
};
|
||||
|
||||
enum BackgroundStyleType {
|
||||
SOLID_BACKGROUND,
|
||||
}
|
||||
|
||||
static function getBackground(style as BackgroundStyleType, options as BackgroundParams) as IBackground {
|
||||
switch (style) {
|
||||
case SOLID_BACKGROUND:
|
||||
default:
|
||||
return new SolidBackground(options);
|
||||
}
|
||||
}
|
||||
|
||||
function initialize(options as BackgroundParams) {
|
||||
var identifier = options[:Identifier];
|
||||
Drawable.initialize({:identifier => identifier});
|
||||
|
||||
for (var s = 0; s < 60; s += 1) {
|
||||
var markType = IMark.getMarkType(s);
|
||||
|
||||
var markIdentifier = Lang.format("$1$/Marks/$2$", [identifier, markType]);
|
||||
var markStyle = Properties.getValue(Lang.format("$1$/Type", [markIdentifier])) as IMark.MarkStyleType;
|
||||
|
||||
var mark = IMark.getMark(markStyle, {
|
||||
:Identifier => markIdentifier,
|
||||
:Seconds => s,
|
||||
:Color => Properties.getValue(Lang.format("$1$/Color", [markIdentifier])) as ColorType,
|
||||
});
|
||||
if (mark != null) {
|
||||
Marks.add(mark);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function draw(dc as Dc) as Void {
|
||||
drawBackground(dc);
|
||||
for (var i = 0; i < Marks.size(); ++i) {
|
||||
Marks[i].draw(dc);
|
||||
}
|
||||
}
|
||||
|
||||
function drawBackground(dc as Dc) as Void {}
|
||||
}
|
||||
29
source/Background/Marks/ArabicMark.mc
Normal file
29
source/Background/Marks/ArabicMark.mc
Normal file
@ -0,0 +1,29 @@
|
||||
import Toybox.Graphics;
|
||||
import Toybox.Lang;
|
||||
import Toybox.WatchUi;
|
||||
|
||||
class ArabicMark extends IMark {
|
||||
|
||||
var Font as FontType;
|
||||
|
||||
function initialize(options as IMark.MarkParams) {
|
||||
IMark.initialize(options);
|
||||
|
||||
Font = getOrElse(options[:Font], Graphics.FONT_SMALL);
|
||||
}
|
||||
|
||||
function drawMark(dc as Dc, x as Float, y as Float, length as Float) as Void {
|
||||
var angle = getAngle();
|
||||
var text = secondsToText();
|
||||
var dimentions = dc.getTextDimensions(text, Font);
|
||||
|
||||
dc.setColor(Color, Graphics.COLOR_TRANSPARENT);
|
||||
dc.drawText(x + length * InnerRadius * Math.cos(angle) - dimentions[0] / 2.0,
|
||||
y + length * InnerRadius * Math.sin(angle) - dimentions[1] / 2.0,
|
||||
Font, text, Graphics.TEXT_JUSTIFY_LEFT);
|
||||
}
|
||||
|
||||
function secondsToText() as String? {
|
||||
return getHours().toString();
|
||||
}
|
||||
}
|
||||
18
source/Background/Marks/DotMark.mc
Normal file
18
source/Background/Marks/DotMark.mc
Normal file
@ -0,0 +1,18 @@
|
||||
import Toybox.Graphics;
|
||||
import Toybox.Lang;
|
||||
import Toybox.WatchUi;
|
||||
|
||||
class DotMark extends IMark {
|
||||
|
||||
function initialize(options as IMark.MarkParams) {
|
||||
IMark.initialize(options);
|
||||
}
|
||||
|
||||
function drawMark(dc as Dc, x as Float, y as Float, length as Float) as Void {
|
||||
var angle = getAngle();
|
||||
|
||||
dc.setColor(Color, Graphics.COLOR_TRANSPARENT);
|
||||
dc.fillCircle(x + length * InnerRadius * Math.cos(angle), y + length * InnerRadius * Math.sin(angle),
|
||||
length * Size / 2.0);
|
||||
}
|
||||
}
|
||||
22
source/Background/Marks/DoubleLineMark.mc
Normal file
22
source/Background/Marks/DoubleLineMark.mc
Normal file
@ -0,0 +1,22 @@
|
||||
import Toybox.Graphics;
|
||||
import Toybox.Lang;
|
||||
import Toybox.WatchUi;
|
||||
|
||||
class DoubleLineMark extends IMark {
|
||||
|
||||
var Offset as Float = Math.toRadians(1.0);
|
||||
|
||||
function initialize(options as IMark.MarkParams) {
|
||||
IMark.initialize(options);
|
||||
}
|
||||
|
||||
function drawMark(dc as Dc, x as Float, y as Float, length as Float) as Void {
|
||||
var angle = getAngle();
|
||||
|
||||
dc.setColor(Color, Color);
|
||||
dc.drawLine(x + length * InnerRadius * Math.cos(angle - Offset), y + length * InnerRadius * Math.sin(angle - Offset),
|
||||
x + length * Radius * Math.cos(angle - Offset), y + length * Radius * Math.sin(angle - Offset));
|
||||
dc.drawLine(x + length * InnerRadius * Math.cos(angle + Offset), y + length * InnerRadius * Math.sin(angle + Offset),
|
||||
x + length * Radius * Math.cos(angle + Offset), y + length * Radius * Math.sin(angle + Offset));
|
||||
}
|
||||
}
|
||||
121
source/Background/Marks/IMark.mc
Normal file
121
source/Background/Marks/IMark.mc
Normal file
@ -0,0 +1,121 @@
|
||||
import Toybox.Graphics;
|
||||
import Toybox.Lang;
|
||||
import Toybox.WatchUi;
|
||||
|
||||
class IMark extends Drawable {
|
||||
|
||||
var CenterShift as [Float, Float];
|
||||
var Color as ColorType;
|
||||
var InnerRadius as Float;
|
||||
var Radius as Float;
|
||||
var Seconds as Number;
|
||||
var Size as Float;
|
||||
|
||||
typedef MarkParams as {
|
||||
:Identifier as Object,
|
||||
:Seconds as Number,
|
||||
:Color as ColorType,
|
||||
:Font as FontType, // not used
|
||||
:Size as Float,
|
||||
:HandsParams as IHands.HandsParams,
|
||||
};
|
||||
|
||||
enum MarkType {
|
||||
START_MARK = 0,
|
||||
PRIMARY_MARK = 1,
|
||||
SECONDARY_MARK = 2,
|
||||
TERTIARY_MARK = 3,
|
||||
}
|
||||
|
||||
enum MarkStyleType {
|
||||
EMPTY_MARK = 0,
|
||||
LINE_MARK = 1,
|
||||
DOUBLE_LINE_MARK = 2,
|
||||
DOT_MARK = 3,
|
||||
ARABIC_MARK = 4,
|
||||
ROMAN_MARK = 5,
|
||||
}
|
||||
|
||||
static function getMark(style as MarkStyleType, options as MarkParams) as IMark? {
|
||||
switch (style) {
|
||||
case LINE_MARK:
|
||||
return new LineMark(options);
|
||||
case DOUBLE_LINE_MARK:
|
||||
return new DoubleLineMark(options);
|
||||
case DOT_MARK:
|
||||
return new DotMark(options);
|
||||
case ARABIC_MARK:
|
||||
return new ArabicMark(options);
|
||||
case ROMAN_MARK:
|
||||
return new RomanMark(options);
|
||||
case EMPTY_MARK:
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static function getMarkType(seconds as Number) as MarkType {
|
||||
switch (seconds) {
|
||||
case 0:
|
||||
return START_MARK;
|
||||
case 15:
|
||||
case 30:
|
||||
case 45:
|
||||
return PRIMARY_MARK;
|
||||
case 5:
|
||||
case 10:
|
||||
case 20:
|
||||
case 25:
|
||||
case 35:
|
||||
case 40:
|
||||
case 50:
|
||||
case 55:
|
||||
return SECONDARY_MARK;
|
||||
default:
|
||||
return TERTIARY_MARK;
|
||||
}
|
||||
}
|
||||
|
||||
function initialize(options as MarkParams) {
|
||||
Drawable.initialize({:identifier => options[:Identifier]});
|
||||
|
||||
var handsParams = getOrElse(options[:HandsParams], {}) as IHands.HandsParams;
|
||||
|
||||
// scene
|
||||
CenterShift = getOrElse(handsParams[:CenterShift], [0.0, 0.0]);
|
||||
Radius = getOrElse(handsParams[:Radius], 1.0);
|
||||
|
||||
// properties
|
||||
Color = getOrElse(options[:Color], Graphics.COLOR_WHITE);
|
||||
Seconds = options[:Seconds];
|
||||
Size = getOrElse(options[:Size], 0.1);
|
||||
|
||||
// calculated
|
||||
InnerRadius = Radius * (1 - Size);
|
||||
}
|
||||
|
||||
function draw(dc as Dc) as Void {
|
||||
var center = getCenter(dc, CenterShift);
|
||||
var length = min(center[0], center[1]);
|
||||
drawMark(dc, center[0], center[1], length);
|
||||
}
|
||||
|
||||
function drawMark(dc as Dc, x as Float, y as Float, length as Float) as Void {}
|
||||
|
||||
function getAngle() as Float {
|
||||
return Math.toRadians(Seconds * 6.0 - 90);
|
||||
}
|
||||
|
||||
function getHours() as Number? {
|
||||
if (Seconds % 5 != 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var hours = Seconds / 5;
|
||||
if (hours == 0) {
|
||||
return 12;
|
||||
}
|
||||
|
||||
return hours;
|
||||
}
|
||||
}
|
||||
18
source/Background/Marks/LineMark.mc
Normal file
18
source/Background/Marks/LineMark.mc
Normal file
@ -0,0 +1,18 @@
|
||||
import Toybox.Graphics;
|
||||
import Toybox.Lang;
|
||||
import Toybox.WatchUi;
|
||||
|
||||
class LineMark extends IMark {
|
||||
|
||||
function initialize(options as IMark.MarkParams) {
|
||||
IMark.initialize(options);
|
||||
}
|
||||
|
||||
function drawMark(dc as Dc, x as Float, y as Float, length as Float) as Void {
|
||||
var angle = getAngle();
|
||||
|
||||
dc.setColor(Color, Color);
|
||||
dc.drawLine(x + length * InnerRadius * Math.cos(angle), y + length * InnerRadius * Math.sin(angle),
|
||||
x + length * Radius * Math.cos(angle), y + length * Radius * Math.sin(angle));
|
||||
}
|
||||
}
|
||||
41
source/Background/Marks/RomanMark.mc
Normal file
41
source/Background/Marks/RomanMark.mc
Normal file
@ -0,0 +1,41 @@
|
||||
import Toybox.Graphics;
|
||||
import Toybox.Lang;
|
||||
import Toybox.WatchUi;
|
||||
|
||||
class RomanMark extends ArabicMark {
|
||||
|
||||
function initialize(options as IMark.MarkParams) {
|
||||
ArabicMark.initialize(options);
|
||||
}
|
||||
|
||||
function secondsToText() as String? {
|
||||
switch (getHours()) {
|
||||
case 1:
|
||||
return "I";
|
||||
case 2:
|
||||
return "II";
|
||||
case 3:
|
||||
return "III";
|
||||
case 4:
|
||||
return "IV";
|
||||
case 5:
|
||||
return "V";
|
||||
case 6:
|
||||
return "VI";
|
||||
case 7:
|
||||
return "VII";
|
||||
case 8:
|
||||
return "VIII";
|
||||
case 9:
|
||||
return "IX";
|
||||
case 10:
|
||||
return "X";
|
||||
case 11:
|
||||
return "XI";
|
||||
case 12:
|
||||
return "XII";
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
19
source/Background/SolidBackground.mc
Normal file
19
source/Background/SolidBackground.mc
Normal file
@ -0,0 +1,19 @@
|
||||
import Toybox.Graphics;
|
||||
import Toybox.Lang;
|
||||
import Toybox.WatchUi;
|
||||
|
||||
class SolidBackground extends IBackground {
|
||||
|
||||
var Color as ColorType;
|
||||
|
||||
function initialize(options as IBackground.BackgroundParams) {
|
||||
IBackground.initialize(options);
|
||||
|
||||
Color = getOrElse(options[:Color], Graphics.COLOR_BLACK);
|
||||
}
|
||||
|
||||
function drawBackground(dc as Dc) as Void {
|
||||
dc.setColor(Graphics.COLOR_TRANSPARENT, Color);
|
||||
dc.clear();
|
||||
}
|
||||
}
|
||||
59
source/Hands/IHands.mc
Normal file
59
source/Hands/IHands.mc
Normal file
@ -0,0 +1,59 @@
|
||||
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;
|
||||
|
||||
typedef HandsParams as {
|
||||
:Identifier as Object,
|
||||
:CenterShift as [Float, Float],
|
||||
:Radius as Float,
|
||||
};
|
||||
|
||||
enum HandType {
|
||||
HOURS_HAND,
|
||||
MINUTES_HAND,
|
||||
SECONDS_HAND,
|
||||
}
|
||||
|
||||
enum HandStyleType {
|
||||
SIMPLE_HANDS,
|
||||
}
|
||||
|
||||
static function getHands(style as HandStyleType) as IHands {
|
||||
switch (style) {
|
||||
case SIMPLE_HANDS:
|
||||
default:
|
||||
return new SimpleHands({});
|
||||
}
|
||||
}
|
||||
|
||||
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, CenterShift);
|
||||
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_HAND);
|
||||
|
||||
var minutesAngle = now.min * 6.0;
|
||||
drawHand(dc, center[0], center[1], minutesAngle, length, MINUTES_HAND);
|
||||
|
||||
var secondsAngle = now.sec * 6.0;
|
||||
drawHand(dc, center[0], center[1], secondsAngle, length, SECONDS_HAND);
|
||||
}
|
||||
|
||||
function drawHand(dc as Dc, x as Float, y as Float, angle as Float, length as Float, handType as HandType) as Void {}
|
||||
}
|
||||
48
source/Hands/SimpleHands.mc
Normal file
48
source/Hands/SimpleHands.mc
Normal file
@ -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 color = getColor(handType);
|
||||
angle = Math.toRadians(angle - 90);
|
||||
length *= getLenght(handType);
|
||||
|
||||
dc.setColor(color, color);
|
||||
dc.drawLine(x, y, x + length * Math.cos(angle), y + length * Math.sin(angle));
|
||||
}
|
||||
|
||||
private function getColor(handType as IHands.HandType) as ColorType {
|
||||
switch (handType) {
|
||||
case SECONDS_HAND:
|
||||
return SecondsColor;
|
||||
default:
|
||||
return Color;
|
||||
}
|
||||
}
|
||||
|
||||
private function getLenght(handType as IHands.HandType) as Float {
|
||||
switch (handType) {
|
||||
case HOURS_HAND:
|
||||
return 0.7;
|
||||
default:
|
||||
return 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
23
source/Utils.mc
Normal file
23
source/Utils.mc
Normal file
@ -0,0 +1,23 @@
|
||||
import Toybox.Lang;
|
||||
import Toybox.Graphics;
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
function getCenter(dc as Dc, shift as [Float, Float]) as [Float, Float] {
|
||||
return [dc.getWidth() / 2.0 + shift[0], dc.getHeight() / 2.0 + shift[1]];
|
||||
}
|
||||
33
source/wfApp.mc
Normal file
33
source/wfApp.mc
Normal file
@ -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;
|
||||
}
|
||||
51
source/wfView.mc
Normal file
51
source/wfView.mc
Normal file
@ -0,0 +1,51 @@
|
||||
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 = IHands.getHands(IHands.SIMPLE_HANDS);
|
||||
background = IBackground.getBackground(IBackground.SOLID_BACKGROUND, {
|
||||
:Identifier => "Main",
|
||||
});
|
||||
}
|
||||
|
||||
// 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 {
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user