Skip to content

Commit 57842a7

Browse files
committed
Timer: Remember last timer setting
Remember last duration used in Timer app. Stop with long press while paused. Reset to zero with long press while stopped.
1 parent 6b5235c commit 57842a7

File tree

5 files changed

+182
-51
lines changed

5 files changed

+182
-51
lines changed

src/components/timer/Timer.cpp

+49-8
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,67 @@
33
using namespace Pinetime::Controllers;
44

55
Timer::Timer(void* const timerData, TimerCallbackFunction_t timerCallbackFunction) {
6+
pausedAtTimer = std::chrono::seconds(0);
7+
lastTimer = std::chrono::seconds(0);
8+
state = Stopped;
69
timer = xTimerCreate("Timer", 1, pdFALSE, timerData, timerCallbackFunction);
710
}
811

9-
void Timer::StartTimer(std::chrono::milliseconds duration) {
10-
xTimerChangePeriod(timer, pdMS_TO_TICKS(duration.count()), 0);
11-
xTimerStart(timer, 0);
12-
}
13-
1412
std::chrono::milliseconds Timer::GetTimeRemaining() {
1513
if (IsRunning()) {
16-
TickType_t remainingTime = xTimerGetExpiryTime(timer) - xTaskGetTickCount();
14+
const TickType_t remainingTime = xTimerGetExpiryTime(timer) - xTaskGetTickCount();
1715
return std::chrono::milliseconds(remainingTime * 1000 / configTICK_RATE_HZ);
1816
}
17+
18+
if (state == Paused)
19+
return pausedAtTimer;
20+
1921
return std::chrono::milliseconds(0);
2022
}
2123

22-
void Timer::StopTimer() {
23-
xTimerStop(timer, 0);
24+
std::chrono::milliseconds Timer::GetLast() {
25+
return lastTimer;
26+
}
27+
28+
void Timer::ResetLast() {
29+
lastTimer = std::chrono::seconds(0);
30+
}
31+
32+
Timer::TimerState Timer::GetState() {
33+
return state;
34+
}
35+
36+
void Timer::Start(const std::chrono::milliseconds duration) {
37+
TimerStart(duration);
38+
lastTimer = duration;
39+
state = Running;
40+
}
41+
42+
void Timer::Stop() {
43+
TimerStop();
44+
state = Stopped;
45+
}
46+
47+
void Timer::Pause() {
48+
pausedAtTimer = GetTimeRemaining();
49+
TimerStop();
50+
state = Paused;
51+
}
52+
53+
void Timer::Resume() {
54+
TimerStart(pausedAtTimer);
55+
state = Running;
2456
}
2557

2658
bool Timer::IsRunning() {
2759
return (xTimerIsTimerActive(timer) == pdTRUE);
60+
};
61+
62+
void Timer::TimerStart(const std::chrono::milliseconds duration) {
63+
xTimerChangePeriod(timer, pdMS_TO_TICKS(duration.count()), 0);
64+
xTimerStart(timer, 0);
65+
}
66+
67+
void Timer::TimerStop() {
68+
xTimerStop(timer, 0);
2869
}

src/components/timer/Timer.h

+21-3
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,34 @@ namespace Pinetime {
1111
public:
1212
Timer(void* timerData, TimerCallbackFunction_t timerCallbackFunction);
1313

14-
void StartTimer(std::chrono::milliseconds duration);
14+
void Start(const std::chrono::milliseconds duration);
1515

16-
void StopTimer();
16+
void Stop();
17+
18+
void Pause();
19+
20+
void Resume();
1721

1822
std::chrono::milliseconds GetTimeRemaining();
1923

20-
bool IsRunning();
24+
std::chrono::milliseconds GetLast();
25+
void ResetLast();
26+
27+
typedef enum TimerState { Running, Stopped, Paused } TimerState;
28+
29+
TimerState GetState();
2130

2231
private:
2332
TimerHandle_t timer;
33+
34+
std::chrono::milliseconds lastTimer;
35+
std::chrono::milliseconds pausedAtTimer;
36+
37+
TimerState state;
38+
39+
bool IsRunning();
40+
void TimerStart(const std::chrono::milliseconds duration);
41+
void TimerStop();
2442
};
2543
}
2644
}

