├── resources
├── layouts
│ └── layout.xml
├── strings
│ └── strings.xml
├── drawables
│ ├── mute-2-12.png
│ ├── mute-2-13.png
│ ├── alarm-clock-12.png
│ ├── alarm-clock-13.png
│ ├── alarm-clock-14.png
│ ├── alarm-clock-15.png
│ ├── alarm-clock-16.png
│ ├── bluetooth-2-12.png
│ ├── bluetooth-2-13.png
│ ├── bluetooth-2-14.png
│ ├── bluetooth-2-15.png
│ ├── bluetooth-2-16.png
│ ├── launcher_icon.png
│ ├── speech-bubble-12.png
│ ├── speech-bubble-13.png
│ ├── speech-bubble-14.png
│ ├── speech-bubble-15.png
│ ├── speech-bubble-16.png
│ └── drawables.xml
└── resources.xml
├── bin
├── SnapshotWatch.prg
├── SnapshotWatch-settings.json
└── SnapshotWatch.prg.debug.xml
├── .project
├── source
├── SnapshotWatchApp.mc
├── SunCalc.mc
└── SnapshotWatchView.mc
├── manifest.xml
└── README.md
/resources/layouts/layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/bin/SnapshotWatch.prg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrencroton/SnapshotWatch/HEAD/bin/SnapshotWatch.prg
--------------------------------------------------------------------------------
/resources/strings/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | SnapshotWatch
3 |
4 |
--------------------------------------------------------------------------------
/resources/drawables/mute-2-12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrencroton/SnapshotWatch/HEAD/resources/drawables/mute-2-12.png
--------------------------------------------------------------------------------
/resources/drawables/mute-2-13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrencroton/SnapshotWatch/HEAD/resources/drawables/mute-2-13.png
--------------------------------------------------------------------------------
/resources/drawables/alarm-clock-12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrencroton/SnapshotWatch/HEAD/resources/drawables/alarm-clock-12.png
--------------------------------------------------------------------------------
/resources/drawables/alarm-clock-13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrencroton/SnapshotWatch/HEAD/resources/drawables/alarm-clock-13.png
--------------------------------------------------------------------------------
/resources/drawables/alarm-clock-14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrencroton/SnapshotWatch/HEAD/resources/drawables/alarm-clock-14.png
--------------------------------------------------------------------------------
/resources/drawables/alarm-clock-15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrencroton/SnapshotWatch/HEAD/resources/drawables/alarm-clock-15.png
--------------------------------------------------------------------------------
/resources/drawables/alarm-clock-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrencroton/SnapshotWatch/HEAD/resources/drawables/alarm-clock-16.png
--------------------------------------------------------------------------------
/resources/drawables/bluetooth-2-12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrencroton/SnapshotWatch/HEAD/resources/drawables/bluetooth-2-12.png
--------------------------------------------------------------------------------
/resources/drawables/bluetooth-2-13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrencroton/SnapshotWatch/HEAD/resources/drawables/bluetooth-2-13.png
--------------------------------------------------------------------------------
/resources/drawables/bluetooth-2-14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrencroton/SnapshotWatch/HEAD/resources/drawables/bluetooth-2-14.png
--------------------------------------------------------------------------------
/resources/drawables/bluetooth-2-15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrencroton/SnapshotWatch/HEAD/resources/drawables/bluetooth-2-15.png
--------------------------------------------------------------------------------
/resources/drawables/bluetooth-2-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrencroton/SnapshotWatch/HEAD/resources/drawables/bluetooth-2-16.png
--------------------------------------------------------------------------------
/resources/drawables/launcher_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrencroton/SnapshotWatch/HEAD/resources/drawables/launcher_icon.png
--------------------------------------------------------------------------------
/resources/drawables/speech-bubble-12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrencroton/SnapshotWatch/HEAD/resources/drawables/speech-bubble-12.png
--------------------------------------------------------------------------------
/resources/drawables/speech-bubble-13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrencroton/SnapshotWatch/HEAD/resources/drawables/speech-bubble-13.png
--------------------------------------------------------------------------------
/resources/drawables/speech-bubble-14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrencroton/SnapshotWatch/HEAD/resources/drawables/speech-bubble-14.png
--------------------------------------------------------------------------------
/resources/drawables/speech-bubble-15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrencroton/SnapshotWatch/HEAD/resources/drawables/speech-bubble-15.png
--------------------------------------------------------------------------------
/resources/drawables/speech-bubble-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrencroton/SnapshotWatch/HEAD/resources/drawables/speech-bubble-16.png
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | SnapshotWatch
4 |
5 |
6 |
7 |
8 |
9 | connectiq.builder
10 |
11 |
12 |
13 |
14 |
15 | connectiq.projectNature
16 |
17 |
18 |
--------------------------------------------------------------------------------
/resources/drawables/drawables.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/source/SnapshotWatchApp.mc:
--------------------------------------------------------------------------------
1 | using Toybox.Application as App;
2 |
3 | class SnapshotWatchApp extends App.AppBase {
4 |
5 | function initialize() {
6 | AppBase.initialize();
7 | }
8 |
9 | // onStart() is called on application start up
10 | function onStart(state) {
11 | }
12 |
13 | // onStop() is called when your application is exiting
14 | function onStop(state) {
15 | }
16 |
17 | // Return the initial view of your application here
18 | function getInitialView() {
19 | return [ new SnapshotWatchView() ];
20 | }
21 |
22 | }
--------------------------------------------------------------------------------
/manifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Snapshot Watch
2 | A clean, simple, and elegant analogue watch face for the Forerunner 735XT that plots a heart rate graph of your last 4 hours in the background.
3 |
4 | In addition, most of your daily data is shown in an unobtrusive way: day and date, current/minimum/maximum heart rate, steps and step goal, sunrise/sunset, and icons for notification count/bluetooth/alarms/do not disturb.
5 |
6 | The heart rate graph and information can be turned off in the settings, and a second digital time (with or without offset) turned on.
7 |
8 | Snapshot Watch can be downloaded to your device here: https://apps.garmin.com/en-US/apps/20b5e4c9-382c-429d-91fa-199869c4777b.
9 |
10 | A special thanks to haraldh/SunCalc, from whom i borrowed code to calculate sunrise and sunset times: https://github.com/haraldh/SunCalc.
11 |
--------------------------------------------------------------------------------
/source/SunCalc.mc:
--------------------------------------------------------------------------------
1 | using Toybox.Math as Math;
2 | using Toybox.Time as Time;
3 |
4 | enum {
5 | NIGHT_END,
6 | NAUTICAL_DAWN,
7 | DAWN,
8 | BLUE_HOUR_AM,
9 | SUNRISE,
10 | SUNRISE_END,
11 | GOLDEN_HOUR_AM,
12 | NOON,
13 | GOLDEN_HOUR_PM,
14 | SUNSET_START,
15 | SUNSET,
16 | BLUE_HOUR_PM,
17 | DUSK,
18 | NAUTICAL_DUSK,
19 | NIGHT,
20 | NUM_RESULTS
21 | }
22 |
23 | class SunCalc {
24 |
25 | hidden const PI = Math.PI,
26 | RAD = Math.PI / 180.0,
27 | PI2 = Math.PI * 2.0,
28 | DAYS = Time.Gregorian.SECONDS_PER_DAY,
29 | J1970 = 2440588,
30 | J2000 = 2451545,
31 | J0 = 0.0009;
32 |
33 | hidden const TIMES = [
34 | -18 * RAD,
35 | -12 * RAD,
36 | -6 * RAD,
37 | -4 * RAD,
38 | -0.833 * RAD,
39 | -0.3 * RAD,
40 | 6 * RAD,
41 | null,
42 | 6 * RAD,
43 | -0.3 * RAD,
44 | -0.833 * RAD,
45 | -4 * RAD,
46 | -6 * RAD,
47 | -12 * RAD,
48 | -18 * RAD
49 | ];
50 |
51 | var lastD, lastLng;
52 | var n, ds, M, sinM, C, L, sin2L, dec, Jnoon;
53 |
54 | function initialize() {
55 | lastD = null;
56 | lastLng = null;
57 | }
58 |
59 | function fromJulian(j) {
60 | return new Time.Moment((j + 0.5 - J1970) * DAYS);
61 | }
62 |
63 | function round(a) {
64 | if (a > 0) {
65 | return (a + 0.5).toNumber().toFloat();
66 | } else {
67 | return (a - 0.5).toNumber().toFloat();
68 | }
69 | }
70 |
71 | // lat and lng in radians
72 | function calculate(moment, lat, lng, what) {
73 | var d = moment.value().toDouble() / DAYS - 0.5 + J1970 - J2000;
74 | if (lastD != d || lastLng != lng) {
75 | n = round(d - J0 + lng / PI2);
76 | // ds = J0 - lng / PI2 + n;
77 | ds = J0 - lng / PI2 + n - 1.1574e-5 * 68;
78 | M = 6.240059967 + 0.0172019715 * ds;
79 | sinM = Math.sin(M);
80 | C = (1.9148 * sinM + 0.02 * Math.sin(2 * M) + 0.0003 * Math.sin(3 * M)) * RAD;
81 | L = M + C + 1.796593063 + PI;
82 | sin2L = Math.sin(2 * L);
83 | dec = Math.asin( 0.397783703 * Math.sin(L) );
84 | Jnoon = J2000 + ds + 0.0053 * sinM - 0.0069 * sin2L;
85 | lastD = d;
86 | lastLng = lng;
87 | }
88 |
89 | if (what == NOON) {
90 | return fromJulian(Jnoon);
91 | }
92 |
93 | var x = (Math.sin(TIMES[what]) - Math.sin(lat) * Math.sin(dec)) / (Math.cos(lat) * Math.cos(dec));
94 |
95 | if (x > 1.0 || x < -1.0) {
96 | return null;
97 | }
98 |
99 | var ds = J0 + (Math.acos(x) - lng) / PI2 + n - 1.1574e-5 * 68;
100 |
101 | var Jset = J2000 + ds + 0.0053 * sinM - 0.0069 * sin2L;
102 | if (what > NOON) {
103 | return fromJulian(Jset);
104 | }
105 |
106 | var Jrise = Jnoon - (Jset - Jnoon);
107 |
108 | return fromJulian(Jrise);
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/bin/SnapshotWatch-settings.json:
--------------------------------------------------------------------------------
1 | {"settings":[{"key":"code","valueType":"string","defaultValue":"get code at app store page","configTitle":"CodeLabel","configPrompt":null,"configHelpUrl":null,"configError":null,"configType":"alphaNumeric","configReadonly":false,"configRequired":false,"configOptions":null,"configMin":null,"configMax":null,"configMaxLength":null},{"key":"showHeartRate","valueType":"boolean","defaultValue":true,"configTitle":"ShowHeartRateLabel","configPrompt":null,"configHelpUrl":null,"configError":null,"configType":"boolean","configReadonly":false,"configRequired":false,"configOptions":null,"configMin":null,"configMax":null,"configMaxLength":null},{"key":"graphLength","valueType":"number","defaultValue":240,"configTitle":"GraphLengthLabel","configPrompt":null,"configHelpUrl":null,"configError":null,"configType":"numeric","configReadonly":false,"configRequired":false,"configOptions":null,"configMin":null,"configMax":null,"configMaxLength":null},{"key":"graphColour","valueType":"number","defaultValue":0,"configTitle":"GraphColourLabel","configPrompt":null,"configHelpUrl":null,"configError":null,"configType":"list","configReadonly":false,"configRequired":true,"configOptions":[{"display":"DK_GRAY","value":0},{"display":"RED","value":1},{"display":"DK_RED","value":2},{"display":"ORANGE","value":3},{"display":"YELLOW","value":4},{"display":"GREEN","value":5},{"display":"DK_GREEN","value":6},{"display":"BLUE","value":7},{"display":"DK_BLUE","value":8},{"display":"PURPLE","value":9},{"display":"PINK","value":10}],"configMin":null,"configMax":null,"configMaxLength":null},{"key":"useZonesColour","valueType":"boolean","defaultValue":true,"configTitle":"UseZonesColourLabel","configPrompt":null,"configHelpUrl":null,"configError":null,"configType":"boolean","configReadonly":false,"configRequired":false,"configOptions":null,"configMin":null,"configMax":null,"configMaxLength":null},{"key":"showMoveBar","valueType":"boolean","defaultValue":false,"configTitle":"ShowMoveBarLabel","configPrompt":null,"configHelpUrl":null,"configError":null,"configType":"boolean","configReadonly":false,"configRequired":false,"configOptions":null,"configMin":null,"configMax":null,"configMaxLength":null},{"key":"showSteps","valueType":"boolean","defaultValue":false,"configTitle":"ShowStepsLabel","configPrompt":null,"configHelpUrl":null,"configError":null,"configType":"boolean","configReadonly":false,"configRequired":false,"configOptions":null,"configMin":null,"configMax":null,"configMaxLength":null},{"key":"showRiseSet","valueType":"boolean","defaultValue":false,"configTitle":"ShowRiseSetLabel","configPrompt":null,"configHelpUrl":null,"configError":null,"configType":"boolean","configReadonly":false,"configRequired":false,"configOptions":null,"configMin":null,"configMax":null,"configMaxLength":null},{"key":"showSecondTime","valueType":"boolean","defaultValue":false,"configTitle":"ShowSecondTimeLabel","configPrompt":null,"configHelpUrl":null,"configError":null,"configType":"boolean","configReadonly":false,"configRequired":false,"configOptions":null,"configMin":null,"configMax":null,"configMaxLength":null},{"key":"secondTimeOffset","valueType":"number","defaultValue":0,"configTitle":"SecondTimeOffsetLabel","configPrompt":null,"configHelpUrl":null,"configError":null,"configType":"numeric","configReadonly":false,"configRequired":false,"configOptions":null,"configMin":null,"configMax":null,"configMaxLength":null}],"languages":{"valyrian":{"UseZonesColourLabel":"Additionally colour code graph by profile heart rate zones","ShowRiseSetLabel":"[PRO] Show sunrise/sunset","DK_GRAY":"Dark Gray","DK_GREEN":"Dark Green","BLUE":"Blue","SecondTimeOffsetLabel":"[PRO] Second (digital) time hour offset (integer, +-24)","PURPLE":"Purple","GREEN":"Green","ShowMoveBarLabel":"Colour graph red when move bar alert is on (or orange if red set above)","DK_RED":"Dark Red","DK_BLUE":"Dark Blue","AppName":"SnapshotWatch","RED":"Red","PINK":"Pink","CodeLabel":"Activation code for PRO features","ShowHeartRateLabel":"Show heart rate, graph, and min/max values","GraphLengthLabel":"Number of past minutes to show in heart rate graph (minimum 15, maximum 240)","GraphColourLabel":"Heart rate graph colour","ShowSecondTimeLabel":"[PRO] Show second (digital) time","YELLOW":"Yellow","ORANGE":"Orange","ShowStepsLabel":"[PRO] Show steps/step goal"}}}
--------------------------------------------------------------------------------
/resources/resources.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | get code at app store page
5 | true
6 | 240
7 | 0
8 | true
9 | false
10 | false
11 | false
12 | false
13 | 0
14 |
15 |
16 |
17 | Activation code for PRO features
18 | Show heart rate, graph, and min/max values
19 | Number of past minutes to show in heart rate graph (minimum 15, maximum 240)
20 | Heart rate graph colour
21 | Dark Gray
22 | Red
23 | Dark Red
24 | Orange
25 | Yellow
26 | Green
27 | Dark Green
28 | Blue
29 | Dark Blue
30 | Purple
31 | Pink
32 | Additionally colour code graph by profile heart rate zones
33 | Colour graph red when move bar alert is on (or orange if red set above)
34 | [PRO] Show steps/step goal
35 | [PRO] Show sunrise/sunset
36 | [PRO] Show second (digital) time
37 | [PRO] Second (digital) time hour offset (integer, +-24)
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | @Strings.DK_GRAY
53 | @Strings.RED
54 | @Strings.DK_RED
55 | @Strings.ORANGE
56 | @Strings.YELLOW
57 | @Strings.GREEN
58 | @Strings.DK_GREEN
59 | @Strings.BLUE
60 | @Strings.DK_BLUE
61 | @Strings.PURPLE
62 | @Strings.PINK
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/source/SnapshotWatchView.mc:
--------------------------------------------------------------------------------
1 | using Toybox.Graphics as Gfx;
2 | using Toybox.System as Sys;
3 | using Toybox.Lang as Lang;
4 | using Toybox.Math as Math;
5 | using Toybox.Time as Time;
6 | using Toybox.Time.Gregorian as Calendar;
7 | using Toybox.WatchUi as Ui;
8 | using Toybox.Application as App;
9 | using Toybox.ActivityMonitor as ActMon;
10 | using Toybox.SensorHistory as Sensor;
11 | using Toybox.Activity as Activity;
12 | using Toybox.UserProfile as User;
13 |
14 | enum
15 | {
16 | LAT,
17 | LON
18 | }
19 |
20 |
21 | class SnapshotWatchView extends Ui.WatchFace {
22 |
23 | var usePreferences = true;
24 | var showHeartRate = true;
25 | var showSteps = false;
26 | var showRiseSet = false;
27 | var showSecondTime = false;
28 | var secondTimeOffset = 0;
29 |
30 | var graphLength = 240;
31 | var arrayColours = new [11];
32 | var graphColour = 0;
33 | var useZonesColour = true;
34 | var heartRateZones;
35 | var showMoveBar = false;
36 |
37 | var background_color = Gfx.COLOR_BLACK;
38 | // var background_color = Gfx.COLOR_DK_GRAY;
39 |
40 | var showSeconds = true;
41 | var width_screen, height_screen;
42 | var hashMarksArray = new [60];
43 |
44 | var heartNow;
45 | var heartMin = 1000;
46 | var heartMax = 0;
47 |
48 | var proFeatures;
49 |
50 |
51 | //! Load your resources here
52 | function onLayout(dc) {
53 |
54 | //get screen dimensions
55 | width_screen = dc.getWidth();
56 | height_screen = dc.getHeight();
57 |
58 | //colours and zones
59 | arrayColours = [Gfx.COLOR_DK_GRAY, Gfx.COLOR_RED, Gfx.COLOR_DK_RED, Gfx.COLOR_ORANGE, Gfx.COLOR_YELLOW, Gfx.COLOR_GREEN, Gfx.COLOR_DK_GREEN, Gfx.COLOR_BLUE, Gfx.COLOR_DK_BLUE, Gfx.COLOR_PURPLE, Gfx.COLOR_PINK];
60 | heartRateZones = User.getHeartRateZones(User.getCurrentSport());
61 | // heartRateZones = [98, 127, 146, 166, 185, 195];
62 |
63 | //get hash marks position
64 | for(var i = 0; i < 60; i+=1)
65 | {
66 | hashMarksArray[i] = new [2];
67 | hashMarksArray[i][0] = (i / 60.0) * Math.PI * 2;
68 |
69 | if(i != 0 && i != 15 && i != 30 && i != 45)
70 | { hashMarksArray[i][1] = -85; }
71 | else
72 | { hashMarksArray[i][1] = -67; }
73 | }
74 |
75 | setLayout(Rez.Layouts.WatchFace(dc));
76 | }
77 |
78 |
79 | //! Restore the state of the app and prepare the view to be shown
80 | function onShow() {
81 | }
82 |
83 | //! Update the view
84 | function onUpdate(dc) {
85 |
86 | var code = "0";
87 |
88 | if (usePreferences)
89 | {
90 | code = Application.getApp().getProperty("code");
91 | showHeartRate = Application.getApp().getProperty("showHeartRate");
92 | graphLength = Application.getApp().getProperty("graphLength");
93 | graphColour = Application.getApp().getProperty("graphColour");
94 | useZonesColour = Application.getApp().getProperty("useZonesColour");
95 | showMoveBar = Application.getApp().getProperty("showMoveBar");
96 | showSteps = Application.getApp().getProperty("showSteps");
97 | showRiseSet = Application.getApp().getProperty("showRiseSet");
98 | showSecondTime = Application.getApp().getProperty("showSecondTime");
99 | secondTimeOffset = Application.getApp().getProperty("secondTimeOffset");
100 | }
101 |
102 | authenticate(code);
103 |
104 | if (!proFeatures)
105 | {
106 | showSteps = false;
107 | showRiseSet = false;
108 | showSecondTime = false;
109 | }
110 |
111 | if (showSecondTime)
112 | {
113 | if (secondTimeOffset != null && secondTimeOffset <= 24 && secondTimeOffset >= -24)
114 | {
115 | secondTimeOffset = secondTimeOffset.toNumber();
116 | }
117 | else
118 | {
119 | showSecondTime = false;
120 | secondTimeOffset = 0;
121 | }
122 | }
123 |
124 | // Clear screen
125 | dc.setColor(background_color, Gfx.COLOR_WHITE);
126 | dc.fillRectangle(0,0, width_screen, height_screen);
127 |
128 | heartNow = 0;
129 |
130 | // Plot heart rate graph
131 | plotHRgraph(dc);
132 |
133 | // Draw hash marks
134 | drawHashMarks(dc);
135 |
136 | // Draw analogue clock hands
137 | drawHands(dc, Sys.getClockTime().hour, Sys.getClockTime().min, Sys.getClockTime().sec);
138 |
139 | // Set text colour for the remaining information
140 | dc.setColor(Gfx.COLOR_WHITE, Gfx.COLOR_TRANSPARENT);
141 |
142 | // Show cur/min/max HR values (recorded when plotting graph, above)
143 | if (showHeartRate)
144 | {
145 | if (heartNow == 0)
146 | { dc.drawText(width_screen/2, height_screen/2 + 20, Gfx.FONT_SMALL, "-- bpm", Graphics.TEXT_JUSTIFY_CENTER|Graphics.TEXT_JUSTIFY_VCENTER); }
147 | else
148 | { dc.drawText(width_screen/2, height_screen/2 + 20, Gfx.FONT_SMALL, Lang.format("$1$ bpm", [heartNow]), Graphics.TEXT_JUSTIFY_CENTER|Graphics.TEXT_JUSTIFY_VCENTER); }
149 |
150 | var heartMinMaxString;
151 | if (heartMin == 0 || heartMax == 0)
152 | { heartMinMaxString = "-- / -- bpm"; }
153 | else
154 | { heartMinMaxString = Lang.format("$1$ / $2$ bpm", [heartMin, heartMax]); }
155 |
156 | dc.drawText(width_screen/2, height_screen - 19, Gfx.FONT_SMALL, heartMinMaxString, Graphics.TEXT_JUSTIFY_CENTER);
157 | }
158 |
159 | // Show date
160 | drawDate(dc);
161 |
162 | // Show second (digital) time
163 | drawDigitalTime(dc, Sys.getClockTime());
164 |
165 | // Show bluetooth icon
166 | if (Sys.getDeviceSettings().phoneConnected)
167 | { dc.drawBitmap(39, 6, Ui.loadResource(Rez.Drawables.BluetoothIcon)); }
168 |
169 | // Show alarm icon
170 | if (Sys.getDeviceSettings().alarmCount > 0)
171 | { dc.drawBitmap(25, 23, Ui.loadResource(Rez.Drawables.AlarmIcon)); }
172 |
173 | // Show do not disturb icon
174 | if (Sys.getDeviceSettings().doNotDisturb)
175 | { dc.drawBitmap(10, 49, Ui.loadResource(Rez.Drawables.MuteIcon)); }
176 |
177 | // Show notification count icon
178 | if (Sys.getDeviceSettings().notificationCount > 0)
179 | {
180 | var offset = 0;
181 | if (Sys.getDeviceSettings().notificationCount >= 10) { offset = 6; }
182 |
183 | dc.drawText(width_screen/2+16+offset, 7, Gfx.FONT_SMALL, Sys.getDeviceSettings().notificationCount, Graphics.TEXT_JUSTIFY_RIGHT|Graphics.TEXT_JUSTIFY_VCENTER);
184 | dc.drawBitmap(width_screen/2+18+offset, 2, Ui.loadResource(Rez.Drawables.NotificationIcon));
185 | }
186 |
187 | // Show battery percent
188 | var battery = Sys.getSystemStats().battery;
189 | var offset = 0;
190 | if (battery == 100)
191 | { offset = 6; }
192 | dc.drawText(width_screen/2-33-offset, 7, Gfx.FONT_SMALL, Lang.format("$1$%", [battery.format("%2d")]), Graphics.TEXT_JUSTIFY_LEFT|Graphics.TEXT_JUSTIFY_VCENTER);
193 |
194 | if (showSteps)
195 | {
196 | // Show steps
197 | dc.drawText(width_screen-4, height_screen/2 - 14, Gfx.FONT_SMALL, ActMon.getInfo().steps, Graphics.TEXT_JUSTIFY_RIGHT|Graphics.TEXT_JUSTIFY_VCENTER);
198 | dc.drawText(width_screen-4, height_screen/2 + 11, Gfx.FONT_SMALL, ActMon.getInfo().stepGoal, Graphics.TEXT_JUSTIFY_RIGHT|Graphics.TEXT_JUSTIFY_VCENTER);
199 | }
200 |
201 | if (showRiseSet)
202 | {
203 | // Show sunrise and sunset
204 | drawSunriseSunset(dc);
205 | }
206 |
207 | }
208 |
209 |
210 | //! The user has just looked at their watch. Timers and animations may be started here.
211 | function onExitSleep() {
212 | showSeconds = true;
213 | }
214 |
215 |
216 | //! Terminate any active timers and prepare for slow updates.
217 | function onEnterSleep() {
218 | showSeconds = false;
219 | requestUpdate();
220 | }
221 |
222 |
223 | function plotHRgraph(dc) {
224 |
225 | var curHeartMin = 0;
226 | var curHeartMax = 0;
227 |
228 | var sample = Sensor.getHeartRateHistory( {:order=>Sensor.ORDER_NEWEST_FIRST} );
229 | if (sample != null)
230 | {
231 | var heart = sample.next();
232 | if (heart.data != null)
233 | { heartNow = heart.data; }
234 |
235 | if (showHeartRate)
236 | {
237 | curHeartMin = heartMin;
238 | curHeartMax = heartMax;
239 | heartMin = 1000;
240 | heartMax = 0;
241 |
242 | var maxSecs = graphLength * 60;
243 | if (maxSecs < 900)
244 | { maxSecs = 900; } // 900sec = 15min
245 | else if (maxSecs > 14355)
246 | { maxSecs = 14355; } // 14400sec = 4hrs
247 |
248 | var totHeight = 44;
249 | var totWidth = 165;
250 | var binPixels = 1;
251 |
252 | var totBins = Math.ceil(totWidth / binPixels).toNumber();
253 | var binWidthSecs = Math.floor(binPixels * maxSecs / totWidth).toNumber();
254 |
255 | var heartSecs;
256 | var heartValue = 0;
257 | var secsBin = 0;
258 | var lastHeartSecs = sample.getNewestSampleTime().value();
259 | var heartBinMax;
260 | var heartBinMin;
261 |
262 | var finished = false;
263 |
264 | for (var i = 0; i < totBins; ++i) {
265 |
266 | heartBinMax = 0;
267 | heartBinMin = 0;
268 |
269 | if (!finished)
270 | {
271 | //deal with carryover values
272 | if (secsBin > 0 && heartValue != null)
273 | {
274 | heartBinMax = heartValue;
275 | heartBinMin = heartValue;
276 | }
277 |
278 | //deal with new values in this bin
279 | while (!finished && secsBin < binWidthSecs)
280 | {
281 | heart = sample.next();
282 | if (heart != null)
283 | {
284 | heartValue = heart.data;
285 | if (heartValue != null)
286 | {
287 | if (heartBinMax == 0)
288 | {
289 | heartBinMax = heartValue;
290 | heartBinMin = heartValue;
291 | }
292 | else
293 | {
294 | if (heartValue > heartBinMax)
295 | { heartBinMax = heartValue; }
296 |
297 | if (heartValue < heartBinMin)
298 | { heartBinMin = heartValue; }
299 | }
300 | }
301 |
302 | // keep track of time in this bin
303 | heartSecs = lastHeartSecs - heart.when.value();
304 | lastHeartSecs = heart.when.value();
305 | secsBin += heartSecs;
306 |
307 | // Sys.println(i + ": " + heartValue + " " + heartSecs + " " + secsBin + " " + heartBinMin + " " + heartBinMax);
308 | }
309 | else
310 | {
311 | finished = true;
312 | }
313 |
314 | } // while secsBin < binWidthSecs
315 |
316 | if (secsBin >= binWidthSecs)
317 | { secsBin -= binWidthSecs; }
318 |
319 | // only plot bar if we have valid values
320 | if (heartBinMax > 0 && heartBinMax >= heartBinMin)
321 | {
322 | if (curHeartMax > 0 && curHeartMax > curHeartMin)
323 | {
324 | var heartBinMid = (heartBinMax+heartBinMin)/2;
325 | var height = (heartBinMid-curHeartMin*0.9) / (curHeartMax-curHeartMin*0.9) * totHeight;
326 | var xVal = (width_screen-totWidth)/2 + totWidth - i*binPixels -2;
327 | var yVal = height_screen/2+28 + totHeight - height;
328 |
329 | if (showMoveBar && ActMon.getInfo().moveBarLevel > 0)
330 | {
331 | if (graphColour == 1)
332 | { dc.setColor(Gfx.COLOR_ORANGE, Gfx.COLOR_TRANSPARENT); }
333 | else
334 | { dc.setColor(Gfx.COLOR_RED, Gfx.COLOR_TRANSPARENT); }
335 | } else
336 | {
337 | dc.setColor(arrayColours[getHRColour(heartBinMid)], Gfx.COLOR_TRANSPARENT);
338 | }
339 |
340 | dc.fillRectangle(xVal, yVal, binPixels, height);
341 | }
342 |
343 | if (heartBinMin < heartMin)
344 | { heartMin = heartBinMin; }
345 | if (heartBinMax > heartMax)
346 | { heartMax = heartBinMax; }
347 |
348 | // Sys.println(i + ": " + binWidthSecs + " " + secsBin + " " + heartBinMin + " " + heartBinMax);
349 | }
350 |
351 | } // if !finished
352 |
353 | } // loop over all bins
354 |
355 | } // if sample != null
356 |
357 | }
358 | }
359 |
360 |
361 | function getHRColour(heartrate)
362 | {
363 | if (!useZonesColour || heartrate == null || heartrate < heartRateZones[1])
364 | { return graphColour; }
365 | // else if (heartrate >= heartRateZones[0] && heartrate < heartRateZones[1])
366 | // { return 0; }
367 | else if (heartrate >= heartRateZones[1] && heartrate < heartRateZones[2])
368 | { return 7; }
369 | else if (heartrate >= heartRateZones[2] && heartrate < heartRateZones[3])
370 | { return 5; }
371 | else if (heartrate >= heartRateZones[3] && heartrate < heartRateZones[4])
372 | { return 3; }
373 | else
374 | { return 2; }
375 | }
376 |
377 |
378 | //! Draw the watch hand
379 | function drawHand(dc, angle, whichHand, width, handColour)
380 | {
381 | dc.setColor(handColour, Gfx.COLOR_TRANSPARENT);
382 |
383 | var length, r1, r2, r3, r4, deflect1, deflect2;
384 |
385 | var centerX = width_screen/2;
386 | var centerY = height_screen/2;
387 |
388 | if (whichHand == 0) //hour hand
389 | {
390 | length = 0.6*centerX;
391 | r1 = 0.0*length;
392 | r2 = 0.39*length;
393 | r3 = 0.49*length;
394 | r4 = 1.1*length;
395 | deflect1 = 0.10*width;
396 | deflect2 = 0.08*width;
397 | }
398 | else //minute hand
399 | {
400 | length = 1.0*centerX;
401 | r1 = 0.0*length;
402 | r2 = 0.37*length;
403 | r3 = 0.47*length;
404 | r4 = 1.2*length;
405 | deflect1 = 0.10*width;
406 | deflect2 = 0.08*width;
407 | }
408 |
409 | var coords = [
410 | [centerX + r1 * Math.sin(angle) , centerY - r1 * Math.cos(angle)],
411 | [centerX + r2 * Math.sin(angle+deflect1) , centerY - r2 * Math.cos(angle+deflect1)],
412 | [centerX + r3 * Math.sin(angle+deflect2) , centerY - r3 * Math.cos(angle+deflect2)],
413 | [centerX + r4 * Math.sin(angle) , centerY - r4 * Math.cos(angle)],
414 | [centerX + r3 * Math.sin(angle-deflect2) , centerY - r3 * Math.cos(angle-deflect2)],
415 | [centerX + r2 * Math.sin(angle-deflect1) , centerY - r2 * Math.cos(angle-deflect1)],
416 | [centerX + r1 * Math.sin(angle) , centerY - r1 * Math.cos(angle)]
417 | ];
418 |
419 | dc.fillPolygon(coords);
420 |
421 | }
422 |
423 |
424 | function drawHands(dc, clock_hour, clock_min, clock_sec)
425 | {
426 | var hour, min, sec;
427 |
428 | // Draw the hour hand - convert to minutes then compute angle
429 | hour = ( ( ( clock_hour % 12 ) * 60 ) + clock_min ); // hour = 2*60.0;
430 | hour = hour / (12 * 60.0) * Math.PI * 2;
431 | drawHand(dc, hour, 0, 2.0, Gfx.COLOR_DK_BLUE);
432 | drawHand(dc, hour, 0, 1.6, Gfx.COLOR_LT_GRAY);
433 |
434 | // Draw the minute hand
435 | min = ( clock_min / 60.0); // min = 40/60.0;
436 | min = min * Math.PI * 2;
437 | drawHand(dc, min, 1, 1.2, Gfx.COLOR_DK_BLUE);
438 | drawHand(dc, min, 1, 1.0, Gfx.COLOR_LT_GRAY);
439 |
440 | // Draw the seconds hand (use hash graphic here)
441 | if(showSeconds)
442 | {
443 | sec = ( clock_sec / 60.0) * Math.PI * 2;
444 | drawHash(dc, sec, width_screen/2, 4, 25, Gfx.COLOR_DK_BLUE);
445 | drawHash(dc, sec, width_screen/2, 2, 25, Gfx.COLOR_LT_GRAY);
446 | }
447 |
448 | // Draw the inner circle
449 | dc.setColor(Gfx.COLOR_DK_GRAY, background_color);
450 | dc.fillCircle(width_screen/2, height_screen/2, 6);
451 | dc.setColor(background_color,background_color);
452 | dc.drawCircle(width_screen/2, height_screen/2, 6);
453 | dc.fillCircle(width_screen/2, height_screen/2, 2);
454 | }
455 |
456 |
457 | function drawHash(dc, angle, length, width, overheadLine, handColour)
458 | {
459 | dc.setColor(handColour, Gfx.COLOR_TRANSPARENT);
460 |
461 | var centerX = width_screen/2;
462 | var centerY = height_screen/2;
463 |
464 | var result = new [4];
465 | var cos = Math.cos(angle);
466 | var sin = Math.sin(angle);
467 |
468 | var coords = [
469 | [-(width/2), 0 + overheadLine],
470 | [-(width/2), -length],
471 | [width/2, -length],
472 | [width/2, 0 + overheadLine]
473 | ];
474 |
475 | for (var i = 0; i < 4; i += 1)
476 | {
477 | var x = (coords[i][0] * cos) - (coords[i][1] * sin);
478 | var y = (coords[i][0] * sin) + (coords[i][1] * cos);
479 | result[i] = [ centerX + x, centerY + y];
480 | }
481 |
482 | dc.fillPolygon(result);
483 |
484 | }
485 |
486 |
487 | //! Draw the hash mark symbols
488 | function drawHashMarks(dc)
489 | {
490 | drawHash(dc, hashMarksArray[5][0], 110, 3, hashMarksArray[5][1], Gfx.COLOR_WHITE);
491 | drawHash(dc, hashMarksArray[10][0], 110, 3, hashMarksArray[10][1], Gfx.COLOR_WHITE);
492 | drawHash(dc, hashMarksArray[20][0], 110, 3, hashMarksArray[20][1], Gfx.COLOR_WHITE);
493 | drawHash(dc, hashMarksArray[25][0], 110, 3, hashMarksArray[25][1], Gfx.COLOR_WHITE);
494 | drawHash(dc, hashMarksArray[35][0], 110, 3, hashMarksArray[35][1], Gfx.COLOR_WHITE);
495 | drawHash(dc, hashMarksArray[40][0], 110, 3, hashMarksArray[40][1], Gfx.COLOR_WHITE);
496 | drawHash(dc, hashMarksArray[50][0], 110, 3, hashMarksArray[50][1], Gfx.COLOR_WHITE);
497 | drawHash(dc, hashMarksArray[55][0], 110, 3, hashMarksArray[55][1], Gfx.COLOR_WHITE);
498 |
499 | drawHash(dc, hashMarksArray[0][0], 110, 5, hashMarksArray[0][1], Gfx.COLOR_WHITE);
500 | drawHash(dc, hashMarksArray[15][0], 110, 5, hashMarksArray[15][1], Gfx.COLOR_WHITE);
501 | drawHash(dc, hashMarksArray[45][0], 110, 5, hashMarksArray[45][1], Gfx.COLOR_WHITE);
502 |
503 | if(!showHeartRate)
504 | { drawHash(dc, hashMarksArray[30][0], 110, 5, hashMarksArray[30][1], Gfx.COLOR_WHITE); }
505 | }
506 |
507 |
508 | function drawDate(dc)
509 | {
510 | var info = Calendar.info(Time.now(), Time.FORMAT_LONG);
511 | var dateStr = Lang.format("$1$ $2$ $3$", [info.day_of_week, info.month, info.day]);
512 |
513 | if (showSecondTime)
514 | { dc.drawText(width_screen/2, height_screen/2 - 60, Gfx.FONT_MEDIUM, dateStr, Gfx.TEXT_JUSTIFY_CENTER); }
515 | else
516 | { dc.drawText(width_screen/2, height_screen/2 - 55, Gfx.FONT_MEDIUM, dateStr, Gfx.TEXT_JUSTIFY_CENTER); }
517 | }
518 |
519 |
520 | function drawDigitalTime(dc, clockTime)
521 | {
522 | if (showSecondTime)
523 | {
524 | var offsetHour = clockTime.hour + secondTimeOffset;
525 |
526 | if (offsetHour > 23)
527 | { offsetHour -= 24; }
528 | else if (offsetHour < 0)
529 | { offsetHour += 24; }
530 |
531 | var ampm = "am";
532 | if (offsetHour >= 12)
533 | { ampm = "pm"; }
534 |
535 | var timeString = Lang.format("$1$:$2$$3$", [to12hourFormat(offsetHour), clockTime.min.format("%02d"), ampm]);
536 | dc.drawText(width_screen/2, height_screen/2 - 30, Gfx.FONT_SMALL, timeString, Gfx.TEXT_JUSTIFY_CENTER|Graphics.TEXT_JUSTIFY_VCENTER);
537 | }
538 | }
539 |
540 |
541 | function drawSunriseSunset(dc)
542 | {
543 | var sc = new SunCalc();
544 | var lat;
545 | var lon;
546 | var timeStringRise = " --:--";
547 | var timeStringSet = " --:--";
548 |
549 |
550 | var loc = Activity.getActivityInfo().currentLocation;
551 | if (loc == null)
552 | {
553 | lat = App.getApp().getProperty(LAT);
554 | lon = App.getApp().getProperty(LON);
555 | }
556 | else
557 | {
558 | lat = loc.toDegrees()[0] * Math.PI / 180.0;
559 | App.getApp().setProperty(LAT, lat);
560 | lon = loc.toDegrees()[1] * Math.PI / 180.0;
561 | App.getApp().setProperty(LON, lon);
562 | }
563 |
564 | // lat = -37.81400 * Math.PI / 180.0;
565 | // lon = 144.96332 * Math.PI / 180.0;
566 |
567 | if(lat != null && lon != null)
568 | {
569 | var ampm;
570 |
571 | var now = new Time.Moment(Time.now().value());
572 | var sunrise_moment = sc.calculate(now, lat.toDouble(), lon.toDouble(), SUNRISE);
573 | var sunset_moment = sc.calculate(now, lat.toDouble(), lon.toDouble(), SUNSET);
574 |
575 | var timeInfoSunrise = Calendar.info(sunrise_moment, Time.FORMAT_SHORT);
576 | var timeInfoSunset = Calendar.info(sunset_moment, Time.FORMAT_SHORT);
577 |
578 | ampm = "a";
579 | if (timeInfoSunrise.hour >= 12)
580 | { ampm = "p"; }
581 | timeStringRise = Lang.format("$1$:$2$$3$", [to12hourFormat(timeInfoSunrise.hour), timeInfoSunrise.min.format("%02d"), ampm]);
582 |
583 | ampm = "a";
584 | if (timeInfoSunset.hour >= 12)
585 | { ampm = "p"; }
586 | timeStringSet = Lang.format("$1$:$2$$3$", [to12hourFormat(timeInfoSunset.hour), timeInfoSunset.min.format("%02d"), ampm]);
587 | }
588 |
589 | dc.drawText(3, height_screen/2 - 14, Gfx.FONT_SMALL, timeStringRise, Gfx.TEXT_JUSTIFY_LEFT|Graphics.TEXT_JUSTIFY_VCENTER);
590 | dc.drawText(3, height_screen/2 + 11, Gfx.FONT_SMALL, timeStringSet, Gfx.TEXT_JUSTIFY_LEFT|Graphics.TEXT_JUSTIFY_VCENTER);
591 |
592 | }
593 |
594 |
595 | function to12hourFormat(hour)
596 | {
597 | var hour12 = hour % 12;
598 | if (hour12 == 0)
599 | { hour12 = 12; }
600 |
601 | return hour12;
602 | }
603 |
604 |
605 | function authenticate(code) {
606 |
607 | proFeatures = true;
608 |
609 | // set proFeatures=false
610 | // insert your authentication requirements here
611 | // then change proFeatures=true if "code" variable is valid
612 |
613 | }
614 |
615 | }
616 |
--------------------------------------------------------------------------------
/bin/SnapshotWatch.prg.debug.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
585 |
586 |
587 | Load your resources here
]]>
588 |
589 |
590 | Restore the state of the app and prepare the view to be shown
]]>
591 |
592 |
593 |
594 | Update the view
]]>
595 |
596 |
597 | The user has just looked at their watch. Timers and animations may be started here.
]]>
598 |
599 |
600 | Terminate any active timers and prepare for slow updates.
]]>
601 |
602 |
603 |
604 |
605 |
606 |
607 |
608 |
609 |
610 |
611 |
612 |
613 |
614 |
615 |
616 | Draw the watch hand
]]>
617 |
618 |
619 |
620 |
621 |
622 |
623 |
624 |
625 |
626 |
627 |
628 |
629 |
630 |
631 |
632 |
633 |
634 |
635 |
636 | Draw the hash mark symbols
]]>
637 |
638 |
639 |
640 |
641 |
642 |
643 |
644 |
645 |
646 |
647 |
648 |
649 |
650 |
651 |
652 |
653 |
654 |
655 |
656 |
657 |
658 |
659 |
660 |
661 |
662 |
663 |
664 |
665 |
666 |
667 |
668 |
669 |
670 |
671 |
672 |
673 |
674 |
675 | Draw the layout
param The context
]]>
676 |
677 |
678 |
679 |
680 |
681 |
682 |
683 |
684 |
685 |
686 |
687 |
688 |
689 |
690 |
691 |
692 |
--------------------------------------------------------------------------------