Adding ComboLayers to Layers Module (See #658) (#666)

---------

Co-authored-by: xs5871 <60395129+xs5871@users.noreply.github.com>
This commit is contained in:
Alex Miller
2023-03-10 15:40:57 -05:00
committed by GitHub
parent adff02e88a
commit 878fe0deca
3 changed files with 180 additions and 41 deletions

View File

@@ -36,9 +36,15 @@ class LayerKeyMeta:
class Layers(HoldTap):
'''Gives access to the keys used to enable the layer system'''
def __init__(self):
_active_combo = None
def __init__(
self,
combo_layers=None,
):
# Layers
super().__init__()
self.combo_layers = combo_layers
make_argumented_key(
validator=layer_key_validator,
names=('MO',),
@@ -46,9 +52,7 @@ class Layers(HoldTap):
on_release=self._mo_released,
)
make_argumented_key(
validator=layer_key_validator,
names=('DF',),
on_press=self._df_pressed,
validator=layer_key_validator, names=('DF',), on_press=self._df_pressed
)
make_argumented_key(
validator=layer_key_validator,
@@ -57,14 +61,10 @@ class Layers(HoldTap):
on_release=self._lm_released,
)
make_argumented_key(
validator=layer_key_validator,
names=('TG',),
on_press=self._tg_pressed,
validator=layer_key_validator, names=('TG',), on_press=self._tg_pressed
)
make_argumented_key(
validator=layer_key_validator,
names=('TO',),
on_press=self._to_pressed,
validator=layer_key_validator, names=('TO',), on_press=self._to_pressed
)
make_argumented_key(
validator=layer_key_validator_lt,
@@ -83,67 +83,102 @@ class Layers(HoldTap):
'''
Switches the default layer
'''
keyboard.active_layers[-1] = key.meta.layer
self._print_debug(keyboard)
self.activate_layer(keyboard, key.meta.layer, as_default=True)
def _mo_pressed(self, key, keyboard, *args, **kwargs):
'''
Momentarily activates layer, switches off when you let go
'''
keyboard.active_layers.insert(0, key.meta.layer)
self._print_debug(keyboard)
self.activate_layer(keyboard, key.meta.layer)
@staticmethod
def _mo_released(key, keyboard, *args, **kwargs):
# remove the first instance of the target layer
# from the active list
# under almost all normal use cases, this will
# disable the layer (but preserve it if it was triggered
# as a default layer, etc.)
# this also resolves an issue where using DF() on a layer
# triggered by MO() and then defaulting to the MO()'s layer
# would result in no layers active
try:
del_idx = keyboard.active_layers.index(key.meta.layer)
del keyboard.active_layers[del_idx]
except ValueError:
pass
__class__._print_debug(__class__, keyboard)
def _mo_released(self, key, keyboard, *args, **kwargs):
self.deactivate_layer(keyboard, key.meta.layer)
def _lm_pressed(self, key, keyboard, *args, **kwargs):
'''
As MO(layer) but with mod active
'''
# Sets the timer start and acts like MO otherwise
keyboard.add_key(key.meta.kc)
self._mo_pressed(key, keyboard, *args, **kwargs)
keyboard.hid_pending = True
keyboard.keys_pressed.add(key.meta.kc)
self.activate_layer(keyboard, key.meta.layer)
def _lm_released(self, key, keyboard, *args, **kwargs):
'''
As MO(layer) but with mod active
'''
keyboard.remove_key(key.meta.kc)
self._mo_released(key, keyboard, *args, **kwargs)
keyboard.hid_pending = True
keyboard.keys_pressed.discard(key.meta.kc)
self.deactivate_layer(keyboard, key.meta.layer)
def _tg_pressed(self, key, keyboard, *args, **kwargs):
'''
Toggles the layer (enables it if not active, and vise versa)
'''
# See mo_released for implementation details around this
try:
del_idx = keyboard.active_layers.index(key.meta.layer)
del keyboard.active_layers[del_idx]
except ValueError:
keyboard.active_layers.insert(0, key.meta.layer)
if key.meta.layer in keyboard.active_layers:
self.deactivate_layer(keyboard, key.meta.layer)
else:
self.activate_layer(keyboard, key.meta.layer)
def _to_pressed(self, key, keyboard, *args, **kwargs):
'''
Activates layer and deactivates all other layers
'''
self._active_combo = None
keyboard.active_layers.clear()
keyboard.active_layers.insert(0, key.meta.layer)
def _print_debug(self, keyboard):
# debug(f'__getitem__ {key}')
if debug.enabled:
debug(f'active_layers={keyboard.active_layers}')
def activate_layer(self, keyboard, layer, as_default=False):
if as_default:
keyboard.active_layers[-1] = layer
else:
keyboard.active_layers.insert(0, layer)
if self.combo_layers:
self._activate_combo_layer(keyboard)
self._print_debug(keyboard)
def deactivate_layer(self, keyboard, layer):
# Remove the first instance of the target layer from the active list
# under almost all normal use cases, this will disable the layer (but
# preserve it if it was triggered as a default layer, etc.).
# This also resolves an issue where using DF() on a layer
# triggered by MO() and then defaulting to the MO()'s layer
# would result in no layers active.
try:
del_idx = keyboard.active_layers.index(layer)
del keyboard.active_layers[del_idx]
except ValueError:
if debug.enabled:
debug(f'_mo_released: layer {layer} not active')
if self.combo_layers:
self._deactivate_combo_layer(keyboard, layer)
self._print_debug(keyboard)
def _activate_combo_layer(self, keyboard):
if self._active_combo:
return
for combo, result in self.combo_layers.items():
matching = True
for layer in combo:
if layer not in keyboard.active_layers:
matching = False
break
if matching:
self._active_combo = combo
keyboard.active_layers.insert(0, result)
break
def _deactivate_combo_layer(self, keyboard, layer):
if self._active_combo and layer in self._active_combo:
keyboard.active_layers.remove(self.combo_layers[self._active_combo])
self._active_combo = None