summaryrefslogtreecommitdiff
path: root/wasp/apps
diff options
context:
space:
mode:
Diffstat (limited to 'wasp/apps')
-rw-r--r--wasp/apps/pager.py119
-rw-r--r--wasp/apps/testapp.py22
2 files changed, 140 insertions, 1 deletions
diff --git a/wasp/apps/pager.py b/wasp/apps/pager.py
new file mode 100644
index 0000000..7da8f5a
--- /dev/null
+++ b/wasp/apps/pager.py
@@ -0,0 +1,119 @@
+# SPDX-License-Identifier: LGPL-3.0-or-later
+# Copyright (C) 2020 Daniel Thompson
+
+import wasp
+import icons
+
+import io
+import sys
+
+
+class PagerApp():
+ """Show long text in a pager.
+
+ This is used to present text based information to the user. It is primarily
+ intended for notifications but is also used to provide debugging
+ information when applications crash.
+ """
+ NAME = 'Pager'
+ ICON = icons.app
+
+ def __init__(self, msg):
+ self._msg = msg
+ self._scroll = wasp.widgets.ScrollIndicator()
+
+ def foreground(self):
+ """Activate the application."""
+ self._page = 0
+ self._chunks = wasp.watch.drawable.wrap(self._msg, 240)
+ self._numpages = (len(self._chunks) - 2) // 9
+ wasp.system.request_event(wasp.EventMask.SWIPE_UPDOWN)
+ self._draw()
+
+ def background(self):
+ del self._chunks
+ del self._numpages
+
+ def swipe(self, event):
+ mute = wasp.watch.display.mute
+
+ if event[0] == wasp.EventType.UP:
+ if self._page >= self._numpages:
+ wasp.system.navigate(wasp.EventType.BACK)
+ return
+ self._page += 1
+ else:
+ if self._page <= 0:
+ wasp.watch.vibrator.pulse()
+ return
+ self._page -= 1
+ mute(True)
+ self._draw()
+ mute(False)
+
+ def _draw(self):
+ """Draw the display from scratch."""
+ draw = wasp.watch.drawable
+ draw.fill()
+
+ page = self._page
+ i = page * 9
+ j = i + 11
+ chunks = self._chunks[i:j]
+ for i in range(len(chunks)-1):
+ sub = self._msg[chunks[i]:chunks[i+1]].rstrip()
+ draw.string(sub, 0, 24*i)
+
+ scroll = self._scroll
+ scroll.up = page > 0
+ scroll.down = page < self._numpages
+ scroll.draw()
+
+class CrashApp():
+ """Crash handler application.
+
+ This application is launched automatically whenever another
+ application crashes. Our main job it to indicate as loudly as
+ possible that the system is no longer running correctly. This
+ app deliberately enables inverted video mode in order to deliver
+ that message as strongly as possible.
+ """
+ def __init__(self, exc):
+ """Capture the exception information.
+
+ This app does not actually display the exception information
+ but we need to capture the exception info before we leave
+ the except block.
+ """
+ msg = io.StringIO()
+ sys.print_exception(exc, msg)
+ self._msg = msg.getvalue()
+ msg.close()
+
+ def foreground(self):
+ """Indicate the system has crashed by drawing a couple of bomb icons.
+
+ If you owned an Atari ST back in the mid-eighties then I hope you
+ recognise this as a tribute a long forgotten home computer!
+ """
+ wasp.watch.display.invert(False)
+ draw = wasp.watch.drawable
+ draw.blit(icons.bomb, 0, 104)
+ draw.blit(icons.bomb, 32, 104)
+
+ wasp.system.request_event(wasp.EventMask.SWIPE_UPDOWN |
+ wasp.EventMask.SWIPE_LEFTRIGHT)
+
+ def background(self):
+ """Restore a normal display mode.
+
+ Conceal the display before the transition otherwise the inverted
+ bombs get noticed by the user.
+ """
+ wasp.watch.display.mute(True)
+ wasp.watch.display.invert(True)
+
+ def swipe(self, event):
+ """Show the exception message in a pager.
+ """
+ wasp.system.switch(PagerApp(self._msg))
diff --git a/wasp/apps/testapp.py b/wasp/apps/testapp.py
index 789454f..0df4ee7 100644
--- a/wasp/apps/testapp.py
+++ b/wasp/apps/testapp.py
@@ -12,7 +12,7 @@ class TestApp():
ICON = icons.app
def __init__(self):
- self.tests = ('Touch', 'String', 'Button', 'Crash', 'RLE')
+ self.tests = ('Touch', 'String', 'Wrap', 'Button', 'Crash', 'RLE')
self.test = self.tests[0]
self.scroll = wasp.widgets.ScrollIndicator()
@@ -56,6 +56,8 @@ class TestApp():
event[1], event[2]), 0, 108, width=240)
elif self.test == 'String':
self.benchmark_string()
+ elif self.test == 'Wrap':
+ self.benchmark_wrap()
elif self.test == 'RLE':
self.benchmark_rle()
@@ -88,6 +90,24 @@ class TestApp():
del t
draw.string('{}s'.format(elapsed / 1000000), 12, 24+192)
+ def benchmark_wrap(self):
+ draw = wasp.watch.drawable
+ draw.fill(0, 0, 30, 240, 240-30)
+ self.scroll.draw()
+ t = machine.Timer(id=1, period=8000000)
+ t.start()
+ draw = wasp.watch.drawable
+ s = 'This\nis a very long string that will need to be wrappedinmultipledifferentways!'
+ chunks = draw.wrap(s, 240)
+
+ for i in range(len(chunks)-1):
+ sub = s[chunks[i]:chunks[i+1]].rstrip()
+ draw.string(sub, 0, 48+24*i)
+ elapsed = t.time()
+ t.stop()
+ del t
+ draw.string('{}s'.format(elapsed / 1000000), 12, 24+192)
+
def draw(self):
"""Redraw the display from scratch."""
wasp.watch.display.mute(True)