diff options
| author | kozova1 <mug66kk@gmail.com> | 2020-12-05 18:27:55 (GMT) |
|---|---|---|
| committer | Daniel Thompson <daniel@redfelineninja.org.uk> | 2020-12-13 16:51:07 (GMT) |
| commit | 2624a6e998f7b5a78a38fa98be15bf3d25ed81a9 (patch) | |
| tree | 932437f9d64c3ca21745deacce570224c240a8de /wasp | |
| parent | 784c9bb36d29457ddb3a5ef5af55918e1f4cd93c (diff) | |
Added basic theming engine.
This theming engine uses a bytestring (but supports anything indexable,
as long as the index results are a byte long),
stored as `wasp.system._theme`.
It has a default value, which should not change anything about the way this looks currently.
The theme can be set via `wasp.system.set_theme`,
but this should *ONLY* be used in `main.py`.
`wasp.system.set_theme` will return True if it was successful,
or False if the theme is of an old format.
Using an old format theme will *not* crash the watch,
but will use the default theme instead.
To theme this, one has to use tools/themer.py (use flag -h for complete explanation)
to generate a bytestring that's added in main.py (see diff).
The bytestring is then loaded into 'wasp.system._theme'.
Theme values can be looked up by apps by using `wasp.system.theme("theme-key")`.
Theme keys appear in the function body of `wasp.system.theme()`.
I've took the liberty of converting existing apps to use this method,
and it seems to work well.
A test theme is provided in `tools/test_theme.py`
Signed-off-by: kozova1 <mug66kk@gmail.com>
Diffstat (limited to 'wasp')
| -rw-r--r-- | wasp/apps/clock.py | 15 | ||||
| -rw-r--r-- | wasp/wasp.py | 29 | ||||
| -rw-r--r-- | wasp/widgets.py | 45 |
3 files changed, 66 insertions, 23 deletions
diff --git a/wasp/apps/clock.py b/wasp/apps/clock.py index 106e712..c062d3e 100644 --- a/wasp/apps/clock.py +++ b/wasp/apps/clock.py @@ -76,7 +76,8 @@ class ClockApp(): # Clear the display and draw that static parts of the watch face draw.fill() - draw.rleblit(digits.clock_colon, pos=(2*48, 80), fg=0xb5b6) + draw.rleblit(digits.clock_colon, pos=(2*48, 80), + fg=wasp.system.theme('accent-mid')) # Redraw the status bar wasp.system.bar.draw() @@ -95,10 +96,14 @@ class ClockApp(): month = MONTH[month*3:(month+1)*3] # Draw the changeable parts of the watch face - draw.rleblit(DIGITS[now[4] % 10], pos=(4*48, 80)) - draw.rleblit(DIGITS[now[4] // 10], pos=(3*48, 80), fg=0xbdb6) - draw.rleblit(DIGITS[now[3] % 10], pos=(1*48, 80)) - draw.rleblit(DIGITS[now[3] // 10], pos=(0*48, 80), fg=0xbdb6) + draw.rleblit(DIGITS[now[4] % 10], pos=(4*48, 80), + fg=wasp.system.theme('accent-hi')) + draw.rleblit(DIGITS[now[4] // 10], pos=(3*48, 80), + fg=wasp.system.theme('accent-lo')) + draw.rleblit(DIGITS[now[3] % 10], pos=(1*48, 80), + fg=wasp.system.theme('accent-hi')) + draw.rleblit(DIGITS[now[3] // 10], pos=(0*48, 80), + fg=wasp.system.theme('accent-lo')) draw.string('{} {} {}'.format(now[2], month, now[0]), 0, 180, width=240) diff --git a/wasp/wasp.py b/wasp/wasp.py index 7cf2883..4837e12 100644 --- a/wasp/wasp.py +++ b/wasp/wasp.py @@ -14,7 +14,6 @@ wasp.watch is an import of :py:mod:`watch` and is simply provided as a shortcut (and to reduce memory by keeping it out of other namespaces). """ - import gc import machine import micropython @@ -118,6 +117,8 @@ class Manager(): self.musicstate = {} self.musicinfo = {} + self._theme = b'\xef{\xef{\xef{<\xe7\xef{\xb6\xb5\xb6\xbd\xff\xff\xff9' + self.blank_after = 15 self._alarms = [] @@ -514,4 +515,30 @@ class Manager(): self._scheduling = enable + def set_theme(self, new_theme) -> bool: + """Sets the system theme. + + Accepts anything that supports indexing, + and has a len() equivalent to the default theme.""" + if len(self._theme) != len(new_theme): + return False + self._theme = new_theme + return True + + def theme(self, theme_part: str) -> int: + """Returns the relevant part of theme. For more see ../tools/themer.py""" + theme_parts = ("ble", + "scroll-indicator", + "battery-charging", + "status-clock", + "notify-icon", + "accent-mid", + "accent-lo", + "accent-hi", + "slider-default") + if theme_part not in theme_parts: + raise IndexError('Theme part {} does not exist'.format(theme_part)) + idx = theme_parts.index(theme_part) * 2 + return self._theme[idx] | (self._theme[idx+1] << 8) + system = Manager() diff --git a/wasp/widgets.py b/wasp/widgets.py index d5abd16..1d79e22 100644 --- a/wasp/widgets.py +++ b/wasp/widgets.py @@ -39,7 +39,8 @@ class BatteryMeter: if watch.battery.charging(): if self.level != -1: - draw.rleblit(icon, pos=(239-icon[0], 0), fg=0x7bef) + draw.rleblit(icon, pos=(239-icon[0], 0), + fg=wasp.system.theme('battery-charging')) self.level = -1 else: level = watch.battery.level() @@ -108,7 +109,7 @@ class Clock: draw = wasp.watch.drawable draw.set_font(fonts.sans28) - draw.set_color(0xe73c) + draw.set_color(wasp.system.theme('status-clock')) draw.string(t1, 52, 12, 138) self.on_screen = now @@ -137,13 +138,15 @@ class NotificationBar: (x, y) = self._pos if wasp.watch.connected(): - draw.blit(icons.blestatus, x, y, fg=0x7bef) + draw.blit(icons.blestatus, x, y, fg=wasp.system.theme('ble')) if wasp.system.notifications: - draw.blit(icons.notification, x+22, y, fg=0x7bef) + draw.blit(icons.notification, x+22, y, + fg=wasp.system.theme('notify-icon')) else: draw.fill(0, x+22, y, 30, 32) elif wasp.system.notifications: - draw.blit(icons.notification, x, y, fg=0x7bef) + draw.blit(icons.notification, x, y, + fg=wasp.system.theme('notify-icon')) draw.fill(0, x+30, y, 22, 32) else: draw.fill(0, x, y, 52, 32) @@ -206,10 +209,13 @@ class ScrollIndicator: def update(self): """Update from scrolling indicator.""" draw = watch.drawable + color = wasp.system.theme('scroll-indicator') + if self.up: - draw.rleblit(icons.up_arrow, pos=self._pos, fg=0x7bef) + draw.rleblit(icons.up_arrow, pos=self._pos, fg=color) if self.down: - draw.rleblit(icons.down_arrow, pos=(self._pos[0], self._pos[1] + 13), fg=0x7bef) + draw.rleblit(icons.down_arrow, pos=(self._pos[0], self._pos[1] + 13), + fg=color) _SLIDER_KNOB_DIAMETER = const(40) _SLIDER_KNOB_RADIUS = const(_SLIDER_KNOB_DIAMETER // 2) @@ -221,22 +227,14 @@ _SLIDER_TRACK_Y2 = const(_SLIDER_TRACK_Y1 + _SLIDER_TRACK_HEIGHT) class Slider(): """A slider to select values.""" - def __init__(self, steps, x=10, y=90, color=0x39ff): + def __init__(self, steps, x=10, y=90, color=None): self.value = 0 self._steps = steps self._stepsize = _SLIDER_TRACK / (steps-1) self._x = x self._y = y self._color = color - - # Automatically generate a lowlight color - if color < 0b10110_000000_00000: - color = (color | 0b10110_000000_00000) & 0b10110_111111_11111 - if (color & 0b111111_00000) < 0b101100_00000: - color = (color | 0b101100_00000) & 0b11111_101100_11111 - if (color & 0b11111) < 0b10110: - color = (color | 0b11000) & 0b11111_111111_10110 - self._lowlight = color + self._lowlight = None def draw(self): """Draw the slider.""" @@ -244,6 +242,19 @@ class Slider(): x = self._x y = self._y color = self._color + if self._color is None: + self._color = wasp.system.theme('slider-default') + color = self._color + if self._lowlight is None: + # Automatically generate a lowlight color + if color < 0b10110_000000_00000: + color = (color | 0b10110_000000_00000) & 0b10110_111111_11111 + if (color & 0b111111_00000) < 0b101100_00000: + color = (color | 0b101100_00000) & 0b11111_101100_11111 + if (color & 0b11111) < 0b10110: + color = (color | 0b11000) & 0b11111_111111_10110 + self._lowlight = color + color = self._color light = self._lowlight knob_x = x + ((_SLIDER_TRACK * self.value) // (self._steps-1)) |
