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:
Daniel Thompson 2021-01-03 14:54:34 +00:00
parent ed6b126e2e
commit 231f3b6fdd
6 changed files with 128 additions and 27 deletions

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

@ -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
View 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()

View File

@ -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

View File

@ -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'
)