apps: software: Add an apps to enable/disable other apps
Currently wasp-os enables a narrow set of applications because we don't want to consume RAM by importing the module and constructing the application. We can improve on this situation by providing a small (stateless) application that can be used to enable or diable applications. This allows all the ROMed applications to be enabled using the GUI without compromising on the ability to develop applications. In fact this application significantlly reduces the RAM consumed in the default case becasue the Self Test app does not need to maintain its state. Signed-off-by: Daniel Thompson <daniel@redfelineninja.org.uk>
This commit is contained in:
parent
ed6b126e2e
commit
231f3b6fdd
6 changed files with 128 additions and 27 deletions
BIN
res/app_icon.png
BIN
res/app_icon.png
Binary file not shown.
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 7.3 KiB |
BIN
res/software_icon.png
Normal file
BIN
res/software_icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.8 KiB |
|
@ -11,7 +11,7 @@ import wasp
|
|||
|
||||
import icons
|
||||
|
||||
class FlashlightApp(object):
|
||||
class TorchApp(object):
|
||||
"""Trivial flashlight application.
|
||||
|
||||
.. figure:: res/TorchApp.png
|
||||
|
|
80
wasp/apps/software.py
Normal file
80
wasp/apps/software.py
Normal file
|
@ -0,0 +1,80 @@
|
|||
# SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
# Copyright (C) 2020 Daniel Thompson
|
||||
"""Wizard to generate main.py."""
|
||||
|
||||
import wasp
|
||||
import icons
|
||||
|
||||
class SoftwareApp():
|
||||
"""Enable and disable applications."""
|
||||
NAME = 'Software'
|
||||
ICON = icons.software
|
||||
|
||||
def foreground(self):
|
||||
"""Activate the application."""
|
||||
self.db = (
|
||||
('alarm', wasp.widgets.Checkbox(0, 0, 'Alarm')),
|
||||
('calc', wasp.widgets.Checkbox(0, 40, 'Calculator')),
|
||||
('chrono', wasp.widgets.Checkbox(0, 80, 'Chrono')),
|
||||
('fibonacci_clock', wasp.widgets.Checkbox(0, 120, 'Fibonacci Clock')),
|
||||
('gameoflife', wasp.widgets.Checkbox(0, 160, 'Game Of Life')),
|
||||
('musicplayer', wasp.widgets.Checkbox(0, 0, 'Music Player')),
|
||||
('snake', wasp.widgets.Checkbox(0, 40, 'Snake Game')),
|
||||
('flashlight', wasp.widgets.Checkbox(0, 80, 'Torch')),
|
||||
('testapp', wasp.widgets.Checkbox(0, 120, 'Test')),
|
||||
)
|
||||
self.si = wasp.widgets.ScrollIndicator()
|
||||
self.page = 0
|
||||
|
||||
# Get the initial state for the checkboxes
|
||||
for _, checkbox in self.db:
|
||||
label = checkbox.label.replace(' ', '')
|
||||
for app in wasp.system.launcher_ring:
|
||||
if type(app).__name__.startswith(label):
|
||||
checkbox.state = True
|
||||
break
|
||||
|
||||
self._draw()
|
||||
wasp.system.request_event(wasp.EventMask.TOUCH |
|
||||
wasp.EventMask.SWIPE_UPDOWN)
|
||||
|
||||
def get_page(self):
|
||||
i = self.page * 5
|
||||
return self.db[i:i+5]
|
||||
|
||||
def swipe(self, event):
|
||||
"""Notify the application of a touchscreen swipe event."""
|
||||
page = self.page
|
||||
pages = 1
|
||||
if event[0] == wasp.EventType.UP:
|
||||
page = page - 1 if page > 0 else pages
|
||||
if event[0] == wasp.EventType.DOWN:
|
||||
page = page + 1 if page < pages else 0
|
||||
self.page = page
|
||||
|
||||
mute = wasp.watch.display.mute
|
||||
mute(True)
|
||||
self._draw()
|
||||
mute(False)
|
||||
|
||||
def touch(self, event):
|
||||
"""Notify the application of a touchscreen touch event."""
|
||||
for module, checkbox in self.get_page():
|
||||
if checkbox.touch(event):
|
||||
label = checkbox.label.replace(' ', '')
|
||||
if checkbox.state:
|
||||
exec('import apps.{}'.format(module))
|
||||
exec('wasp.system.register(apps.{}.{}App())'.format(module, label))
|
||||
else:
|
||||
for app in wasp.system.launcher_ring:
|
||||
if type(app).__name__.startswith(label):
|
||||
wasp.system.launcher_ring.remove(app)
|
||||
break
|
||||
break
|
||||
|
||||
def _draw(self):
|
||||
"""Draw the display from scratch."""
|
||||
wasp.watch.drawable.fill()
|
||||
self.si.draw()
|
||||
for _, checkbox in self.get_page():
|
||||
checkbox.draw()
|
|
@ -133,7 +133,7 @@ class TestApp():
|
|||
t = machine.Timer(id=1, period=8000000)
|
||||
t.start()
|
||||
for i in range(0, 128, 16):
|
||||
draw.blit(self.ICON, i+16, i+32)
|
||||
draw.blit(icons.software, i+16, i+32)
|
||||
elapsed = t.time()
|
||||
t.stop()
|
||||
del t
|
||||
|
|
|
@ -27,8 +27,52 @@ bomb = (
|
|||
b'\x0e'
|
||||
)
|
||||
|
||||
# 2-bit RLE, generated from res/app_icon.png, 460 bytes
|
||||
# 2-bit RLE, generated from res/app_icon.png, 224 bytes
|
||||
app = (
|
||||
b'\x02'
|
||||
b'`@'
|
||||
b'\x1e@\x81d<d<d;f?X\xec2\xf0/'
|
||||
b'\xf2-\xf4,\xc3.\xc3,\xc3.\xc3,\xc3.\xc3,'
|
||||
b'\xc3.\xc3,\xc3.\xc3,\xc3.\xc3,\xc3.\xc3,'
|
||||
b'\xc3.\xc3,\xc3.\xc3,\xc3.\xc3,\xc3.\xc3,'
|
||||
b'\xc3.\xc3,\xc3.\xc3,\xc3.\xc3,\xc3.\xc3,'
|
||||
b'\xc3.\xc3,\xc3.\xc3,\xc3.\xc3+\xc4.\xc3*'
|
||||
b'\xc5.\xc3*\xc5.\xc3*\xc5.\xc3*\xc5.\xc3*'
|
||||
b'\xc5.\xc3*\xc5.\xc3*\xc5.\xc3+\xc4.\xc3,'
|
||||
b'\xc3.\xc3,\xc3.\xc3,\xc3.\xc3,\xc3.\xc3,'
|
||||
b'\xc3.\xc3,\xc3.\xc3,\xc3.\xc3,\xc3.\xc3,'
|
||||
b'\xc3.\xc3,\xc3.\xc3,\xc3.\xc3,\xc3.\xc3,'
|
||||
b'\xc3.\xc3,\xc3.\xc3,\xc3.\xc3,\xc3.\xc3,'
|
||||
b'\xc3.\xc3,\xc3.\xc3,\xc3.\xc3,\xf4-\xf2/'
|
||||
b'\xf02\xec?Xf;d<d<d\x1e'
|
||||
)
|
||||
|
||||
# 2-bit RLE, generated from res/clock_icon.png, 288 bytes
|
||||
clock = (
|
||||
b'\x02'
|
||||
b'`@'
|
||||
b'?\xff\xff\xff\xff\xff\xff\x8e@\xacF\r\xc6!E\x0b'
|
||||
b'\xc8\x0cH\x0b\xca\x1dI\x07\xcc\nH\n\xcc\x1bK\x06'
|
||||
b'\xce\x08C\x02C\n\xc4\x05\xc4\x1aD\x03D\x06\xc2\x08'
|
||||
b'\xc4\rC\t\xc4\x07\xc3\x19D\x05D\x10\xc4\x0cC\t'
|
||||
b'\xc3\t\xc2\x19C\x07C\x11\xc3\x0cC\t\xc3\t\xc3\n'
|
||||
b'D\tD\x07D\x10\xc3\x0cC\t\xc3\t\xc3\nD\t'
|
||||
b'C\tC\x10\xc3\x0cC\t\xc3\t\xc3\nD\tC\t'
|
||||
b'C\x10\xc3\x0cC\t\xc4\x07\xc4\nD\tC\tC\x0f'
|
||||
b'\xc4\x0cC\n\xc4\x05\xc5\nD\tC\tC\x0e\xc4\r'
|
||||
b'C\n\xca\x01\xc3\x17C\tC\r\xc5\rC\x0b\xc9\x01'
|
||||
b'\xc3\x17C\tC\x0c\xc5\x0eC\r\xc5\x03\xc3\x17C\t'
|
||||
b'C\x0b\xc5\x0fC\x15\xc3\x17C\tC\n\xc5\x10C\x14'
|
||||
b'\xc4\x17C\tC\t\xc5\x11C\x14\xc3\x18D\x07D\x08'
|
||||
b'\xc4\x13C\x14\xc3\x19C\x07C\x08\xc4\x14C\x13\xc4\x0b'
|
||||
b'D\nC\x06D\x07\xc4\x15C\x0b\xc1\x05\xc5\x0cD\x0b'
|
||||
b'D\x03D\x07\xc3\x12M\x06\xca\rD\x0bK\x06\xcf\x07'
|
||||
b'M\x06\xc9\x0eD\x0cI\x07\xcf\x07M\x07\xc6\x10D\x0e'
|
||||
b'E\t\xcf?\xff\xff\xff\xff\xff\xff\xff\xffk'
|
||||
)
|
||||
|
||||
# 2-bit RLE, generated from res/software_icon.png, 460 bytes
|
||||
software = (
|
||||
b'\x02'
|
||||
b'`@'
|
||||
b'\x1e@\x81d<d<d;f?X\xec2\xf0/'
|
||||
|
@ -62,30 +106,6 @@ app = (
|
|||
b'\x81f;d<d<d\x1e'
|
||||
)
|
||||
|
||||
# 2-bit RLE, generated from res/clock_icon.png, 288 bytes
|
||||
clock = (
|
||||
b'\x02'
|
||||
b'`@'
|
||||
b'?\xff\xff\xff\xff\xff\xff\x8e@\xacF\r\xc6!E\x0b'
|
||||
b'\xc8\x0cH\x0b\xca\x1dI\x07\xcc\nH\n\xcc\x1bK\x06'
|
||||
b'\xce\x08C\x02C\n\xc4\x05\xc4\x1aD\x03D\x06\xc2\x08'
|
||||
b'\xc4\rC\t\xc4\x07\xc3\x19D\x05D\x10\xc4\x0cC\t'
|
||||
b'\xc3\t\xc2\x19C\x07C\x11\xc3\x0cC\t\xc3\t\xc3\n'
|
||||
b'D\tD\x07D\x10\xc3\x0cC\t\xc3\t\xc3\nD\t'
|
||||
b'C\tC\x10\xc3\x0cC\t\xc3\t\xc3\nD\tC\t'
|
||||
b'C\x10\xc3\x0cC\t\xc4\x07\xc4\nD\tC\tC\x0f'
|
||||
b'\xc4\x0cC\n\xc4\x05\xc5\nD\tC\tC\x0e\xc4\r'
|
||||
b'C\n\xca\x01\xc3\x17C\tC\r\xc5\rC\x0b\xc9\x01'
|
||||
b'\xc3\x17C\tC\x0c\xc5\x0eC\r\xc5\x03\xc3\x17C\t'
|
||||
b'C\x0b\xc5\x0fC\x15\xc3\x17C\tC\n\xc5\x10C\x14'
|
||||
b'\xc4\x17C\tC\t\xc5\x11C\x14\xc3\x18D\x07D\x08'
|
||||
b'\xc4\x13C\x14\xc3\x19C\x07C\x08\xc4\x14C\x13\xc4\x0b'
|
||||
b'D\nC\x06D\x07\xc4\x15C\x0b\xc1\x05\xc5\x0cD\x0b'
|
||||
b'D\x03D\x07\xc3\x12M\x06\xca\rD\x0bK\x06\xcf\x07'
|
||||
b'M\x06\xc9\x0eD\x0cI\x07\xcf\x07M\x07\xc6\x10D\x0e'
|
||||
b'E\t\xcf?\xff\xff\xff\xff\xff\xff\xff\xffk'
|
||||
)
|
||||
|
||||
# 2-bit RLE, generated from res/settings_icon.png, 468 bytes
|
||||
settings = (
|
||||
b'\x02'
|
||||
|
@ -345,3 +365,4 @@ checkbox = (
|
|||
b'F\x85O\xc6G\x83P\xc6H\x81Q\xc6Z\xc6Z\xc6'
|
||||
b'Z\xc7X\xe4\x01\xde\x03\xdc\x02'
|
||||
)
|
||||
|
||||
|
|
Loading…
Reference in a new issue