141 lines
5.4 KiB
Python
Executable File
141 lines
5.4 KiB
Python
Executable File
|
|
from .keymap_delta import KeymapDelta, LayerDelta
|
|
from .pinstate_manager import PinManager
|
|
from .key_types.base import KeyBase
|
|
from .pin import Pin
|
|
|
|
|
|
# Needs to be built in a way where every "key type" only has to know how to modify it's own state
|
|
# it cannot be passed a pin or keyboard instance
|
|
# this is to help keep order in what can access what
|
|
|
|
# layer manager should be able to figure out what needs to happen to the state after a loop is run.
|
|
#
|
|
|
|
# Keys
|
|
# Keys have one way communication from KeymapManager to key and are allowed to return a result
|
|
# all keys changes together create a delta that is handled by the manager
|
|
# the manager defines an interface for changes that can happen to the state
|
|
# - Pressed
|
|
# - unpressed
|
|
# - Layer was changed
|
|
# When a delta is applied the manager can figure out what to do for that state index
|
|
|
|
# state
|
|
# Keys state is stored and managed in the manager
|
|
# One single layer of state removes the issue of when layers are changing
|
|
# each state is a class that can be consumed from different aspects, keycode, toggle, hold etc
|
|
# Where the state presents itself in the way that is asked
|
|
|
|
|
|
# Pins
|
|
# Can be asked for their current event
|
|
# Pins state is a class that holds current and last, can give you the delta to figure out what to change
|
|
_LAYERS_HOLD_NONE = None
|
|
_LAYERS_TOGGLE_NONE = 0
|
|
|
|
|
|
class LayerManager:
|
|
number_of_layers: int = None
|
|
current_hold_layer: int = None
|
|
current_toggle_layer: int = None
|
|
|
|
def __init__(self, number_of_layers: int) -> None:
|
|
assert number_of_layers is not None
|
|
assert number_of_layers > 0
|
|
self.number_of_layers = number_of_layers
|
|
self.current_hold_layer = _LAYERS_HOLD_NONE
|
|
self.current_toggle_layer = _LAYERS_TOGGLE_NONE
|
|
|
|
def get_current_layer(self) -> int:
|
|
return self.current_hold_layer if self.current_hold_layer is not _LAYERS_HOLD_NONE else self.current_toggle_layer
|
|
|
|
def step(self, changes: LayerDelta):
|
|
hold_layer = self.current_hold_layer
|
|
for layer in changes.get_hold_layers_to_remove():
|
|
if layer.get_layer() == hold_layer:
|
|
hold_layer = _LAYERS_HOLD_NONE
|
|
for layer in changes.get_hold_layers_to_apply():
|
|
hold_layer = layer.get_layer()
|
|
self.current_hold_layer = hold_layer
|
|
|
|
toggle_layer = self.current_toggle_layer
|
|
for layer in changes.get_toggle_layers_to_remove():
|
|
if layer.get_layer() == toggle_layer:
|
|
toggle_layer = _LAYERS_TOGGLE_NONE
|
|
for layer in changes.get_toggle_layers_to_apply():
|
|
toggle_layer = layer.get_layer()
|
|
self.current_toggle_layer = toggle_layer
|
|
|
|
|
|
class KeymapReport:
|
|
keymap_changes: KeymapDelta = None
|
|
current_layer: int = None
|
|
|
|
def __init__(self, keymap_changes: KeymapDelta, current_layer: int) -> None:
|
|
assert keymap_changes is not None
|
|
assert current_layer is not None
|
|
self.keymap_changes = keymap_changes
|
|
self.current_layer = current_layer
|
|
|
|
|
|
class KeymapManager:
|
|
keymap: list[list[KeyBase]] = None
|
|
pin_manager: PinManager = None
|
|
layer_manager: LayerManager = None
|
|
keys_state: list[object] = None
|
|
keycodes_currently_pressed: set = None
|
|
|
|
def __init__(self, keymap: list[list[KeyBase]], pins: list[Pin]):
|
|
self.keymap = keymap
|
|
self.pin_manager = PinManager(pins)
|
|
self.layer_manager = LayerManager(len(keymap))
|
|
self.keys_state = [None for key in keymap[0]]
|
|
self.keycodes_currently_pressed = set()
|
|
|
|
def add_to_pressed_keycodes(self, keycode: int):
|
|
self.keycodes_currently_pressed.add(keycode)
|
|
|
|
def remove_from_pressed_keycodes(self, keycode: int):
|
|
try:
|
|
self.keycodes_currently_pressed.remove(keycode)
|
|
except KeyError:
|
|
pass
|
|
|
|
def createReport(self, keymap_changes: KeymapDelta, layer_changes: LayerDelta) -> KeymapReport:
|
|
old_layer = self.layer_manager.get_current_layer()
|
|
self.layer_manager.step(layer_changes)
|
|
new_layer = self.layer_manager.get_current_layer()
|
|
layer_has_changed = new_layer != old_layer
|
|
if layer_has_changed:
|
|
delta = KeymapDelta()
|
|
for keycode in self.keycodes_currently_pressed:
|
|
delta.unpress(keycode)
|
|
self.keycodes_currently_pressed.clear()
|
|
keymap_changes.merge_deltas(delta)
|
|
[self.add_to_pressed_keycodes(keycode)
|
|
for keycode in keymap_changes.get_to_press()]
|
|
[self.remove_from_pressed_keycodes(
|
|
keycode) for keycode in keymap_changes.get_to_unpress()]
|
|
return KeymapReport(keymap_changes, new_layer)
|
|
|
|
def step(self) -> KeymapReport:
|
|
self.pin_manager.step()
|
|
pin_changes = self.pin_manager.get_state_delta()
|
|
keymap_changes = KeymapDelta()
|
|
layer_changes = LayerDelta()
|
|
current_layer_index = self.layer_manager.get_current_layer()
|
|
for pin_index in range(len(pin_changes)):
|
|
pin_state = pin_changes[pin_index]
|
|
if pin_state is None:
|
|
continue
|
|
|
|
key = self.keymap[current_layer_index][pin_index]
|
|
custom_state = self.keys_state[pin_index]
|
|
key_changes = key.calculate_changes(pin_state, custom_state)
|
|
keymap_changes.merge_deltas(key_changes.keymap_delta)
|
|
layer_changes.merge_deltas(key_changes.layer_delta)
|
|
self.keys_state[pin_index] = key_changes.special_state
|
|
|
|
return self.createReport(keymap_changes, layer_changes)
|