From 50148067ce1627072bd62d1ed9f7767c9e56f332 Mon Sep 17 00:00:00 2001 From: miss-architect Date: Sat, 13 Mar 2021 16:22:32 +0100 Subject: [PATCH] Updated SDK to support Button component and introduced support for newer watch models. --- manifest.xml | 46 ++++++--- resources/drawables/launcher_icon.png | Bin 692 -> 763 bytes resources/layouts/playerfield.xml | 50 +++++----- source/GameConfiguration.mc | 138 +++++++++++++------------- source/Session.mc | 3 +- source/SquashDelegate.mc | 27 +---- source/SquashView.mc | 79 ++++++++------- 7 files changed, 170 insertions(+), 173 deletions(-) diff --git a/manifest.xml b/manifest.xml index 50f29aa..65d8548 100644 --- a/manifest.xml +++ b/manifest.xml @@ -1,28 +1,42 @@ - - - - + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - + + + - eng - diff --git a/resources/drawables/launcher_icon.png b/resources/drawables/launcher_icon.png index 1fd5531333c83373e842fea07b5444373ed169b8..1df762a884a5ced8c4d2f88e4838c937a8b10f1b 100644 GIT binary patch delta 754 zcmVhfNkl?2 zd(QNl8FS5a-~a7*&vTx0&w1YWJkPn;N-AeN;1x7mY*FxLl(Pz0$%31q3C4$!qJNyV zLLWRUW#CnClLf!fK8H{;U`@GU*NLPjz-H_YBB9(+BvlA6YpR-h@n5}rD!aH zU$bOSu%!otsfWvOA0FY`3KgIqP$I=v$#N?HTpt&VtTCvA=I zrb=6QjTs$S3$V{(&krNo+DmW)K7YYuXo8W{sjVK!$!MtN=?%2!VK#V0mgC+CIqa*6 z&ujuzjldKbqS(sWg*oyn9nunrc{ zFZY8fa<&56pdaoqXB%w;EX3CG+Py9C1iGOGUtKbmSw8qJ_yOAb+A!kf-*yFf3flJ8 zBzR`2s#PD(UV>_2UKlA#b>aW{3(%LV9U8)D2Kma*!xGR3Vz_hyd@JyepklliMl#Ch kG(C5!B}cI($I_1d0Zi~<&PI)J#sB~S07*qoM6N<$g4eZOWdHyG delta 682 zcmV;b0#*I{1+)b*iBL{Q4GJ0x0000DNk~Le0000Y0000M2nGNE0Hv%>c>n+a1am@3 zR0s$N2z&@+h><=Qe*hVDMObuGZ)S9NVRB^vcXxL#X>MzCV_|S*E^l&Yo9;Xs0006p zNkleBSQIb+7Q${nC!oos{B@2|bDI0%_ol>k6iLxM}ETk+b zQyc6tdJQJmSTC0obMX&&$ZB% z+b2F%tfF$ilWONbS{Ng&6UJAG%@qcd*;AogI8gv|SD5)fAl=DiVU_34lgSg2mU761 zLj^DcjlqPmLZ>jjAihX=osvKP3GpkQ2?zf&GBu{De*|z`=ubm@M!24etgKm+tA+c* ztX!;3XcuM+^Q-K7DAI$$Cu2UZo@Dfzr|*{2inupN_T3>?5w?vP={h zjMudGo0Qz=HfYRvb Qd;kCd07*qoM6N<$f?yj!4gdfE diff --git a/resources/layouts/playerfield.xml b/resources/layouts/playerfield.xml index cca1929..f8eddff 100644 --- a/resources/layouts/playerfield.xml +++ b/resources/layouts/playerfield.xml @@ -1,26 +1,26 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/source/GameConfiguration.mc b/source/GameConfiguration.mc index aa9234a..91c829f 100644 --- a/source/GameConfiguration.mc +++ b/source/GameConfiguration.mc @@ -1,70 +1,70 @@ -using Toybox.WatchUi as Ui; -using Toybox.Application as App; - -//! Class that holds the configuration of the game -//! as total number of sets and the max score in -//! one set. It reads the configuration from -//! the object store of the application. -class GameConfiguration { - - hidden var setMaxScore; - hidden var setTotalSets; - hidden var player1Name; - hidden var player2Name; - static var instance = null; - - static function getInstance() { - if (instance == null) { - instance = new GameConfiguration(); - } - return instance; - } - - function initialize() { - setMaxScore = readKeyInt("setMaxScore", 11); - setTotalSets = readKeyInt("setTotalSets", 5); - player1Name = readString("player1Name", 8, Ui.loadResource(Rez.Strings.player1_score_label)); - player2Name = readString("player2Name", 8, Ui.loadResource(Rez.Strings.player2_score_label)); - } - - // make sure property is of type number - // see https://webcache.googleusercontent.com/search?cd=2&hl=en&ct=clnk&gl=ch& - // q=cache:0hxHRJ_80hcJ:https://forums.garmin.com/archive/index.php/t-359183.html+ - hidden function readKeyInt(key, thisDefault) { - var value = App.getApp().getProperty(key); - - if(value == null || !(value instanceof Number)) { - if(value != null) { - value = value.toNumber(); - } else { - value = thisDefault; - } - } - return value; - } - - hidden function readString(key, length, thisDefault) { - var value = App.getApp().getProperty(key); - - if(value == null) { - value = thisDefault; - } - return value.substring(0, length); - } - - function getMaxScore() { - return setMaxScore; - } - - function getTotalSets() { - return setTotalSets; - } - - function getPlayer1Name(){ - return player1Name; - } - - function getPlayer2Name() { - return player2Name; - } +using Toybox.WatchUi as Ui; +using Toybox.Application as App; + +//! Class that holds the configuration of the game +//! as total number of sets and the max score in +//! one set. It reads the configuration from +//! the object store of the application. +class GameConfiguration { + + hidden var setMaxScore; + hidden var setTotalSets; + hidden var player1Name; + hidden var player2Name; + static var instance = null; + + static function getInstance() { + if (instance == null) { + instance = new GameConfiguration(); + } + return instance; + } + + function initialize() { + setMaxScore = readKeyInt("setMaxScore", 11); + setTotalSets = readKeyInt("setTotalSets", 5); + player1Name = readString("player1Name", 8, App.loadResource(Rez.Strings.player1_score_label)); + player2Name = readString("player2Name", 8, App.loadResource(Rez.Strings.player2_score_label)); + } + + // make sure property is of type number + // see https://webcache.googleusercontent.com/search?cd=2&hl=en&ct=clnk&gl=ch& + // q=cache:0hxHRJ_80hcJ:https://forums.garmin.com/archive/index.php/t-359183.html+ + hidden function readKeyInt(key, thisDefault) { + var value = App.getApp().getProperty(key); + + if(value == null || !(value instanceof Number)) { + if(value != null) { + value = value.toNumber(); + } else { + value = thisDefault; + } + } + return value; + } + + hidden function readString(key, length, thisDefault) { + var value = App.getApp().getProperty(key); + + if(value == null) { + value = thisDefault; + } + return value.substring(0, length); + } + + function getMaxScore() { + return setMaxScore; + } + + function getTotalSets() { + return setTotalSets; + } + + function getPlayer1Name(){ + return player1Name; + } + + function getPlayer2Name() { + return player2Name; + } } \ No newline at end of file diff --git a/source/Session.mc b/source/Session.mc index 76c103a..da4b9d3 100644 --- a/source/Session.mc +++ b/source/Session.mc @@ -1,5 +1,6 @@ using Toybox.ActivityRecording as Record; using Toybox.FitContributor as Fit; +using Toybox.Attention as Attention; //! Class used to record an activity class Session { @@ -29,7 +30,7 @@ class Session { function start(){ if(Toybox has :ActivityRecording ) { if(!isRecording()) { - session = Record.createSession({:name=>"Squash", + session = Record.createSession({:name=>"Squash", :sport=>Record.SPORT_TENNIS, :subSport=>Record.SUB_SPORT_MATCH}); setupFields(); diff --git a/source/SquashDelegate.mc b/source/SquashDelegate.mc index 43727f2..e47e90b 100644 --- a/source/SquashDelegate.mc +++ b/source/SquashDelegate.mc @@ -84,32 +84,6 @@ class SquashDelegate extends Ui.BehaviorDelegate { } } - //! Function called when user taps a touch screen. - //! Replacement of Button feature that does not exist - //! in sdk v1.3.1 - function onTap(evt) - { - var x = evt.getCoordinates()[0]; - var y = evt.getCoordinates()[1]; - if (isHitting(x,y, player1LocX)) { - onPlayer1(); - } - else if (isHitting(x,y, player2LocX)) { - onPlayer2(); - } - return true; - } - - //! Check if the user is tapping a score button. - //! This function uses global variables defined - //! in SquashView. This is ugly, and has to be - //! improved! But if Garmin starts offering the - //! button feature in older devices, this won't be necessary. - function isHitting(x, y, xStartPosition) { - return (((x > xStartPosition) && (x < (xStartPosition + widthButton))) && - (y < heightButton)); - } - //! Event used in non-touchscreen devices to //! increment player 2 score function onNextPage() { @@ -133,6 +107,7 @@ class SquashDelegate extends Ui.BehaviorDelegate { new ExitConfirmationDelegate(), Ui.SLIDE_IMMEDIATE); return true; } + } //! Delegate that handles the event from the Confirmation dialog diff --git a/source/SquashView.mc b/source/SquashView.mc index 639302b..a460595 100644 --- a/source/SquashView.mc +++ b/source/SquashView.mc @@ -5,16 +5,6 @@ using Toybox.Sensor as Snsr; using Toybox.Time as Time; using Toybox.System as System; -//! These are four global variables used by the -//! SquashDelegate to determine if the user -//! touch a player score button. This implementation -//! is ugly, and it must be replaced by the button -//! if it's ever offered in the sdk of older devices -var player1LocX = 0; -var player2LocX = 0; -var heightButton = 0; -var widthButton = 0; - //! Class that represents the main Squash App //! View @@ -58,16 +48,35 @@ class SquashView extends Ui.View { initialY += 10; } - heightButton = dc.getFontHeight(Gfx.FONT_TINY) + dc.getFontHeight(Gfx.FONT_NUMBER_MILD) + VERTICAL_SPACING; - widthButton = (dc.getWidth() / 2) - HORIZONTAL_SPACING; - player1LocX = 0; - player2LocX = (dc.getWidth() / 2) + HORIZONTAL_SPACING; + var heightButton = dc.getFontHeight(Gfx.FONT_TINY) + dc.getFontHeight(Gfx.FONT_NUMBER_MILD) + VERTICAL_SPACING; + var widthButton = dc.getWidth() / 2; + var options = { + :locX=>0, + :locY=>initialY, + :width=>widthButton, + :height=>heightButton, + :behavior=>:onPlayer1, + :stateHighlighted=>Gfx.COLOR_RED + }; + playerButtons = new [2]; + playerButtons[0] = new Ui.Button(options); + + + options.put(:locX, dc.getWidth() / 2); + options.put(:behavior, :onPlayer2); + playerButtons[1] = new Ui.Button(options); + setLayout(playerButtons); } //! 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() { + // If device does not have touch screen, let's activate + // the hard key to be able to click player buttons. + if (!System.getDeviceSettings().isTouchScreen) { + setKeyToSelectableInteraction(true); + } } //! Update the view @@ -85,17 +94,9 @@ class SquashView extends Ui.View { var y = initialY; var gameConfiguration = GameConfiguration.getInstance(); - if (dataTracker.getServingPlayer() == Player.PLAYER_1) { - dc.setColor(Gfx.COLOR_RED, Gfx.COLOR_BLACK); - } - drawPlayerButton(dc, x, y, gameConfiguration.getPlayer1Name(), dataTracker.getPlayer1Score(), Gfx.TEXT_JUSTIFY_RIGHT); + drawPlayerButton(dc, x, y, gameConfiguration.getPlayer1Name(), dataTracker.getPlayer1Score(), Gfx.TEXT_JUSTIFY_RIGHT, isButtonHighlighted(playerButtons[0])); x = dc.getWidth() / 2 + HORIZONTAL_SPACING; - - if (dataTracker.getServingPlayer() == Player.PLAYER_2) { - dc.setColor(Gfx.COLOR_RED, Gfx.COLOR_BLACK); - } - - drawPlayerButton(dc, x, y, gameConfiguration.getPlayer2Name(), dataTracker.getPlayer2Score(), Gfx.TEXT_JUSTIFY_LEFT); + drawPlayerButton(dc, x, y, gameConfiguration.getPlayer2Name(), dataTracker.getPlayer2Score(), Gfx.TEXT_JUSTIFY_LEFT, isButtonHighlighted(playerButtons[1])); x = dc.getWidth() / 2 - HORIZONTAL_SPACING; // Size of label field y = y + dc.getFontHeight(Gfx.FONT_TINY) + VERTICAL_SPACING; @@ -105,12 +106,12 @@ class SquashView extends Ui.View { y = y + (VERTICAL_SPACING / 2); x = dc.getWidth() / 2 - HORIZONTAL_SPACING; - dc.drawText(x, y, Gfx.FONT_TINY, Ui.loadResource(Rez.Strings.steps_label), Gfx.TEXT_JUSTIFY_RIGHT); + dc.drawText(x, y, Gfx.FONT_TINY, Ui.loadResource(Rez.Strings.time_label), Gfx.TEXT_JUSTIFY_RIGHT); x = dc.getWidth() / 2 + HORIZONTAL_SPACING; dc.drawText(x, y, Gfx.FONT_TINY, Ui.loadResource(Rez.Strings.hr_label), Gfx.TEXT_JUSTIFY_LEFT); y = y + dc.getFontHeight(Gfx.FONT_TINY) + VERTICAL_SPACING; x = dc.getWidth() / 2 - HORIZONTAL_SPACING; - dc.drawText(x, y, Gfx.FONT_NUMBER_MILD, dataTracker.getNumberOfSteps(), Gfx.TEXT_JUSTIFY_RIGHT); + dc.drawText(x, y, Gfx.FONT_NUMBER_MILD, time, Gfx.TEXT_JUSTIFY_RIGHT); x = dc.getWidth() / 2 + HORIZONTAL_SPACING; dc.drawText(x, y, Gfx.FONT_NUMBER_MILD, heartRate, Gfx.TEXT_JUSTIFY_LEFT); @@ -119,14 +120,14 @@ class SquashView extends Ui.View { y = y + (VERTICAL_SPACING / 2); x = dc.getWidth() / 2 - HORIZONTAL_SPACING; - dc.drawText(x, y, Gfx.FONT_TINY, Ui.loadResource(Rez.Strings.time_label), Gfx.TEXT_JUSTIFY_RIGHT); + dc.drawText(x, y, Gfx.FONT_TINY, Ui.loadResource(Rez.Strings.steps_label), Gfx.TEXT_JUSTIFY_RIGHT); x = dc.getWidth() / 2 + HORIZONTAL_SPACING; dc.drawText(x, y, Gfx.FONT_TINY, Ui.loadResource(Rez.Strings.calories_label), Gfx.TEXT_JUSTIFY_LEFT); y = y + dc.getFontHeight(Gfx.FONT_TINY) + VERTICAL_SPACING; x = dc.getWidth() / 2 - HORIZONTAL_SPACING; - dc.drawText(x, y, Gfx.FONT_NUMBER_MILD, time, Gfx.TEXT_JUSTIFY_RIGHT); + dc.drawText(x, y, Gfx.FONT_NUMBER_MILD, dataTracker.getNumberOfSteps(), Gfx.TEXT_JUSTIFY_RIGHT); x = dc.getWidth() / 2 + HORIZONTAL_SPACING; dc.drawText(x, y, Gfx.FONT_NUMBER_MILD, dataTracker.getNumberOfCalories(), Gfx.TEXT_JUSTIFY_LEFT); @@ -141,17 +142,23 @@ class SquashView extends Ui.View { //! Draws nicely Player 1 or 2 buttons, considering if they are //! highlithed or not. - //! @param dc Where to draw it - //! @param label Label that indicates which player it is - //! @param score Score to draw in the button - //! @param justify Text justification (e.g. left, right) - hidden function drawPlayerButton(dc, x, y, label, score, justify){ - dc.drawText(x, y, Gfx.FONT_TINY, label, justify); - y = y + dc.getFontHeight(Gfx.FONT_TINY) + VERTICAL_SPACING; - dc.drawText(x, y, Gfx.FONT_NUMBER_MILD, score, justify); + //! @param dc Where to draw it + //! @param label Label that indicates which player it is + //! @param score Score to draw in the button + //! @param justify Text justification (e.g. left, right) + //! @param highlighted True if the button is highlighted + hidden function drawPlayerButton(dc, x, y, label, score, justify, highlighted){ + dc.setColor(Gfx.COLOR_WHITE, highlighted ? Gfx.COLOR_RED : Gfx.COLOR_BLACK); + dc.drawText(x, y, Gfx.FONT_TINY, label, justify); + y = y + dc.getFontHeight(Gfx.FONT_TINY) + VERTICAL_SPACING; + dc.drawText(x, y, Gfx.FONT_NUMBER_MILD, score, justify); dc.setColor(Gfx.COLOR_WHITE, Gfx.COLOR_BLACK); } + hidden function isButtonHighlighted(button) { + return button.getState() == :stateHighlighted; + } + //! Called when this View is removed from the screen. Save the //! state of this View here. This includes freeing resources from //! memory.