src/displayapp/DisplayApp.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -268,11 +268,12 @@ void DisplayApp::Refresh() {
268268
}
269269
if (currentApp == Apps::Timer) {
270270
lv_disp_trig_activity(nullptr);
271-
auto* timer = static_cast<Screens::Timer*>(currentScreen.get());
272-
timer->Reset();
273271
} else {
274272
LoadNewScreen(Apps::Timer, DisplayApp::FullRefreshDirections::Up);
275273
}
274+
Screens::Timer* timer;
275+
timer = static_cast<Screens::Timer*>(currentScreen.get());
276+
timer->Stop();
276277
motorController.RunForDuration(35);
277278
break;
278279
case Messages::AlarmTriggered:

src/displayapp/screens/Timer.cpp

+100-36
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,20 @@ Timer::Timer(Controllers::Timer& timerController) : timer {timerController} {
6060
lv_obj_set_size(btnPlayPause, LV_HOR_RES, 50);
6161

6262
txtPlayPause = lv_label_create(lv_scr_act(), nullptr);
63-
lv_obj_align(txtPlayPause, btnPlayPause, LV_ALIGN_CENTER, 0, 0);
6463

65-
if (timer.IsRunning()) {
66-
SetTimerRunning();
67-
} else {
68-
SetTimerStopped();
64+
switch (timer.GetState()) {
65+
case Controllers::Timer::TimerState::Stopped:
66+
SetCounters(timer.GetLast());
67+
SetInterfaceStopped();
68+
break;
69+
case Controllers::Timer::TimerState::Running:
70+
SetCounters(timer.GetTimeRemaining());
71+
SetInterfaceRunning();
72+
break;
73+
case Controllers::Timer::TimerState::Paused:
74+
SetCounters(timer.GetTimeRemaining());
75+
SetInterfacePaused();
76+
break;
6977
}
7078

7179
taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this);
@@ -76,22 +84,52 @@ Timer::~Timer() {
7684
lv_obj_clean(lv_scr_act());
7785
}
7886

87+
void Timer::SetButtonText(const char* text) {
88+
lv_label_set_text_static(txtPlayPause, text);
89+
lv_obj_align(txtPlayPause, btnPlayPause, LV_ALIGN_CENTER, 0, 0);
90+
}
91+
7992
void Timer::ButtonPressed() {
8093
pressTime = xTaskGetTickCount();
8194
buttonPressing = true;
8295
}
8396

8497
void Timer::MaskReset() {
8598
buttonPressing = false;
99+
86100
// A click event is processed before a release event,
87101
// so the release event would override the "Pause" text without this check
88-
if (!timer.IsRunning()) {
89-
lv_label_set_text_static(txtPlayPause, "Start");
102+
switch (timer.GetState()) {
103+
case Controllers::Timer::TimerState::Stopped:
104+
SetButtonText("Start");
105+
break;
106+
case Controllers::Timer::TimerState::Running:
107+
SetButtonText("Pause");
108+
break;
109+
case Controllers::Timer::TimerState::Paused:
110+
SetButtonText("Resume");
111+
break;
90112
}
113+
91114
maskPosition = 0;
92115
UpdateMask();
93116
}
94117

118+
void Timer::HandleHold() {
119+
if (timer.GetState() == Controllers::Timer::TimerState::Stopped) {
120+
SetButtonText("Reset");
121+
} else {
122+
SetButtonText("Stop");
123+
}
124+
125+
maskPosition += 15;
126+
if (maskPosition > 240) {
127+
HandleLongPress();
128+
} else {
129+
UpdateMask();
130+
}
131+
}
132+
95133
void Timer::UpdateMask() {
96134
lv_draw_mask_line_param_t maskLine;
97135

@@ -102,52 +140,78 @@ void Timer::UpdateMask() {
102140
lv_objmask_update_mask(btnObjectMask, btnMask, &maskLine);
103141
}
104142

143+
void Timer::HandleLongPress() {
144+
if (timer.GetState() == Controllers::Timer::TimerState::Stopped) {
145+
Reset();
146+
} else {
147+
Stop();
148+
}
149+
150+
MaskReset();
151+
}
152+
105153
void Timer::Refresh() {
106-
if (timer.IsRunning()) {
154+
if (timer.GetState() == Controllers::Timer::TimerState::Running) {
107155
auto secondsRemaining = std::chrono::duration_cast<std::chrono::seconds>(timer.GetTimeRemaining());
108-
minuteCounter.SetValue(secondsRemaining.count() / 60);
109-
secondCounter.SetValue(secondsRemaining.count() % 60);
110-
} else if (buttonPressing && xTaskGetTickCount() > pressTime + pdMS_TO_TICKS(150)) {
111-
lv_label_set_text_static(txtPlayPause, "Reset");
112-
maskPosition += 15;
113-
if (maskPosition > 240) {
114-
MaskReset();
115-
Reset();
116-
} else {
117-
UpdateMask();
156+
SetCounters(secondsRemaining);
157+
} else {
158+
if (buttonPressing && xTaskGetTickCount() > pressTime + pdMS_TO_TICKS(150)) {
159+
HandleHold();
118160
}
119161
}
120162
}
121163

122-
void Timer::SetTimerRunning() {
164+
void Timer::SetInterfaceRunning() {
165+
minuteCounter.HideControls();
166+
secondCounter.HideControls();
167+
SetButtonText("Pause");
168+
}
169+
170+
void Timer::SetInterfacePaused() {
123171
minuteCounter.HideControls();
124172
secondCounter.HideControls();
125-
lv_label_set_text_static(txtPlayPause, "Pause");
173+
SetButtonText("Resume");
126174
}
127175

128-
void Timer::SetTimerStopped() {
176+
void Timer::SetInterfaceStopped() {
129177
minuteCounter.ShowControls();
130178
secondCounter.ShowControls();
131-
lv_label_set_text_static(txtPlayPause, "Start");
179+
SetButtonText("Start");
180+
}
181+
182+
void Timer::SetCounters(const std::chrono::milliseconds& duration) {
183+
SetCounters(std::chrono::duration_cast<std::chrono::seconds>(duration));
184+
}
185+
186+
void Timer::SetCounters(const std::chrono::seconds& duration) {
187+
minuteCounter.SetValue(duration.count() / 60);
188+
secondCounter.SetValue(duration.count() % 60);
132189
}
133190

134191
void Timer::ToggleRunning() {
135-
if (timer.IsRunning()) {
136-
auto secondsRemaining = std::chrono::duration_cast<std::chrono::seconds>(timer.GetTimeRemaining());
137-
minuteCounter.SetValue(secondsRemaining.count() / 60);
138-
secondCounter.SetValue(secondsRemaining.count() % 60);
139-
timer.StopTimer();
140-
SetTimerStopped();
141-
} else if (secondCounter.GetValue() + minuteCounter.GetValue() > 0) {
142-
auto timerDuration = std::chrono::minutes(minuteCounter.GetValue()) + std::chrono::seconds(secondCounter.GetValue());
143-
timer.StartTimer(timerDuration);
144-
Refresh();
145-
SetTimerRunning();
192+
if (timer.GetState() == Controllers::Timer::TimerState::Stopped) {
193+
if (secondCounter.GetValue() + minuteCounter.GetValue() > 0) {
194+
auto timerDuration = std::chrono::minutes(minuteCounter.GetValue()) + std::chrono::seconds(secondCounter.GetValue());
195+
timer.Start(timerDuration);
196+
Refresh();
197+
SetInterfaceRunning();
198+
}
199+
} else if (timer.GetState() == Controllers::Timer::TimerState::Running) {
200+
timer.Pause();
201+
SetInterfacePaused();
202+
} else { // Paused
203+
timer.Resume();
204+
SetInterfaceRunning();
146205
}
147206
}
148207

149208
void Timer::Reset() {
150-
minuteCounter.SetValue(0);
151-
secondCounter.SetValue(0);
152-
SetTimerStopped();
209+
timer.ResetLast();
210+
Stop();
211+
}
212+
213+
void Timer::Stop() {
214+
timer.Stop();
215+
SetCounters(timer.GetLast());
216+
SetInterfaceStopped();
153217
}

src/displayapp/screens/Timer.h

+9-2
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,22 @@ namespace Pinetime::Applications {
1717
Timer(Controllers::Timer& timerController);
1818
~Timer() override;
1919
void Refresh() override;
20+
void Stop();
2021
void Reset();
2122
void ToggleRunning();
2223
void ButtonPressed();
2324
void MaskReset();
2425

2526
private:
26-
void SetTimerRunning();
27-
void SetTimerStopped();
27+
void SetInterfaceRunning();
28+
void SetInterfacePaused();
29+
void SetInterfaceStopped();
30+
void HandleHold();
2831
void UpdateMask();
32+
void HandleLongPress();
33+
void SetCounters(const std::chrono::milliseconds& duration);
34+
void SetCounters(const std::chrono::seconds& duration);
35+
void SetButtonText(const char* text);
2936
Pinetime::Controllers::Timer& timer;
3037

3138
lv_obj_t* btnPlayPause;

0 commit comments

Comments
 (0)