From b0bab534ff6308a9d87a61ea88e5fd72c252b75e Mon Sep 17 00:00:00 2001 From: Daniel Thompson Date: Sun, 20 Jun 2021 17:24:10 +0100 Subject: [PATCH] apps: SportsApp: Initial sports app implementation This app is functional... although it lacking in almost every costmetic way, from the icon to the main screen. Signed-off-by: Daniel Thompson --- README.rst | 4 ++ docs/apps.rst | 2 + res/SportsApp.png | Bin 0 -> 6049 bytes wasp/apps/software.py | 1 + wasp/apps/sports.py | 91 ++++++++++++++++++++++++++++++++ wasp/boards/manifest_240x240.py | 1 + 6 files changed, 99 insertions(+) create mode 100644 res/SportsApp.png create mode 100644 wasp/apps/sports.py diff --git a/README.rst b/README.rst index 81b4439..ae40bdf 100644 --- a/README.rst +++ b/README.rst @@ -153,6 +153,10 @@ simulator: :alt: Heart rate application running on the wasp-os simulator :width: 179 +.. image:: res/SportsApp.png + :alt: Sports applications, a combined stopwatch and step counter + :width: 179 + .. image:: res/StopclockApp.png :alt: Stop watch application running on the wasp-os simulator :width: 179 diff --git a/docs/apps.rst b/docs/apps.rst index 17bf149..a931b6c 100644 --- a/docs/apps.rst +++ b/docs/apps.rst @@ -53,6 +53,8 @@ Applications .. automodule:: apps.musicplayer +.. automodule:: apps.sports + .. automodule:: apps.testapp .. automodule:: apps.timer diff --git a/res/SportsApp.png b/res/SportsApp.png new file mode 100644 index 0000000000000000000000000000000000000000..54e9f96f0f8d82a8c7cbd765c17184c3f3515387 GIT binary patch literal 6049 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 literal 0 HcmV?d00001 diff --git a/wasp/apps/software.py b/wasp/apps/software.py index cac4595..9e764bc 100644 --- a/wasp/apps/software.py +++ b/wasp/apps/software.py @@ -44,6 +44,7 @@ class SoftwareApp(): db.append(('musicplayer', factory('Music Player'))) db.append(('play2048', factory('Play 2048'))) db.append(('snake', factory('Snake Game'))) + db.append(('sports', factory('Sports'))) db.append(('flashlight', factory('Torch'))) db.append(('testapp', factory('Test'))) db.append(('timer', factory('Timer'))) diff --git a/wasp/apps/sports.py b/wasp/apps/sports.py new file mode 100644 index 0000000..e966855 --- /dev/null +++ b/wasp/apps/sports.py @@ -0,0 +1,91 @@ +# SPDX-License-Identifier: LGPL-3.0-or-later +# Copyright (C) 2020 Daniel Thompson + +"""Sports timer +~~~~~~~~~~~~~~~ + +A combined stopwatch and step counter. + +.. figure:: res/SportsApp.png + :width: 179 +""" +import wasp +import icons +import fonts + +class SportsApp(): + """Sports timer application.""" + NAME = 'Sports' + ICON = icons.app + + def __init__(self): + self._timer = wasp.widgets.Stopwatch(120-36) + self._reset() + + def foreground(self): + """Activate the application.""" + wasp.system.bar.clock = True + self._draw() + wasp.system.request_tick(97) + wasp.system.request_event(wasp.EventMask.TOUCH | wasp.EventMask.BUTTON) + + def background(self): + if not self._timer.started: + self._timer.reset() + + def sleep(self): + return True + + def wake(self): + self._update() + + def press(self, button, state): + if not state: + return + + steps = wasp.watch.accel.steps + + if self._timer.started: + self._timer.stop() + else: + self._timer.start() + self._last_steps = steps + + def touch(self, event): + if not self._timer.started: + self._reset() + self._update() + + def tick(self, ticks): + self._update() + + def _reset(self): + self._timer.reset() + self._steps = 0 + self._last_steps = 0 + + def _draw(self): + """Draw the display from scratch.""" + draw = wasp.watch.drawable + draw.fill() + + wasp.system.bar.draw() + self._timer.draw() + + def _update(self): + wasp.system.bar.update() + self._timer.update() + + if self._timer.started: + steps = wasp.watch.accel.steps + redraw = bool(steps - self._last_steps) + self._steps += steps - self._last_steps + self._last_steps = steps + else: + redraw = True + + if redraw: + draw = wasp.watch.drawable + draw.set_font(fonts.sans36) + draw.set_color(draw.lighten(wasp.system.theme('spot1'), wasp.system.theme('contrast'))) + draw.string(str(self._steps), 0, 170, 228, True) diff --git a/wasp/boards/manifest_240x240.py b/wasp/boards/manifest_240x240.py index b8e7fc9..f0eb474 100644 --- a/wasp/boards/manifest_240x240.py +++ b/wasp/boards/manifest_240x240.py @@ -20,6 +20,7 @@ manifest = ( 'apps/play2048.py', 'apps/settings.py', 'apps/software.py', + 'apps/sports.py', 'apps/steps.py', 'apps/stopwatch.py', 'apps/snake.py',