diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5e56e04 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/bin diff --git a/manifest.xml b/manifest.xml new file mode 100644 index 0000000..8610910 --- /dev/null +++ b/manifest.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + 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..a22c33c --- /dev/null +++ b/resources/drawables/drawables.xml @@ -0,0 +1,3 @@ + + + diff --git a/resources/drawables/launcher_icon.png b/resources/drawables/launcher_icon.png new file mode 100755 index 0000000..d3594e7 Binary files /dev/null and b/resources/drawables/launcher_icon.png differ diff --git a/resources/layouts/layouts.xml b/resources/layouts/layouts.xml new file mode 100755 index 0000000..b620a0a --- /dev/null +++ b/resources/layouts/layouts.xml @@ -0,0 +1,30 @@ + + + + + + 64 + + + + + + + + + + + + + + + diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml new file mode 100644 index 0000000..1e2c6f4 --- /dev/null +++ b/resources/strings/strings.xml @@ -0,0 +1,5 @@ + + RepaField + + My Value + diff --git a/source/RepaFieldApp.mc b/source/RepaFieldApp.mc new file mode 100644 index 0000000..df4bf1f --- /dev/null +++ b/source/RepaFieldApp.mc @@ -0,0 +1,28 @@ +import Toybox.Application; +import Toybox.Lang; +import Toybox.WatchUi; + +class RepaFieldApp 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 Array? { + return [ new RepaFieldView() ] as Array; + } + +} + +function getApp() as RepaFieldApp { + return Application.getApp() as RepaFieldApp; +} \ No newline at end of file diff --git a/source/RepaFieldBackground.mc b/source/RepaFieldBackground.mc new file mode 100644 index 0000000..5007272 --- /dev/null +++ b/source/RepaFieldBackground.mc @@ -0,0 +1,28 @@ +import Toybox.Application; +import Toybox.Graphics; +import Toybox.WatchUi; + +class Background extends WatchUi.Drawable { + + hidden var mColor as ColorValue; + + function initialize() { + var dictionary = { + :identifier => "Background" + }; + + Drawable.initialize(dictionary); + + mColor = Graphics.COLOR_BLACK; + } + + function setColor(color as ColorValue) as Void { + mColor = color; + } + + function draw(dc as Dc) as Void { + dc.setColor(Graphics.COLOR_TRANSPARENT, mColor); + dc.clear(); + } + +} diff --git a/source/RepaFieldHeartRate.mc b/source/RepaFieldHeartRate.mc new file mode 100644 index 0000000..6385cdc --- /dev/null +++ b/source/RepaFieldHeartRate.mc @@ -0,0 +1,56 @@ +import Toybox.Application; +import Toybox.Graphics; +import Toybox.WatchUi; +import Toybox.Lang; +import Toybox.System; + +class HeartRate extends WatchUi.Drawable { + + hidden var hrZones as Array; + hidden var hrValue as Numeric; + hidden var aColor as Graphics.ColorValue | Number; + hidden var y as Numeric; + + function initialize(params as Dictionary) { + Drawable.initialize(params); + + hrZones = [100, 120, 140, 160, 180, 200]; + hrValue = 0.0f; + aColor = 0xFF8800; + y = 64; + if (params.hasKey(:y)) { + y = params.get(:y) as Number; + } + } + + function setHRZones(zones as Array) as Void { + hrZones = zones; + } + + function setHRValue(value as Numeric) as Void { + hrValue = value; + } + + function setHRColor(color) as Void { + aColor = color; + } + + function draw(dc as Dc) as Void { + dc.setPenWidth(8); + dc.setColor(0x555555, Graphics.COLOR_TRANSPARENT); + var width = dc.getWidth(); + dc.drawLine(width * .1, 64, width * .9, 64); + + var percentage = 0.0f; + var zoneNr = hrZones.size(); + if (hrValue > hrZones[zoneNr - 1]) { + percentage = 1.0f; + } else if (hrValue < hrZones[0]) { + percentage = .0f; + } else { + percentage = (hrValue - hrZones[0]).toFloat() / (hrZones[zoneNr - 1] - hrZones[0]); + } + dc.setColor(aColor, Graphics.COLOR_TRANSPARENT); + dc.drawLine(width * .1, 64, width * (.1 + .8 * percentage), 64); + } +} diff --git a/source/RepaFieldStamina.mc b/source/RepaFieldStamina.mc new file mode 100644 index 0000000..6fab78a --- /dev/null +++ b/source/RepaFieldStamina.mc @@ -0,0 +1,18 @@ +import Toybox.Application; +import Toybox.Graphics; +import Toybox.WatchUi; + +class Stamina extends WatchUi.Drawable { + + function initialize() { + var dictionary = { + :identifier => "Stamina" + }; + + Drawable.initialize(dictionary); + } + + function draw(dc as Dc) as Void { + dc.setColor(0xFF8800, Graphics.COLOR_TRANSPARENT); + } +} diff --git a/source/RepaFieldTrack.mc b/source/RepaFieldTrack.mc new file mode 100644 index 0000000..3ab8e20 --- /dev/null +++ b/source/RepaFieldTrack.mc @@ -0,0 +1,18 @@ +import Toybox.Application; +import Toybox.Graphics; +import Toybox.WatchUi; + +class Track extends WatchUi.Drawable { + + function initialize() { + var dictionary = { + :identifier => "Track" + }; + + Drawable.initialize(dictionary); + } + + function draw(dc as Dc) as Void { + dc.setColor(0xFF8800, Graphics.COLOR_TRANSPARENT); + } +} diff --git a/source/RepaFieldView.mc b/source/RepaFieldView.mc new file mode 100644 index 0000000..84e4c9f --- /dev/null +++ b/source/RepaFieldView.mc @@ -0,0 +1,131 @@ +import Toybox.Activity; +import Toybox.Graphics; +import Toybox.Lang; +import Toybox.UserProfile; +import Toybox.WatchUi; + +class RepaFieldView extends WatchUi.DataField { + + hidden var hrValue as Numeric; + hidden var ahrValue as Numeric; + hidden var mhrValue as Numeric; + hidden var hrZones as Array; + + function initialize() { + DataField.initialize(); + hrValue = 0; + ahrValue = 0; + mhrValue = 0; + hrZones = UserProfile.getHeartRateZones(UserProfile.getCurrentSport()); + } + + function calculateHRColor(hr as Numeric) as Numeric { + var hrColor = Graphics.COLOR_BLACK; + if (hrZones != null) { + if (hr < hrZones[1]) { + hrColor = Graphics.COLOR_LT_GRAY; + } else if (hr < hrZones[2]) { + hrColor = Graphics.COLOR_BLUE; + } else if (hr < hrZones[3]) { + hrColor = Graphics.COLOR_GREEN; + } else if (hr < hrZones[4]) { + hrColor = Graphics.COLOR_YELLOW; + } else if (hr < hrZones[5]) { + hrColor = Graphics.COLOR_ORANGE; + } else { + hrColor = Graphics.COLOR_RED; + } + } + return hrColor; + } + + // Set your layout here. Anytime the size of obscurity of + // the draw context is changed this will be called. + function onLayout(dc as Dc) as Void { + var obscurityFlags = DataField.getObscurityFlags(); + + // TODO ? + // Top layout + if (obscurityFlags == (OBSCURE_TOP | OBSCURE_LEFT | OBSCURE_RIGHT)) { + View.setLayout(Rez.Layouts.TopLayout(dc)); + + // Bottom layout + } else if (obscurityFlags == (OBSCURE_BOTTOM | OBSCURE_LEFT | OBSCURE_RIGHT)) { + View.setLayout(Rez.Layouts.BottomLayout(dc)); + + // Use the generic, centered layout + } else { + View.setLayout(Rez.Layouts.MainLayout(dc)); + } + + var label = View.findDrawableById("label") as Text; + if (label != null) { + label.setText(Rez.Strings.label); + } + } + + // The given info object contains all the current workout information. + // Calculate a value and save it locally in this method. + // Note that compute() and onUpdate() are asynchronous, and there is no + // guarantee that compute() will be called before onUpdate(). + function compute(info as Activity.Info) as Void { + // See Activity.Info in the documentation for available information. + if (info has :currentHeartRate){ + if(info.currentHeartRate != null){ + hrValue = info.currentHeartRate as Number; + } else { + hrValue = 0; + } + } + if (info has :averageHeartRate){ + if(info.averageHeartRate != null){ + ahrValue = info.averageHeartRate as Number; + } else { + ahrValue = 0; + } + } + if (info has :maxHeartRate){ + if(info.maxHeartRate != null){ + mhrValue = info.maxHeartRate as Number; + } else { + mhrValue = 0; + } + } + } + + // Display the value you computed here. This will be called + // once a second when the data field is visible. + function onUpdate(dc as Dc) as Void { + // Set the background color + (View.findDrawableById("Background") as Background).setColor(getBackgroundColor()); + + // HR value + var hrColor = calculateHRColor(hrValue); + var hr = View.findDrawableById("hr") as Text; + hr.setColor(hrColor); + hr.setText(hrValue.format("%d")); + var ahr = View.findDrawableById("ahr") as Text; + ahr.setText(ahrValue.format("%d")); + var mhr = View.findDrawableById("mhr") as Text; + mhr.setText(mhrValue.format("%d")); + var hrGraph = View.findDrawableById("HeartRate") as HeartRate; + hrGraph.setHRColor(hrColor); + hrGraph.setHRZones(hrZones); + hrGraph.setHRValue(hrValue); + + // Set the foreground color and value + var value = View.findDrawableById("value") as Text; + if (value != null) { + if (getBackgroundColor() == Graphics.COLOR_BLACK) { + value.setColor(Graphics.COLOR_WHITE); + } else { + value.setColor(Graphics.COLOR_BLACK); + } + value.setText(hrValue.format("%d")); + } + + // Call parent's onUpdate(dc) to redraw the layout + View.onUpdate(dc); + } + +}