summaryrefslogtreecommitdiff
path: root/wasp
diff options
context:
space:
mode:
authorAdam Blair <adampblair@protonmail.com>2021-06-23 21:31:42 (GMT)
committerDaniel Thompson <daniel@redfelineninja.org.uk>2021-07-25 07:56:14 (GMT)
commite09b951017761236f75137498cc3495a12a91f49 (patch)
tree0174dd4e83f8b58166b7dc75692b74ef2de11469 /wasp
parent0831f79a105329f0dd7cd252b9fcd327415e4f82 (diff)
Advanced alarm app
Features: * Multiple alarms (up to 4) * Day of the week support * One time alarms * Snooze Changes to wasp-os for app support: * Added + and - to the 28pt and 36pt fonts * Checkboxes now require a click on the body of the checkbox if there is no label * Added a Toggle Button class that extends Button and stores a state like checkbox Signed-off-by: Adam Blair <adampblair@protonmail.com>
Diffstat (limited to 'wasp')
-rw-r--r--wasp/apps/alarm.py337
-rw-r--r--wasp/fonts/sans28.py130
-rw-r--r--wasp/fonts/sans36.py203
-rw-r--r--wasp/widgets.py37
4 files changed, 502 insertions, 205 deletions
diff --git a/wasp/apps/alarm.py b/wasp/apps/alarm.py
index c3c1847..4d87b0c 100644
--- a/wasp/apps/alarm.py
+++ b/wasp/apps/alarm.py
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: LGPL-3.0-or-later
# Copyright (C) 2020 Daniel Thompson
# Copyright (C) 2020 Joris Warmbier
+# Copyright (C) 2021 Adam Blair
"""Alarm Application
~~~~~~~~~~~~~~~~~~~~
@@ -12,11 +13,12 @@ An application to set a vibration alarm. All settings can be accessed from the W
Screenshot of the Alarm Application
"""
-
import wasp
import fonts
import time
import widgets
+import array
+from micropython import const
# 2-bit RLE, generated from res/alarm_icon.png, 390 bytes
icon = (
@@ -49,7 +51,29 @@ icon = (
b'\x11\x83\x17'
)
-class AlarmApp():
+# Enabled masks
+_MONDAY = const(0x01)
+_TUESDAY = const(0x02)
+_WEDNESDAY = const(0x04)
+_THURSDAY = const(0x08)
+_FRIDAY = const(0x10)
+_SATURDAY = const(0x20)
+_SUNDAY = const(0x40)
+_WEEKDAYS = const(0x1F)
+_WEEKENDS = const(0x60)
+_EVERY_DAY = const(0x7F)
+_IS_ACTIVE = const(0x80)
+
+# Alarm data indices
+_HOUR_IDX = const(0)
+_MIN_IDX = const(1)
+_ENABLED_IDX = const(2)
+
+# Pages
+_HOME_PAGE = const(-1)
+_RINGING_PAGE = const(-2)
+
+class AlarmApp:
"""Allows the user to set a vibration alarm.
"""
NAME = 'Alarm'
@@ -57,83 +81,296 @@ class AlarmApp():
def __init__(self):
"""Initialize the application."""
- self.active = widgets.Checkbox(104, 200)
- self.hours = widgets.Spinner(50, 60, 0, 23, 2)
- self.minutes = widgets.Spinner(130, 60, 0, 59, 2)
- self.hours.value = 7
- self.ringing = False
+ self.page = _HOME_PAGE
+ self.alarms = (bytearray(3), bytearray(3), bytearray(3), bytearray(3))
+ self.pending_alarms = array.array('d', [0.0, 0.0, 0.0, 0.0])
+
+ # Set a nice default
+ self.num_alarms = 1
+ for alarm in self.alarms:
+ alarm[_HOUR_IDX] = 8
+ alarm[_MIN_IDX] = 0
+ alarm[_ENABLED_IDX] = 0
+ self.alarms[0][_ENABLED_IDX] = _WEEKDAYS
+
def foreground(self):
"""Activate the application."""
+
+ self.del_alarm_btn = widgets.Button(170, 204, 70, 35, 'DEL')
+ self.hours_wid = widgets.Spinner(50, 30, 0, 23, 2)
+ self.min_wid = widgets.Spinner(130, 30, 0, 59, 2)
+ self.day_btns = (widgets.ToggleButton(10, 145, 40, 35, 'Mo'),
+ widgets.ToggleButton(55, 145, 40, 35, 'Tu'),
+ widgets.ToggleButton(100, 145, 40, 35, 'We'),
+ widgets.ToggleButton(145, 145, 40, 35, 'Th'),
+ widgets.ToggleButton(190, 145, 40, 35, 'Fr'),
+ widgets.ToggleButton(10, 185, 40, 35, 'Sa'),
+ widgets.ToggleButton(55, 185, 40, 35, 'Su'))
+ self.alarm_checks = (widgets.Checkbox(200, 57), widgets.Checkbox(200, 102),
+ widgets.Checkbox(200, 147), widgets.Checkbox(200, 192))
+
+ self._deactivate_pending_alarms()
self._draw()
- wasp.system.request_event(wasp.EventMask.TOUCH)
+
+ wasp.system.request_event(wasp.EventMask.TOUCH | wasp.EventMask.SWIPE_LEFTRIGHT | wasp.EventMask.BUTTON)
wasp.system.request_tick(1000)
- if self.active.state:
- wasp.system.cancel_alarm(self.current_alarm, self._alert)
def background(self):
"""De-activate the application."""
- if self.active.state:
- self._set_current_alarm()
- wasp.system.set_alarm(self.current_alarm, self._alert)
- if self.ringing:
- self.ringing = False
+ if self.page > _HOME_PAGE:
+ self._save_alarm()
+
+ self.page = _HOME_PAGE
+
+ del self.del_alarm_btn
+ del self.hours_wid
+ del self.min_wid
+ del self.alarm_checks
+ del self.day_btns
+
+ self._set_pending_alarms()
def tick(self, ticks):
"""Notify the application that its periodic tick is due."""
- if self.ringing:
+ if self.page == _RINGING_PAGE:
wasp.watch.vibrator.pulse(duty=50, ms=500)
wasp.system.keep_awake()
else:
wasp.system.bar.update()
+ def press(self, button, state):
+ """"Notify the application of a button press event."""
+ if self.page == _RINGING_PAGE:
+ self._snooze()
+ wasp.system.navigate(wasp.EventType.HOME)
+
+ def swipe(self, event):
+ """"Notify the application of a swipe event."""
+ if self.page == _RINGING_PAGE:
+ self._silence_alarm()
+ elif self.page > _HOME_PAGE:
+ self._save_alarm()
+ self._draw()
+ else:
+ wasp.system.navigate(event[0])
+
def touch(self, event):
"""Notify the application of a touchscreen touch event."""
- if self.ringing:
- mute = wasp.watch.display.mute
- self.ringing = False
- mute(True)
- self._draw()
- mute(False)
- elif self.hours.touch(event) or self.minutes.touch(event) or \
- self.active.touch(event):
- pass
+ if self.page == _RINGING_PAGE:
+ self._silence_alarm()
+ elif self.page > _HOME_PAGE:
+ if self.hours_wid.touch(event) or self.min_wid.touch(event):
+ return
+ for day_btn in self.day_btns:
+ if day_btn.touch(event):
+ return
+ if self.del_alarm_btn.touch(event):
+ self._remove_alarm(self.page)
+ elif self.page == _HOME_PAGE:
+ for index, checkbox in enumerate(self.alarm_checks):
+ if checkbox.touch(event):
+ if checkbox.state:
+ self.alarms[index][_ENABLED_IDX] |= _IS_ACTIVE
+ else:
+ self.alarms[index][_ENABLED_IDX] &= ~_IS_ACTIVE
+ self._draw(index)
+ return
+ for index, alarm in enumerate(self.alarms):
+ # Open edit page for clicked alarms
+ if index < self.num_alarms and event[1] < 190 \
+ and 60 + (index * 45) < event[2] < 60 + ((index + 1) * 45):
+ self.page = index
+ self._draw()
+ return
+ # Add new alarm if plus clicked
+ elif index == self.num_alarms and 60 + (index * 45) < event[2]:
+ self.num_alarms += 1
+ self._draw(index)
+ return
+
+ def _remove_alarm(self, alarm_index):
+ # Shift alarm indices
+ for index in range(alarm_index, 3):
+ self.alarms[index][_HOUR_IDX] = self.alarms[index + 1][_HOUR_IDX]
+ self.alarms[index][_MIN_IDX] = self.alarms[index + 1][_MIN_IDX]
+ self.alarms[index][_ENABLED_IDX] = self.alarms[index + 1][_ENABLED_IDX]
+ self.pending_alarms[index] = self.pending_alarms[index + 1]
+
+ # Set last alarm to default
+ self.alarms[3][_HOUR_IDX] = 8
+ self.alarms[3][_MIN_IDX] = 0
+ self.alarms[3][_ENABLED_IDX] = 0
+
+ self.page = _HOME_PAGE
+ self.num_alarms -= 1
+ self._draw()
- def _draw(self):
- """Draw the display from scratch."""
+ def _save_alarm(self):
+ alarm = self.alarms[self.page]
+ alarm[_HOUR_IDX] = self.hours_wid.value
+ alarm[_MIN_IDX] = self.min_wid.value
+ for day_idx, day_btn in enumerate(self.day_btns):
+ if day_btn.state:
+ alarm[_ENABLED_IDX] |= 1 << day_idx
+ else:
+ alarm[_ENABLED_IDX] &= ~(1 << day_idx)
+
+ self.page = _HOME_PAGE
+
+ def _draw(self, update_alarm_row=-1):
+ if self.page == _RINGING_PAGE:
+ self._draw_ringing_page()
+ elif self.page > _HOME_PAGE:
+ self._draw_edit_page()
+ else:
+ self._draw_home_page(update_alarm_row)
+
+ def _draw_ringing_page(self):
draw = wasp.watch.drawable
- if not self.ringing:
+
+ draw.set_color(wasp.system.theme('bright'))
+ draw.fill()
+ draw.set_font(fonts.sans24)
+ draw.string("Alarm", 0, 150, width=240)
+ draw.blit(icon, 73, 50)
+ draw.line(35, 1, 35, 239)
+ draw.string('Z', 10, 80)
+ draw.string('z', 10, 110)
+ draw.string('z', 10, 140)
+
+ def _draw_edit_page(self):
+ draw = wasp.watch.drawable
+ alarm = self.alarms[self.page]
+
+ draw.fill()
+ self._draw_system_bar()
+
+ self.hours_wid.value = alarm[_HOUR_IDX]
+ self.min_wid.value = alarm[_MIN_IDX]
+ draw.set_font(fonts.sans28)
+ draw.string(':', 110, 90-14, width=20)
+
+ self.del_alarm_btn.draw()
+ self.hours_wid.draw()
+ self.min_wid.draw()
+ for day_idx, day_btn in enumerate(self.day_btns):
+ day_btn.state = alarm[_ENABLED_IDX] & (1 << day_idx)
+ day_btn.draw()
+
+ def _draw_home_page(self, update_alarm_row=_HOME_PAGE):
+ draw = wasp.watch.drawable
+ if update_alarm_row == _HOME_PAGE:
+ draw.set_color(wasp.system.theme('bright'))
draw.fill()
+ self._draw_system_bar()
+ draw.line(0, 50, 240, 50, width=1, color=wasp.system.theme('bright'))
- sbar = wasp.system.bar
- sbar.clock = True
- sbar.draw()
+ for index in range(len(self.alarms)):
+ if index < self.num_alarms and (update_alarm_row == _HOME_PAGE or update_alarm_row == index):
+ self._draw_alarm_row(index)
+ elif index == self.num_alarms:
+ # Draw the add button
+ draw.set_color(wasp.system.theme('bright'))
+ draw.set_font(fonts.sans28)
+ draw.string('+', 100, 60 + (index * 45))
- draw.set_font(fonts.sans28)
- draw.string(':', 110, 120-14, width=20)
+ def _draw_alarm_row(self, index):
+ draw = wasp.watch.drawable
+ alarm = self.alarms[index]
- self.active.draw()
- self.hours.draw()
- self.minutes.draw()
+ self.alarm_checks[index].state = alarm[_ENABLED_IDX] & _IS_ACTIVE
+ self.alarm_checks[index].draw()
+
+ if self.alarm_checks[index].state:
+ draw.set_color(wasp.system.theme('bright'))
else:
- draw.fill()
- draw.set_font(fonts.sans24)
- draw.string("Alarm", 0, 150, width=240)
- draw.blit(icon, 73, 50)
+ draw.set_color(wasp.system.theme('mid'))
+
+ draw.set_font(fonts.sans28)
+ draw.string("{:02d}:{:02d}".format(alarm[_HOUR_IDX], alarm[_MIN_IDX]), 10, 60 + (index * 45), width=120)
+
+ draw.set_font(fonts.sans18)
+ draw.string(self._get_repeat_code(alarm[_ENABLED_IDX]), 130, 70 + (index * 45), width=60)
+
+ draw.line(0, 95 + (index * 45), 240, 95 + (index * 45), width=1, color=wasp.system.theme('bright'))
+
+ def _draw_system_bar(self):
+ sbar = wasp.system.bar
+ sbar.clock = True
+ sbar.draw()
def _alert(self):
- self.ringing = True
+ self.page = _RINGING_PAGE
wasp.system.wake()
wasp.system.switch(self)
- def _set_current_alarm(self):
+ def _snooze(self):
now = wasp.watch.rtc.get_localtime()
- yyyy = now[0]
- mm = now[1]
- dd = now[2]
- HH = self.hours.value
- MM = self.minutes.value
- if HH < now[3] or (HH == now[3] and MM <= now[4]):
- dd += 1
- self.current_alarm = (time.mktime((yyyy, mm, dd, HH, MM, 0, 0, 0, 0)))
+ alarm = (now[0], now[1], now[2], now[3], now[4] + 10, now[5], 0, 0, 0)
+ wasp.system.set_alarm(time.mktime(alarm), self._alert)
+
+ def _silence_alarm(self):
+ mute = wasp.watch.display.mute
+ mute(True)
+ self._draw()
+ mute(False)
+ wasp.system.navigate(wasp.EventType.HOME)
+
+ def _set_pending_alarms(self):
+ now = wasp.watch.rtc.get_localtime()
+ for index, alarm in enumerate(self.alarms):
+ if index < self.num_alarms and alarm[_ENABLED_IDX] & _IS_ACTIVE:
+ yyyy = now[0]
+ mm = now[1]
+ dd = now[2]
+ HH = alarm[_HOUR_IDX]
+ MM = alarm[_MIN_IDX]
+
+ # If next alarm is tomorrow increment the day
+ if HH < now[3] or (HH == now[3] and MM <= now[4]):
+ dd += 1
+
+ pending_time = time.mktime((yyyy, mm, dd, HH, MM, 0, 0, 0, 0))
+
+ # If this is not a one time alarm find the next day of the week that is enabled
+ if alarm[_ENABLED_IDX] & ~_IS_ACTIVE != 0:
+ for _i in range(7):
+ if (1 << time.localtime(pending_time)[6]) & alarm[_ENABLED_IDX] == 0:
+ dd += 1
+ pending_time = time.mktime((yyyy, mm, dd, HH, MM, 0, 0, 0, 0))
+ else:
+ break
+
+ self.pending_alarms[index] = pending_time
+ wasp.system.set_alarm(pending_time, self._alert)
+ else:
+ self.pending_alarms[index] = 0.0
+
+ def _deactivate_pending_alarms(self):
+ now = wasp.watch.rtc.get_localtime()
+ now = time.mktime((now[0], now[1], now[2], now[3], now[4], now[5], 0, 0, 0))
+ for index, alarm in enumerate(self.alarms):
+ pending_alarm = self.pending_alarms[index]
+ if not pending_alarm == 0.0:
+ wasp.system.cancel_alarm(pending_alarm, self._alert)
+ # If this is a one time alarm and in the past disable it
+ if alarm[_ENABLED_IDX] & ~_IS_ACTIVE == 0 and pending_alarm <= now:
+ alarm[_ENABLED_IDX] = 0
+
+ @staticmethod
+ def _get_repeat_code(days):
+ # Ignore the is_active bit
+ days = days & ~_IS_ACTIVE
+
+ if days == _WEEKDAYS:
+ return "wkds"
+ elif days == _WEEKENDS:
+ return "wkns"
+ elif days == _EVERY_DAY:
+ return "evry"
+ elif days == 0:
+ return "once"
+ else:
+ return "cust" \ No newline at end of file
diff --git a/wasp/fonts/sans28.py b/wasp/fonts/sans28.py
index 9a123f3..72915b8 100644
--- a/wasp/fonts/sans28.py
+++ b/wasp/fonts/sans28.py
@@ -1,6 +1,6 @@
# Code generated by font_to_py.py.
-# Font: DejaVuSans.ttf
-# Cmd: ./tools/micropython-font-to-py/font_to_py.py /usr/share/fonts/dejavu/DejaVuSans.ttf --xmap 28 -e 58 -s 48 -l 58 wasp/fonts/sans28.py
+# Font: DejaVuSans.ttf Char set: +-0123456789:
+# Cmd: tools/micropython-font-to-py/font_to_py.py /usr/share/fonts/dejavu/DejaVuSans.ttf --xmap 28 -e 58 -c 0123456789:+- wasp/fonts/sans28.py
version = '0.33'
def height():
@@ -10,7 +10,7 @@ def baseline():
return 27
def max_width():
- return 24
+ return 31
def hmap():
return True
@@ -22,7 +22,7 @@ def monospaced():
return False
def min_ch():
- return 48
+ return 43
def max_ch():
return 58
@@ -31,66 +31,78 @@ _font =\
b'\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00'\
-b'\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x18\x00\x00\xfe\x00\x03\xff\x80'\
-b'\x07\xff\xc0\x0f\x83\xe0\x0f\x01\xe0\x1e\x00\xf0\x1e\x00\xf0\x1e'\
-b'\x00\xf0\x3c\x00\x78\x3c\x00\x78\x3c\x00\x78\x3c\x00\x78\x3c\x00'\
+b'\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x1f\x00\x00\x00\x00\x00\x00\x00'\
+b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x80\x00\x00\x03'\
+b'\x80\x00\x00\x03\x80\x00\x00\x03\x80\x00\x00\x03\x80\x00\x00\x03'\
+b'\x80\x00\x00\x03\x80\x00\x00\x03\x80\x00\x00\x03\x80\x00\x00\x03'\
+b'\x80\x00\x0f\xff\xff\xe0\x0f\xff\xff\xe0\x0f\xff\xff\xe0\x00\x03'\
+b'\x80\x00\x00\x03\x80\x00\x00\x03\x80\x00\x00\x03\x80\x00\x00\x03'\
+b'\x80\x00\x00\x03\x80\x00\x00\x03\x80\x00\x00\x03\x80\x00\x00\x03'\
+b'\x80\x00\x00\x03\x80\x00\x0d\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
+b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
+b'\x00\x00\x00\x00\x00\x00\x3f\xf0\x3f\xf0\x3f\xf0\x00\x00\x00\x00'\
+b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00'\
+b'\x00\xfe\x00\x03\xff\x80\x07\xff\xc0\x0f\x83\xe0\x0f\x01\xe0\x1e'\
+b'\x00\xf0\x1e\x00\xf0\x1e\x00\xf0\x3c\x00\x78\x3c\x00\x78\x3c\x00'\
b'\x78\x3c\x00\x78\x3c\x00\x78\x3c\x00\x78\x3c\x00\x78\x3c\x00\x78'\
-b'\x3c\x00\x78\x1e\x00\xf0\x1e\x00\xf0\x1e\x00\xf0\x0f\x01\xe0\x0f'\
-b'\x83\xe0\x07\xff\xc0\x03\xff\x80\x00\xfe\x00\x18\x00\x00\xfe\x00'\
-b'\x07\xfe\x00\x07\xfe\x00\x07\x1e\x00\x00\x1e\x00\x00\x1e\x00\x00'\
+b'\x3c\x00\x78\x3c\x00\x78\x3c\x00\x78\x1e\x00\xf0\x1e\x00\xf0\x1e'\
+b'\x00\xf0\x0f\x01\xe0\x0f\x83\xe0\x07\xff\xc0\x03\xff\x80\x00\xfe'\
+b'\x00\x18\x00\x00\xfe\x00\x07\xfe\x00\x07\xfe\x00\x07\x1e\x00\x00'\
b'\x1e\x00\x00\x1e\x00\x00\x1e\x00\x00\x1e\x00\x00\x1e\x00\x00\x1e'\
b'\x00\x00\x1e\x00\x00\x1e\x00\x00\x1e\x00\x00\x1e\x00\x00\x1e\x00'\
b'\x00\x1e\x00\x00\x1e\x00\x00\x1e\x00\x00\x1e\x00\x00\x1e\x00\x00'\
-b'\x1e\x00\x00\x1e\x00\x07\xff\xf8\x07\xff\xf8\x07\xff\xf8\x18\x00'\
-b'\x01\xfc\x00\x0f\xff\x80\x1f\xff\xc0\x1f\x07\xe0\x18\x01\xe0\x10'\
-b'\x01\xf0\x00\x00\xf0\x00\x00\xf0\x00\x00\xf0\x00\x00\xf0\x00\x01'\
-b'\xf0\x00\x01\xe0\x00\x03\xe0\x00\x07\xc0\x00\x0f\x80\x00\x1f\x00'\
-b'\x00\x3e\x00\x00\x7e\x00\x00\xfc\x00\x01\xf8\x00\x03\xf0\x00\x07'\
-b'\xe0\x00\x0f\xc0\x00\x1f\x80\x00\x1f\xff\xf0\x1f\xff\xf0\x1f\xff'\
-b'\xf0\x18\x00\x03\xfe\x00\x0f\xff\x80\x0f\xff\xc0\x0c\x03\xe0\x00'\
-b'\x01\xf0\x00\x00\xf0\x00\x00\xf0\x00\x00\xf0\x00\x00\xf0\x00\x01'\
-b'\xe0\x00\x03\xc0\x00\xff\x80\x00\xfe\x00\x00\xff\xc0\x00\x03\xe0'\
-b'\x00\x00\xf0\x00\x00\xf8\x00\x00\x78\x00\x00\x78\x00\x00\x78\x00'\
-b'\x00\x78\x00\x00\xf8\x00\x01\xf0\x18\x03\xf0\x1f\xff\xe0\x1f\xff'\
-b'\x80\x07\xfe\x00\x18\x00\x00\x07\xc0\x00\x0f\xc0\x00\x0f\xc0\x00'\
-b'\x1f\xc0\x00\x3b\xc0\x00\x3b\xc0\x00\x73\xc0\x00\xf3\xc0\x00\xe3'\
-b'\xc0\x01\xc3\xc0\x03\xc3\xc0\x03\x83\xc0\x07\x03\xc0\x07\x03\xc0'\
-b'\x0e\x03\xc0\x1e\x03\xc0\x1c\x03\xc0\x38\x03\xc0\x3f\xff\xfc\x3f'\
-b'\xff\xfc\x3f\xff\xfc\x00\x03\xc0\x00\x03\xc0\x00\x03\xc0\x00\x03'\
-b'\xc0\x00\x03\xc0\x00\x03\xc0\x18\x00\x0f\xff\xc0\x0f\xff\xc0\x0f'\
-b'\xff\xc0\x0f\x00\x00\x0f\x00\x00\x0f\x00\x00\x0f\x00\x00\x0f\x00'\
-b'\x00\x0f\x00\x00\x0f\xfc\x00\x0f\xff\x00\x0f\xff\xc0\x0c\x0f\xc0'\
-b'\x00\x03\xe0\x00\x01\xe0\x00\x00\xf0\x00\x00\xf0\x00\x00\xf0\x00'\
-b'\x00\xf0\x00\x00\xf0\x00\x00\xf0\x00\x01\xe0\x00\x03\xe0\x18\x07'\
-b'\xc0\x1f\xff\xc0\x1f\xff\x00\x07\xfc\x00\x18\x00\x00\x3f\x80\x00'\
-b'\xff\xe0\x03\xff\xe0\x07\xe0\x60\x0f\x80\x00\x0f\x00\x00\x1f\x00'\
-b'\x00\x1e\x00\x00\x1e\x00\x00\x3c\x00\x00\x3c\x7f\x00\x3c\xff\xc0'\
-b'\x3d\xff\xe0\x3f\x83\xf0\x3e\x00\xf0\x3e\x00\xf8\x3c\x00\x78\x3c'\
-b'\x00\x78\x3c\x00\x78\x1c\x00\x78\x1c\x00\x78\x1e\x00\xf8\x0e\x00'\
-b'\xf0\x0f\x83\xf0\x07\xff\xe0\x03\xff\x80\x00\xfe\x00\x18\x00\x1f'\
-b'\xff\xf0\x1f\xff\xf0\x1f\xff\xf0\x00\x01\xe0\x00\x01\xe0\x00\x03'\
-b'\xe0\x00\x03\xc0\x00\x03\xc0\x00\x07\xc0\x00\x07\x80\x00\x07\x80'\
-b'\x00\x0f\x80\x00\x0f\x00\x00\x0f\x00\x00\x1f\x00\x00\x1e\x00\x00'\
-b'\x1e\x00\x00\x3e\x00\x00\x3c\x00\x00\x3c\x00\x00\x78\x00\x00\x78'\
-b'\x00\x00\x78\x00\x00\xf0\x00\x00\xf0\x00\x00\xf0\x00\x01\xe0\x00'\
-b'\x18\x00\x00\xfe\x00\x03\xff\x80\x0f\xff\xe0\x0f\x83\xe0\x1f\x01'\
-b'\xf0\x1e\x00\xf0\x1e\x00\xf0\x1e\x00\xf0\x1e\x00\xf0\x0f\x01\xe0'\
-b'\x07\x83\xc0\x03\xff\x80\x00\xfe\x00\x07\xff\xc0\x0f\x83\xe0\x1e'\
-b'\x00\xf0\x3e\x00\xf0\x3c\x00\x78\x3c\x00\x78\x3c\x00\x78\x3c\x00'\
-b'\x78\x3e\x00\xf8\x1e\x00\xf0\x1f\x83\xf0\x0f\xff\xe0\x07\xff\xc0'\
-b'\x00\xfe\x00\x18\x00\x00\xfe\x00\x03\xff\x00\x0f\xff\xc0\x1f\x83'\
-b'\xe0\x1e\x00\xe0\x3e\x00\xf0\x3c\x00\x70\x3c\x00\x70\x3c\x00\x78'\
-b'\x3c\x00\x78\x3c\x00\x78\x3e\x00\xf8\x1e\x00\xf8\x1f\x83\xf8\x0f'\
-b'\xff\x78\x07\xfe\x78\x01\xfc\x78\x00\x00\xf8\x00\x00\xf0\x00\x00'\
-b'\xf0\x00\x01\xf0\x00\x01\xe0\x00\x03\xe0\x0c\x0f\xc0\x0f\xff\x80'\
-b'\x0f\xfe\x00\x03\xf8\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
-b'\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00'\
-b'\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
-b'\x00\x00\x00\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00'
+b'\x1e\x00\x00\x1e\x00\x00\x1e\x00\x00\x1e\x00\x07\xff\xf8\x07\xff'\
+b'\xf8\x07\xff\xf8\x18\x00\x01\xfc\x00\x0f\xff\x80\x1f\xff\xc0\x1f'\
+b'\x07\xe0\x18\x01\xe0\x10\x01\xf0\x00\x00\xf0\x00\x00\xf0\x00\x00'\
+b'\xf0\x00\x00\xf0\x00\x01\xf0\x00\x01\xe0\x00\x03\xe0\x00\x07\xc0'\
+b'\x00\x0f\x80\x00\x1f\x00\x00\x3e\x00\x00\x7e\x00\x00\xfc\x00\x01'\
+b'\xf8\x00\x03\xf0\x00\x07\xe0\x00\x0f\xc0\x00\x1f\x80\x00\x1f\xff'\
+b'\xf0\x1f\xff\xf0\x1f\xff\xf0\x18\x00\x03\xfe\x00\x0f\xff\x80\x0f'\
+b'\xff\xc0\x0c\x03\xe0\x00\x01\xf0\x00\x00\xf0\x00\x00\xf0\x00\x00'\
+b'\xf0\x00\x00\xf0\x00\x01\xe0\x00\x03\xc0\x00\xff\x80\x00\xfe\x00'\
+b'\x00\xff\xc0\x00\x03\xe0\x00\x00\xf0\x00\x00\xf8\x00\x00\x78\x00'\
+b'\x00\x78\x00\x00\x78\x00\x00\x78\x00\x00\xf8\x00\x01\xf0\x18\x03'\
+b'\xf0\x1f\xff\xe0\x1f\xff\x80\x07\xfe\x00\x18\x00\x00\x07\xc0\x00'\
+b'\x0f\xc0\x00\x0f\xc0\x00\x1f\xc0\x00\x3b\xc0\x00\x3b\xc0\x00\x73'\
+b'\xc0\x00\xf3\xc0\x00\xe3\xc0\x01\xc3\xc0\x03\xc3\xc0\x03\x83\xc0'\
+b'\x07\x03\xc0\x07\x03\xc0\x0e\x03\xc0\x1e\x03\xc0\x1c\x03\xc0\x38'\
+b'\x03\xc0\x3f\xff\xfc\x3f\xff\xfc\x3f\xff\xfc\x00\x03\xc0\x00\x03'\
+b'\xc0\x00\x03\xc0\x00\x03\xc0\x00\x03\xc0\x00\x03\xc0\x18\x00\x0f'\
+b'\xff\xc0\x0f\xff\xc0\x0f\xff\xc0\x0f\x00\x00\x0f\x00\x00\x0f\x00'\
+b'\x00\x0f\x00\x00\x0f\x00\x00\x0f\x00\x00\x0f\xfc\x00\x0f\xff\x00'\
+b'\x0f\xff\xc0\x0c\x0f\xc0\x00\x03\xe0\x00\x01\xe0\x00\x00\xf0\x00'\
+b'\x00\xf0\x00\x00\xf0\x00\x00\xf0\x00\x00\xf0\x00\x00\xf0\x00\x01'\
+b'\xe0\x00\x03\xe0\x18\x07\xc0\x1f\xff\xc0\x1f\xff\x00\x07\xfc\x00'\
+b'\x18\x00\x00\x3f\x80\x00\xff\xe0\x03\xff\xe0\x07\xe0\x60\x0f\x80'\
+b'\x00\x0f\x00\x00\x1f\x00\x00\x1e\x00\x00\x1e\x00\x00\x3c\x00\x00'\
+b'\x3c\x7f\x00\x3c\xff\xc0\x3d\xff\xe0\x3f\x83\xf0\x3e\x00\xf0\x3e'\
+b'\x00\xf8\x3c\x00\x78\x3c\x00\x78\x3c\x00\x78\x1c\x00\x78\x1c\x00'\
+b'\x78\x1e\x00\xf8\x0e\x00\xf0\x0f\x83\xf0\x07\xff\xe0\x03\xff\x80'\
+b'\x00\xfe\x00\x18\x00\x1f\xff\xf0\x1f\xff\xf0\x1f\xff\xf0\x00\x01'\
+b'\xe0\x00\x01\xe0\x00\x03\xe0\x00\x03\xc0\x00\x03\xc0\x00\x07\xc0'\
+b'\x00\x07\x80\x00\x07\x80\x00\x0f\x80\x00\x0f\x00\x00\x0f\x00\x00'\
+b'\x1f\x00\x00\x1e\x00\x00\x1e\x00\x00\x3e\x00\x00\x3c\x00\x00\x3c'\
+b'\x00\x00\x78\x00\x00\x78\x00\x00\x78\x00\x00\xf0\x00\x00\xf0\x00'\
+b'\x00\xf0\x00\x01\xe0\x00\x18\x00\x00\xfe\x00\x03\xff\x80\x0f\xff'\
+b'\xe0\x0f\x83\xe0\x1f\x01\xf0\x1e\x00\xf0\x1e\x00\xf0\x1e\x00\xf0'\
+b'\x1e\x00\xf0\x0f\x01\xe0\x07\x83\xc0\x03\xff\x80\x00\xfe\x00\x07'\
+b'\xff\xc0\x0f\x83\xe0\x1e\x00\xf0\x3e\x00\xf0\x3c\x00\x78\x3c\x00'\
+b'\x78\x3c\x00\x78\x3c\x00\x78\x3e\x00\xf8\x1e\x00\xf0\x1f\x83\xf0'\
+b'\x0f\xff\xe0\x07\xff\xc0\x00\xfe\x00\x18\x00\x00\xfe\x00\x03\xff'\
+b'\x00\x0f\xff\xc0\x1f\x83\xe0\x1e\x00\xe0\x3e\x00\xf0\x3c\x00\x70'\
+b'\x3c\x00\x70\x3c\x00\x78\x3c\x00\x78\x3c\x00\x78\x3e\x00\xf8\x1e'\
+b'\x00\xf8\x1f\x83\xf8\x0f\xff\x78\x07\xfe\x78\x01\xfc\x78\x00\x00'\
+b'\xf8\x00\x00\xf0\x00\x00\xf0\x00\x01\xf0\x00\x01\xe0\x00\x03\xe0'\
+b'\x0c\x0f\xc0\x0f\xff\x80\x0f\xfe\x00\x03\xf8\x00\x0c\x00\x00\x00'\
+b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00'\
+b'\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
+b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x0f\x00\x0f\x00'\
+b'\x0f\x00\x0f\x00'
_index =\
-b'\x00\x00\x38\x00\x8b\x00\xde\x00\x31\x01\x84\x01\xd7\x01\x2a\x02'\
-b'\x7d\x02\xd0\x02\x23\x03\x76\x03\xae\x03'
+b'\x00\x00\x38\x00\x00\x00\xa6\x00\x00\x00\x00\x00\xde\x00\x31\x01'\
+b'\x84\x01\xd7\x01\x2a\x02\x7d\x02\xd0\x02\x23\x03\x76\x03\xc9\x03'\
+b'\x1c\x04\x54\x04'
_mvfont = memoryview(_font)
_mvi = memoryview(_index)
@@ -98,7 +110,7 @@ ifb = lambda l : l[0] | (l[1] << 8)
def get_ch(ch):
oc = ord(ch)
- ioff = 2 * (oc - 48 + 1) if oc >= 48 and oc <= 58 else 0
+ ioff = 2 * (oc - 43 + 1) if oc >= 43 and oc <= 58 else 0
doff = ifb(_mvi[ioff : ])
width = ifb(_mvfont[doff : ])
diff --git a/wasp/fonts/sans36.py b/wasp/fonts/sans36.py
index 683dbb5..642fd5d 100644
--- a/wasp/fonts/sans36.py
+++ b/wasp/fonts/sans36.py
@@ -1,6 +1,6 @@
# Code generated by font_to_py.py.
-# Font: DejaVuSans.ttf
-# Cmd: tools/micropython-font-to-py/font_to_py.py /usr/share/fonts/dejavu/DejaVuSans.ttf --xmap 36 -e 58 -s 48 -l 58 wasp/fonts/sans36.py
+# Font: DejaVuSans.ttf Char set: +-0123456789:
+# Cmd: tools/micropython-font-to-py/font_to_py.py /usr/share/fonts/dejavu/DejaVuSans.ttf --xmap 36 -e 58 -c 0123456789:+- wasp/fonts/sans36.py
version = '0.33'
def height():
@@ -10,7 +10,7 @@ def baseline():
return 35
def max_width():
- return 30
+ return 39
def hmap():
return True
@@ -22,7 +22,7 @@ def monospaced():
return False
def min_ch():
- return 48
+ return 43
def max_ch():
return 58
@@ -32,107 +32,126 @@ b'\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x03\xe0\x03\xe0\x03\xe0\x03\xe0'\
b'\x03\xe0\x03\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xe0\x03\xe0'\
-b'\x03\xe0\x03\xe0\x03\xe0\x03\xe0\x00\x00\x1e\x00\x00\x0f\xc0\x00'\
-b'\x00\x7f\xf8\x00\x00\xff\xfc\x00\x01\xff\xfe\x00\x03\xf0\x3f\x00'\
-b'\x03\xe0\x1f\x00\x07\xc0\x0f\x80\x07\x80\x07\x80\x0f\x80\x07\xc0'\
-b'\x0f\x00\x03\xc0\x0f\x00\x03\xc0\x0f\x00\x03\xc0\x1e\x00\x01\xe0'\
+b'\x03\xe0\x03\xe0\x03\xe0\x03\xe0\x00\x00\x27\x00\x00\x00\x00\x00'\
+b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
+b'\x00\x00\x00\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c\x00\x00\x00'\
+b'\x00\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00'\
+b'\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c'\
+b'\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c\x00'\
+b'\x00\x00\x00\x3c\x00\x00\x07\xff\xff\xff\xe0\x07\xff\xff\xff\xe0'\
+b'\x07\xff\xff\xff\xe0\x07\xff\xff\xff\xe0\x00\x00\x3c\x00\x00\x00'\
+b'\x00\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00'\
+b'\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c'\
+b'\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c\x00'\
+b'\x00\x00\x00\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x00\x00\x00'\
+b'\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
+b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
+b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
+b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3f\xfc'\
+b'\x00\x3f\xfc\x00\x3f\xfc\x00\x3f\xfc\x00\x00\x00\x00\x00\x00\x00'\
+b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
+b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1e\x00'\
+b'\x00\x0f\xc0\x00\x00\x7f\xf8\x00\x00\xff\xfc\x00\x01\xff\xfe\x00'\
+b'\x03\xf0\x3f\x00\x03\xe0\x1f\x00\x07\xc0\x0f\x80\x07\x80\x07\x80'\
+b'\x0f\x80\x07\xc0\x0f\x00\x03\xc0\x0f\x00\x03\xc0\x1f\x00\x03\xc0'\
+b'\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0'\
b'\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0'\
b'\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0'\
-b'\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x0f\x00\x03\xc0'\
-b'\x0f\x00\x03\xc0\x0f\x00\x03\xc0\x0f\x00\x07\xc0\x07\x80\x07\x80'\
-b'\x07\xc0\x0f\x80\x07\xe0\x1f\x00\x03\xf0\x3f\x00\x01\xff\xfe\x00'\
-b'\x00\xff\xfc\x00\x00\x7f\xf8\x00\x00\x1f\xe0\x00\x1e\x00\x00\x00'\
-b'\x00\x00\x00\x1f\x80\x00\x01\xff\x80\x00\x07\xff\x80\x00\x07\xff'\
-b'\x80\x00\x07\xe7\x80\x00\x06\x07\x80\x00\x00\x07\x80\x00\x00\x07'\
+b'\x1f\x00\x03\xc0\x0f\x00\x03\xc0\x0f\x00\x03\xc0\x0f\x80\x07\xc0'\
+b'\x07\x80\x07\x80\x07\xc0\x0f\x80\x03\xe0\x1f\x00\x03\xf0\x3f\x00'\
+b'\x01\xff\xfe\x00\x00\xff\xfc\x00\x00\x7f\xf8\x00\x00\x1f\xc0\x00'\
+b'\x1e\x00\x00\x00\x00\x00\x00\x1f\x80\x00\x01\xff\x80\x00\x07\xff'\
+b'\x80\x00\x07\xff\x80\x00\x07\xe7\x80\x00\x06\x07\x80\x00\x00\x07'\
b'\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07'\
b'\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07'\
b'\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07'\
b'\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07'\
b'\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07'\
-b'\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x07\xff\xff\x80\x07\xff'\
-b'\xff\x80\x07\xff\xff\x80\x07\xff\xff\x80\x00\x00\x00\x00\x1e\x00'\
-b'\x00\x7f\xc0\x00\x03\xff\xf8\x00\x0f\xff\xfc\x00\x0f\xff\xff\x00'\
-b'\x0f\xe0\x3f\x00\x0e\x00\x0f\x80\x08\x00\x07\x80\x00\x00\x07\xc0'\
-b'\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0'\
-b'\x00\x00\x03\xc0\x00\x00\x07\x80\x00\x00\x0f\x80\x00\x00\x0f\x00'\
-b'\x00\x00\x1f\x00\x00\x00\x3e\x00\x00\x00\x7c\x00\x00\x00\xf8\x00'\
-b'\x00\x01\xf0\x00\x00\x03\xe0\x00\x00\x07\xc0\x00\x00\x0f\x80\x00'\
-b'\x00\x1f\x00\x00\x00\x3e\x00\x00\x00\x7c\x00\x00\x00\xf8\x00\x00'\
-b'\x01\xf0\x00\x00\x03\xe0\x00\x00\x07\xc0\x00\x00\x0f\xff\xff\xc0'\
-b'\x0f\xff\xff\xc0\x0f\xff\xff\xc0\x0f\xff\xff\xc0\x00\x00\x00\x00'\
-b'\x1e\x00\x00\xff\xe0\x00\x07\xff\xf8\x00\x07\xff\xfe\x00\x07\xff'\
-b'\xff\x00\x07\x00\x3f\x80\x00\x00\x0f\x80\x00\x00\x07\xc0\x00\x00'\
-b'\x03\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00'\
-b'\x03\xc0\x00\x00\x07\x80\x00\x00\x0f\x80\x00\x00\x3f\x00\x00\x3f'\
-b'\xfe\x00\x00\x3f\xf8\x00\x00\x3f\xfc\x00\x00\x3f\xff\x00\x00\x00'\
-b'\x3f\x80\x00\x00\x0f\xc0\x00\x00\x03\xc0\x00\x00\x03\xe0\x00\x00'\
-b'\x01\xe0\x00\x00\x01\xe0\x00\x00\x01\xe0\x00\x00\x01\xe0\x00\x00'\
-b'\x01\xe0\x00\x00\x03\xe0\x00\x00\x07\xc0\x08\x00\x0f\xc0\x0f\x00'\
-b'\x3f\x80\x0f\xff\xff\x00\x0f\xff\xfe\x00\x07\xff\xf8\x00\x00\x7f'\
-b'\xc0\x00\x1e\x00\x00\x00\x00\x00\x00\x00\xfc\x00\x00\x01\xfc\x00'\
-b'\x00\x01\xfc\x00\x00\x03\xfc\x00\x00\x07\xbc\x00\x00\x07\x3c\x00'\
-b'\x00\x0f\x3c\x00\x00\x1e\x3c\x00\x00\x1e\x3c\x00\x00\x3c\x3c\x00'\
-b'\x00\x78\x3c\x00\x00\x78\x3c\x00\x00\xf0\x3c\x00\x01\xe0\x3c\x00'\
-b'\x01\xe0\x3c\x00\x03\xc0\x3c\x00\x07\x80\x3c\x00\x07\x80\x3c\x00'\
-b'\x0f\x00\x3c\x00\x1f\x00\x3c\x00\x1e\x00\x3c\x00\x3c\x00\x3c\x00'\
-b'\x3f\xff\xff\xe0\x3f\xff\xff\xe0\x3f\xff\xff\xe0\x3f\xff\xff\xe0'\
-b'\x00\x00\x3c\x00\x00\x00\x3c\x00\x00\x00\x3c\x00\x00\x00\x3c\x00'\
+b'\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x07\xff'\
+b'\xff\x80\x07\xff\xff\x80\x07\xff\xff\x80\x07\xff\xff\x80\x00\x00'\
+b'\x00\x00\x1e\x00\x00\x7f\xc0\x00\x03\xff\xf8\x00\x0f\xff\xfe\x00'\
+b'\x0f\xff\xff\x00\x0f\xe0\x3f\x00\x0e\x00\x0f\x80\x08\x00\x07\x80'\
+b'\x00\x00\x07\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0'\
+b'\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x07\x80\x00\x00\x0f\x80'\
+b'\x00\x00\x0f\x00\x00\x00\x1f\x00\x00\x00\x3e\x00\x00\x00\x7c\x00'\
+b'\x00\x00\xf8\x00\x00\x01\xf0\x00\x00\x03\xe0\x00\x00\x07\xc0\x00'\
+b'\x00\x0f\x80\x00\x00\x1f\x00\x00\x00\x3e\x00\x00\x00\x7c\x00\x00'\
+b'\x00\xf8\x00\x00\x01\xf0\x00\x00\x03\xe0\x00\x00\x07\xc0\x00\x00'\
+b'\x0f\xff\xff\xc0\x0f\xff\xff\xc0\x0f\xff\xff\xc0\x0f\xff\xff\xc0'\
+b'\x00\x00\x00\x00\x1e\x00\x00\xff\xe0\x00\x07\xff\xf8\x00\x07\xff'\
+b'\xfe\x00\x07\xff\xff\x00\x07\x00\x3f\x80\x00\x00\x0f\x80\x00\x00'\
+b'\x07\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00'\
+b'\x03\xc0\x00\x00\x03\xc0\x00\x00\x07\x80\x00\x00\x0f\x80\x00\x00'\
+b'\x3f\x00\x00\x3f\xfe\x00\x00\x3f\xf8\x00\x00\x3f\xfc\x00\x00\x3f'\
+b'\xff\x00\x00\x00\x3f\x80\x00\x00\x0f\xc0\x00\x00\x03\xc0\x00\x00'\
+b'\x03\xe0\x00\x00\x01\xe0\x00\x00\x01\xe0\x00\x00\x01\xe0\x00\x00'\
+b'\x01\xe0\x00\x00\x01\xe0\x00\x00\x03\xe0\x00\x00\x07\xc0\x08\x00'\
+b'\x0f\xc0\x0f\x00\x3f\x80\x0f\xff\xff\x00\x0f\xff\xfe\x00\x07\xff'\
+b'\xf8\x00\x00\x7f\xc0\x00\x1e\x00\x00\x00\x00\x00\x00\x00\xfc\x00'\
+b'\x00\x01\xfc\x00\x00\x01\xfc\x00\x00\x03\xfc\x00\x00\x07\xbc\x00'\
+b'\x00\x07\x3c\x00\x00\x0f\x3c\x00\x00\x1e\x3c\x00\x00\x1e\x3c\x00'\
+b'\x00\x3c\x3c\x00\x00\x78\x3c\x00\x00\x78\x3c\x00\x00\xf0\x3c\x00'\
+b'\x01\xe0\x3c\x00\x01\xe0\x3c\x00\x03\xc0\x3c\x00\x07\x80\x3c\x00'\
+b'\x07\x80\x3c\x00\x0f\x00\x3c\x00\x1f\x00\x3c\x00\x1e\x00\x3c\x00'\
+b'\x3c\x00\x3c\x00\x3f\xff\xff\xe0\x3f\xff\xff\xe0\x3f\xff\xff\xe0'\
+b'\x3f\xff\xff\xe0\x00\x00\x3c\x00\x00\x00\x3c\x00\x00\x00\x3c\x00'\
b'\x00\x00\x3c\x00\x00\x00\x3c\x00\x00\x00\x3c\x00\x00\x00\x3c\x00'\
-b'\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x07\xff\xfe\x00\x07\xff'\
-b'\xfe\x00\x07\xff\xfe\x00\x07\xff\xfe\x00\x07\x80\x00\x00\x07\x80'\
+b'\x00\x00\x3c\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x07\xff'\
+b'\xfe\x00\x07\xff\xfe\x00\x07\xff\xfe\x00\x07\xff\xfe\x00\x07\x80'\
b'\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80'\
-b'\x00\x00\x07\x80\x00\x00\x07\xbf\x80\x00\x07\xff\xf0\x00\x07\xff'\
-b'\xfc\x00\x07\xff\xfe\x00\x07\x80\xff\x00\x04\x00\x1f\x00\x00\x00'\
-b'\x0f\x80\x00\x00\x07\x80\x00\x00\x07\xc0\x00\x00\x03\xc0\x00\x00'\
+b'\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\xbf\x80\x00\x07\xff'\
+b'\xf0\x00\x07\xff\xfc\x00\x07\xff\xfe\x00\x07\x80\xff\x00\x04\x00'\
+b'\x1f\x00\x00\x00\x0f\x80\x00\x00\x07\x80\x00\x00\x07\xc0\x00\x00'\
b'\x03\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00'\
-b'\x03\xc0\x00\x00\x07\xc0\x00\x00\x07\x80\x00\x00\x0f\x80\x08\x00'\
-b'\x1f\x00\x0f\x00\x7f\x00\x0f\xff\xfe\x00\x0f\xff\xfc\x00\x0f\xff'\
-b'\xf0\x00\x01\xff\x80\x00\x1e\x00\x00\x03\xfe\x00\x00\x1f\xff\x80'\
-b'\x00\x7f\xff\x80\x00\xff\xff\x80\x01\xfc\x01\x80\x03\xf0\x00\x00'\
-b'\x03\xe0\x00\x00\x07\xc0\x00\x00\x07\x80\x00\x00\x0f\x00\x00\x00'\
-b'\x0f\x00\x00\x00\x0f\x00\x00\x00\x0f\x0f\xe0\x00\x1e\x3f\xfc\x00'\
-b'\x1e\x7f\xfe\x00\x1e\xff\xff\x00\x1f\xf8\x3f\x80\x1f\xe0\x0f\x80'\
-b'\x1f\xc0\x07\xc0\x1f\x80\x03\xc0\x1f\x80\x03\xe0\x1f\x00\x01\xe0'\
-b'\x1f\x00\x01\xe0\x1f\x00\x01\xe0\x0f\x00\x01\xe0\x0f\x00\x01\xe0'\
-b'\x0f\x00\x01\xe0\x0f\x80\x03\xe0\x07\x80\x03\xc0\x07\xc0\x07\xc0'\
-b'\x03\xe0\x0f\x80\x03\xf8\x3f\x80\x01\xff\xff\x00\x00\xff\xfe\x00'\
-b'\x00\x7f\xfc\x00\x00\x0f\xe0\x00\x1e\x00\x00\x00\x00\x00\x0f\xff'\
-b'\xff\xc0\x0f\xff\xff\xc0\x0f\xff\xff\xc0\x0f\xff\xff\x80\x00\x00'\
-b'\x07\x80\x00\x00\x0f\x80\x00\x00\x0f\x00\x00\x00\x1f\x00\x00\x00'\
-b'\x1e\x00\x00\x00\x1e\x00\x00\x00\x3e\x00\x00\x00\x3c\x00\x00\x00'\
-b'\x3c\x00\x00\x00\x78\x00\x00\x00\x78\x00\x00\x00\xf8\x00\x00\x00'\
-b'\xf0\x00\x00\x00\xf0\x00\x00\x01\xe0\x00\x00\x01\xe0\x00\x00\x03'\
-b'\xe0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x07\x80\x00\x00\x07'\
-b'\x80\x00\x00\x0f\x80\x00\x00\x0f\x00\x00\x00\x0f\x00\x00\x00\x1e'\
-b'\x00\x00\x00\x1e\x00\x00\x00\x3e\x00\x00\x00\x3c\x00\x00\x00\x3c'\
-b'\x00\x00\x00\x78\x00\x00\x00\x00\x00\x00\x1e\x00\x00\x1f\xe0\x00'\
-b'\x00\xff\xfc\x00\x01\xff\xfe\x00\x03\xff\xff\x00\x07\xf0\x3f\x80'\
-b'\x07\xc0\x0f\x80\x0f\x80\x07\xc0\x0f\x00\x03\xc0\x0f\x00\x03\xc0'\
-b'\x0f\x00\x03\xc0\x0f\x00\x03\xc0\x0f\x00\x03\xc0\x07\x80\x07\x80'\
-b'\x07\xc0\x0f\x80\x03\xf0\x3f\x00\x01\xff\xfe\x00\x00\x7f\xf8\x00'\
-b'\x00\xff\xfc\x00\x03\xff\xff\x00\x07\xe0\x1f\x80\x0f\x80\x07\xc0'\
-b'\x0f\x00\x03\xc0\x1f\x00\x03\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0'\
-b'\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1f\x00\x03\xe0'\
-b'\x0f\x00\x03\xc0\x0f\x80\x07\xc0\x0f\xe0\x1f\x80\x07\xff\xff\x80'\
-b'\x03\xff\xff\x00\x00\xff\xfc\x00\x00\x1f\xe0\x00\x1e\x00\x00\x1f'\
-b'\xc0\x00\x00\xff\xf0\x00\x01\xff\xfc\x00\x03\xff\xfe\x00\x07\xf0'\
-b'\x7f\x00\x0f\xc0\x1f\x00\x0f\x80\x0f\x80\x0f\x00\x07\x80\x1f\x00'\
-b'\x07\xc0\x1e\x00\x03\xc0\x1e\x00\x03\xc0\x1e\x00\x03\xc0\x1e\x00'\
-b'\x03\xe0\x1e\x00\x03\xe0\x1e\x00\x03\xe0\x1f\x00\x07\xe0\x0f\x00'\
-b'\x07\xe0\x0f\x80\x0f\xe0\x0f\xc0\x1f\xe0\x07\xf0\x7f\xe0\x03\xff'\
-b'\xfd\xe0\x01\xff\xf9\xe0\x00\xff\xf1\xe0\x00\x1f\xc3\xc0\x00\x00'\
b'\x03\xc0\x00\x00\x03\xc0\x00\x00\x07\xc0\x00\x00\x07\x80\x00\x00'\
-b'\x0f\x80\x00\x00\x1f\x00\x00\x00\x3f\x00\x06\x00\xfe\x00\x07\xff'\
-b'\xfc\x00\x07\xff\xf8\x00\x07\xff\xe0\x00\x01\xff\x00\x00\x10\x00'\
-b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
-b'\x00\x00\x00\x00\x00\x00\x03\xe0\x03\xe0\x03\xe0\x03\xe0\x03\xe0'\
-b'\x03\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
+b'\x0f\x80\x08\x00\x1f\x00\x0f\x00\x7f\x00\x0f\xff\xfe\x00\x0f\xff'\
+b'\xfc\x00\x0f\xff\xf0\x00\x01\xff\x80\x00\x1e\x00\x00\x03\xfe\x00'\
+b'\x00\x1f\xff\x80\x00\x7f\xff\x80\x00\xff\xff\x80\x01\xfc\x01\x80'\
+b'\x03\xf0\x00\x00\x03\xc0\x00\x00\x07\xc0\x00\x00\x07\x80\x00\x00'\
+b'\x0f\x00\x00\x00\x0f\x00\x00\x00\x0f\x00\x00\x00\x1f\x0f\xe0\x00'\
+b'\x1e\x3f\xfc\x00\x1e\x7f\xfe\x00\x1e\xff\xff\x00\x1f\xf8\x3f\x80'\
+b'\x1f\xe0\x0f\xc0\x1f\xc0\x07\xc0\x1f\x80\x03\xc0\x1f\x80\x03\xe0'\
+b'\x1f\x00\x01\xe0\x1f\x00\x01\xe0\x1f\x00\x01\xe0\x0f\x00\x01\xe0'\
+b'\x0f\x00\x01\xe0\x0f\x00\x01\xe0\x0f\x80\x03\xe0\x07\x80\x03\xc0'\
+b'\x07\xc0\x07\xc0\x03\xe0\x0f\x80\x03\xf8\x3f\x80\x01\xff\xff\x00'\
+b'\x00\xff\xfe\x00\x00\x7f\xfc\x00\x00\x0f\xe0\x00\x1e\x00\x00\x00'\
+b'\x00\x00\x0f\xff\xff\xc0\x0f\xff\xff\xc0\x0f\xff\xff\xc0\x0f\xff'\
+b'\xff\x80\x00\x00\x07\x80\x00\x00\x0f\x80\x00\x00\x0f\x00\x00\x00'\
+b'\x1f\x00\x00\x00\x1e\x00\x00\x00\x1e\x00\x00\x00\x3e\x00\x00\x00'\
+b'\x3c\x00\x00\x00\x3c\x00\x00\x00\x78\x00\x00\x00\x78\x00\x00\x00'\
+b'\xf8\x00\x00\x00\xf0\x00\x00\x00\xf0\x00\x00\x01\xe0\x00\x00\x01'\
+b'\xe0\x00\x00\x03\xe0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x07'\
+b'\x80\x00\x00\x07\x80\x00\x00\x0f\x80\x00\x00\x0f\x00\x00\x00\x0f'\
+b'\x00\x00\x00\x1e\x00\x00\x00\x1e\x00\x00\x00\x3e\x00\x00\x00\x3c'\
+b'\x00\x00\x00\x3c\x00\x00\x00\x78\x00\x00\x00\x00\x00\x00\x1e\x00'\
+b'\x00\x1f\xe0\x00\x00\xff\xfc\x00\x01\xff\xfe\x00\x03\xff\xff\x00'\
+b'\x07\xf0\x3f\x80\x07\xc0\x0f\x80\x0f\x80\x07\xc0\x0f\x00\x03\xc0'\
+b'\x0f\x00\x03\xc0\x0f\x00\x03\xc0\x0f\x00\x03\xc0\x0f\x00\x03\xc0'\
+b'\x07\x80\x07\x80\x07\xc0\x0f\x80\x03\xf0\x3f\x00\x01\xff\xfe\x00'\
+b'\x00\x7f\xf8\x00\x00\xff\xfc\x00\x03\xff\xff\x00\x07\xe0\x1f\x80'\
+b'\x0f\x80\x07\xc0\x0f\x00\x03\xc0\x1f\x00\x03\xe0\x1e\x00\x01\xe0'\
+b'\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0'\
+b'\x1f\x00\x03\xe0\x0f\x00\x03\xc0\x0f\x80\x07\xc0\x07\xe0\x1f\x80'\
+b'\x07\xff\xff\x80\x03\xff\xff\x00\x00\xff\xfc\x00\x00\x1f\xe0\x00'\
+b'\x1e\x00\x00\x1f\xc0\x00\x00\xff\xf8\x00\x01\xff\xfc\x00\x03\xff'\
+b'\xfe\x00\x07\xf0\x7f\x00\x0f\xc0\x1f\x00\x0f\x80\x0f\x80\x0f\x00'\
+b'\x07\x80\x1f\x00\x07\xc0\x1e\x00\x03\xc0\x1e\x00\x03\xc0\x1e\x00'\
+b'\x03\xc0\x1e\x00\x03\xe0\x1e\x00\x03\xe0\x1e\x00\x03\xe0\x1f\x00'\
+b'\x07\xe0\x0f\x00\x07\xe0\x0f\x80\x0f\xe0\x0f\xc0\x1f\xe0\x07\xf0'\
+b'\x7f\xe0\x03\xff\xfd\xe0\x01\xff\xf9\xe0\x00\xff\xf1\xe0\x00\x1f'\
+b'\xc3\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x07\xc0\x00\x00'\
+b'\x07\x80\x00\x00\x0f\x80\x00\x00\x1f\x00\x00\x00\x3f\x00\x06\x00'\
+b'\xfe\x00\x07\xff\xfc\x00\x07\xff\xf8\x00\x07\xff\xe0\x00\x01\xff'\
+b'\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xe0\x03\xe0\x03\xe0'\
-b'\x03\xe0\x03\xe0\x03\xe0\x00\x00'
+b'\x03\xe0\x03\xe0\x03\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
+b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xe0'\
+b'\x03\xe0\x03\xe0\x03\xe0\x03\xe0\x03\xe0\x00\x00'
_index =\
-b'\x00\x00\x4a\x00\xdc\x00\x6e\x01\x00\x02\x92\x02\x24\x03\xb6\x03'\
-b'\x48\x04\xda\x04\x6c\x05\xfe\x05\x48\x06'
+b'\x00\x00\x4a\x00\x00\x00\x00\x01\x00\x00\x00\x00\x6e\x01\x00\x02'\
+b'\x92\x02\x24\x03\xb6\x03\x48\x04\xda\x04\x6c\x05\xfe\x05\x90\x06'\
+b'\x22\x07\x6c\x07'
_mvfont = memoryview(_font)
_mvi = memoryview(_index)
@@ -140,7 +159,7 @@ ifb = lambda l : l[0] | (l[1] << 8)
def get_ch(ch):
oc = ord(ch)
- ioff = 2 * (oc - 48 + 1) if oc >= 48 and oc <= 58 else 0
+ ioff = 2 * (oc - 43 + 1) if oc >= 43 and oc <= 58 else 0
doff = ifb(_mvi[ioff : ])
width = ifb(_mvfont[doff : ])
diff --git a/wasp/widgets.py b/wasp/widgets.py
index 01d20a8..4e63d95 100644
--- a/wasp/widgets.py
+++ b/wasp/widgets.py
@@ -222,11 +222,14 @@ class Button():
def draw(self):
"""Draw the button."""
- draw = wasp.watch.drawable
- im = self._im
- bg = draw.darken(wasp.system.theme('ui'))
+ bg = wasp.watch.drawable.darken(wasp.system.theme('ui'))
frame = wasp.system.theme('mid')
txt = wasp.system.theme('bright')
+ self.update(bg, frame, txt)
+
+ def update(self, bg, frame, txt):
+ draw = wasp.watch.drawable
+ im = self._im
draw.fill(bg, im[0], im[1], im[2], im[3])
draw.set_color(txt, bg)
@@ -255,6 +258,31 @@ class Button():
return False
+class ToggleButton(Button):
+ """A button with a text label that can be toggled on and off."""
+ def __init__(self, x, y, w, h, label):
+ super().__init__(x, y, w, h, label)
+ self.state = False
+
+ def draw(self):
+ """Draw the button."""
+ draw = wasp.watch.drawable
+
+ if self.state:
+ bg = draw.darken(wasp.system.theme('ui'))
+ else:
+ bg = draw.darken(wasp.system.theme('mid'))
+ frame = wasp.system.theme('mid')
+ txt = wasp.system.theme('bright')
+
+ self.update(bg, frame, txt)
+
+ def touch(self, event):
+ """Handle touch events."""
+ if super().touch(event):
+ self.state = not self.state
+ self.draw()
+
class Checkbox():
"""A simple (labelled) checkbox."""
def __init__(self, x, y, label=None):
@@ -294,9 +322,10 @@ class Checkbox():
def touch(self, event):
"""Handle touch events."""
+ x = event[1]
y = event[2]
im = self._im
- if y >= im[1] and y < im[1]+40:
+ if (self.label or im[0] <= x < im[0]+40) and im[1] <= y < im[1]+40:
self.state = not self.state
self.update()
return True