summaryrefslogtreecommitdiff
path: root/src/skeleton.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/skeleton.py')
-rw-r--r--src/skeleton.py199
1 files changed, 199 insertions, 0 deletions
diff --git a/src/skeleton.py b/src/skeleton.py
new file mode 100644
index 0000000..8497d34
--- /dev/null
+++ b/src/skeleton.py
@@ -0,0 +1,199 @@
+import displayio
+import terminalio
+from adafruit_display_shapes.rect import Rect
+from adafruit_display_text import label
+
+from collections import namedtuple
+from supervisor import ticks_ms
+from actions import Action
+import ticks
+
+class Group(object):
+ def __init__(self, color, actions):
+
+ # The color of the LED for the selected element
+ self.color = color
+
+ self.actions = actions
+
+ self._selected = actions[0][0]
+
+ @property
+ def selected(self):
+ return self._selected
+
+ @selected.setter
+ def selected(self, value):
+ """Set the value, and switch the LED accordingly"""
+
+ keys = [action[0] for action in self.actions]
+
+ if value not in keys:
+ return
+
+ for keyId in keys:
+ Action().macropad.pixels[keyId] = 0
+ Action().macropad.pixels[value] = int(self.color)
+ self._selected = value
+
+class Configuration(object):
+
+ def __init__(self, title):
+
+ # Set the application available in the menu by default
+ self.visible = True
+ self.Action = namedtuple("Action", ("name", "callback", "color"))
+ self.title = title
+ self.keys = {
+ 0 : None, 1 : None, 2 : None,
+ 3 : None, 4 : None, 5 : None,
+ 6 : None, 7 : None, 8 : None,
+ 9 : None, 10 : None, 11 : None,
+ 12 : None,
+ 13 : None,
+ }
+ self.group = []
+ self.tick = None
+
+ def registerKey(self, keyId, name, callback, color):
+ if keyId > 13:
+ return
+ self.keys[keyId] = self.Action(name, callback, color)
+
+ def registerGroup(self, group):
+ self.group.append(group)
+
+ def setTick(self, duration, callback):
+ self.tick = (duration, callback)
+
+class Handler(object):
+
+ def __init__(self, macropad, configuration):
+ self.macropad = macropad
+ self.group = displayio.Group()
+
+ self.keys = {
+ 0 : None, 1 : None, 2 : None,
+ 3 : None, 4 : None, 5 : None,
+ 6 : None, 7 : None, 8 : None,
+ 9 : None, 10 : None, 11 : None,
+ 12 : None,
+ 13 : None,
+ }
+
+ self.colors = {
+ 0 : None, 1 : None, 2 : None,
+ 3 : None, 4 : None, 5 : None,
+ 6 : None, 7 : None, 8 : None,
+ 9 : None, 10 : None, 11 : None,
+ }
+
+ self.options = configuration.group
+
+ self.name = configuration.title
+
+ for index, value in configuration.keys.items():
+ if value is None:
+ continue
+ self.keys[index] = value.name, value.callback
+ self.colors[index] = value.color
+
+ for option in self.options:
+ for action in option.actions:
+ keyId = action[0]
+ self.keys[keyId] = action[1], lambda macropad, key, pressed: None
+ self.macropad.pixels[option.selected] = int(option.color)
+
+ self.periodic_callback = None
+ self.next_tick = None
+
+ if configuration.tick is not None:
+ self.periodic_callback = configuration.tick
+ self._update_tick()
+ self.macropad.pixels.show()
+
+ def _update_tick(self):
+ self.next_tick = ticks.add(
+ ticks_ms(),
+ self.periodic_callback[0]
+ )
+
+ def _set_color(self, key, pressed):
+ if pressed:
+ self.macropad.pixels[key] = int(0x010101)
+ else:
+ color = self.colors[key]
+ self.macropad.pixels[key] = int( self.colors[key] or 0 )
+ for option in self.options:
+ self.macropad.pixels[option.selected] = int(option.color)
+
+ def tick(self):
+ "Execute asyncronous events"
+
+ Action().collect_tasks()
+ if self.next_tick is None or ticks.less(self.next_tick):
+ return
+
+ self.periodic_callback[1](self.macropad)
+ self._update_tick()
+
+ def start(self):
+ self.position = self.macropad.encoder
+
+ for key_index in range(12):
+ x = key_index % 3
+ y = key_index // 3
+ self.group.append(label.Label(terminalio.FONT, text='', color=0xFFFFFF,
+ anchored_position=((self.macropad.display.width - 1) * x / 2,
+ self.macropad.display.height - 1 -
+ (3 - y) * 12),
+ anchor_point=(x / 2, 1.0)))
+ self.group.append(Rect(0, 0, self.macropad.display.width, 12, fill=0xFFFFFF))
+ self.group.append(label.Label(terminalio.FONT, text='', color=0x000000,
+ anchored_position=(self.macropad.display.width//2, -2),
+ anchor_point=(0.5, 0.0)))
+ self.macropad.display.show(self.group)
+
+ self.group[13].text = self.name # Application name
+ for i in range(12):
+ if self.keys[i] is not None:
+ self.group[i].text = self.keys[i][0]
+ self.macropad.keyboard.release_all()
+ self.macropad.consumer_control.release()
+ self.macropad.mouse.release_all()
+ self.macropad.stop_tone()
+ for key in range(12):
+ self._set_color(key, False)
+ self.macropad.pixels.show()
+ self.macropad.display.refresh()
+
+ def execute_action(self, key, pressed):
+
+ for option in self.options:
+ option.selected = key
+
+ action = self.keys[key]
+
+ # Do nothing if there is no action for this key
+ if action is None:
+ return
+
+ # Update the leds
+ if key < 12:
+ if pressed: Action().flash(key, 0x010101)
+ else: self._set_color(key, pressed)
+ else:
+ for key_idx in range(12):
+ self._set_color(key_idx, pressed)
+ self.macropad.pixels.show()
+
+ result = action[1](self.macropad, key, pressed)
+
+ # If we use the rotary encoder, mark all the actions as resolved.
+ if key >= 12:
+ action[1](self.macropad, key, False)
+ for key_idx in range(12):
+ self._set_color(key_idx, False)
+ self.macropad.pixels.show()
+
+ return result