Skip to content

Commit

Permalink
Merge pull request #16 from mchilli:new_keycode_macro
Browse files Browse the repository at this point in the history
Improved keycode macro
  • Loading branch information
mchilli authored Nov 8, 2024
2 parents 6630349 + ffbb406 commit abba97d
Show file tree
Hide file tree
Showing 11 changed files with 417 additions and 89 deletions.
74 changes: 40 additions & 34 deletions circuitpython/code.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
gc.enable()
supervisor.runtime.autoreload = False

VERSION = "1.4.1"
VERSION = "1.4.2"
# The file in which the settings are saved
SETTINGSFILE = "settings.json"
# The file in which the macros are saved
Expand Down Expand Up @@ -173,7 +173,7 @@ def _init_group_label(self) -> None:
padding_bottom=0,
padding_left=0,
padding_right=0,
color=0xFFFFFF,
color=0xffffff,
anchored_position=(
self.macropad.display.width // 2,
self.macropad.display.height - 10),
Expand All @@ -196,7 +196,7 @@ def _init_keys(self) -> None:
padding_bottom=1,
padding_left=4,
padding_right=4,
color=0xFFFFFF,
color=0xffffff,
anchored_position=(
(self.macropad.display.width - 2) / 2 * (i % 3) + 1,
self.macropad.display.height / 5 * (i // 3) + 2),
Expand Down Expand Up @@ -235,16 +235,32 @@ def run_macro(self, item: tuple[str, list], *args) -> None:
if isinstance(key, (int, float)):
time.sleep(key)
elif isinstance(key, str):
self.macropad.keyboard_layout.write(key)
try:
self.macropad.keyboard_layout.write(key)
except ValueError:
# if any of the characters has no keycode
pass
elif isinstance(key, dict):
if 'kc' in key:
key_name = key['kc'][1:] if key['kc'][:1] == "-" else key['kc']
key_code = getattr(Keycode, key_name.upper(), None)
if key_code:
if key['kc'][:1] != "-":
self.macropad.keyboard.press(key_code)
key_codes = [
getattr(Keycode, key_name, None)
for key_name in key['kc'].lstrip('-+').upper().split(',')
if getattr(Keycode, key_name, None) is not None
]
if key_codes:
if key['kc'] == 'RELALL':
# release all keys
self.macropad.keyboard.release_all()
elif key['kc'][0] == '+':
# tap keys
self.macropad.keyboard.press(*key_codes)
self.macropad.keyboard.release(*key_codes)
elif key['kc'][0] == '-':
# release keys
self.macropad.keyboard.release(*key_codes)
else:
self.macropad.keyboard.release(key_code)
# press keys
self.macropad.keyboard.press(*key_codes)
if 'ccc' in key:
control_code = getattr(
ConsumerControlCode, key['ccc'].upper(), None)
Expand Down Expand Up @@ -304,6 +320,11 @@ def go_to_root(self, *args) -> None:
def _update_tab(self) -> None:
""" update the current displayed group tab
"""
key_funcs = {
"macro": self.run_macro,
"group": self.open_group
}

for key in self.keys:
key.clear_props()

Expand All @@ -313,33 +334,18 @@ def _update_tab(self) -> None:
if key_id:
macro_data = json.loads(self.macro_store[str(key_id)])
key_type = macro_data["type"]

self.keys[i].type = key_type
self.keys[i].label = "" if key_type == "blank" else macro_data["label"]
self.keys[i].color = (0, 0, 0) if key_type == "blank" else macro_data["color"]
self.keys[i].set_func(self._get_key_func(key_type), (str(key_id), macro_data["content"]))

key = self.keys[i]
key.type = key_type
key.label = macro_data["label"]
key.color = macro_data["color"]
key.set_func(key_funcs.get(key_type), (str(key_id), macro_data["content"]))

self.group_label.text = group["label"]

for key in self.keys:
key.update_colors()

def _get_key_func(self, type: str) -> function:
""" get the specific function for the type
Args:
type (str): the item type
Returns:
function: return the function for type
"""
key_funcs = {
"blank": None,
"group": self.open_group
}

return key_funcs.get(type, self.run_macro)

def _update_encoder_macros(self) -> None:
""" update the rotary encoder macros defined for opened group
"""
Expand Down Expand Up @@ -429,7 +435,7 @@ def _handle_serial_data(self, payload: object) -> dict:
return

response['ACK'] = 'Macros received'
response['CONTENT'] = len(self.macro_store)
response['CONTENT'] = len(self.macro_store) - 1
return response

elif command == 'save_macros':
Expand Down Expand Up @@ -545,14 +551,14 @@ def start(self) -> None:
if key_event.pressed and not any([key.pressed for key in self.keys]):
self.keys[key_event.key_number].pressed = True
active_key = key_event.key_number
self.active_key_delay = time.monotonic()
active_key_delay = time.monotonic()

elif key_event.released and key_event.key_number == active_key:
self.keys[key_event.key_number].pressed = False
active_key = None

# if a key is pressed continuously, the function triggers again after a short delay
if active_key and time.monotonic() - self.active_key_delay > 0.75:
if active_key is not None and time.monotonic() - active_key_delay > 0.75:
self._display_on()
self.keys[active_key].call_func()

Expand Down
12 changes: 7 additions & 5 deletions circuitpython/utils/devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ def color(self, color:tuple) -> None:
def update_colors(self) -> None:
""" update the backgroundcolor and color based on type
"""
if self.type in ["blank", "group"]:
if self.type in [None, "group"]:
self._label.background_color = 0x000000
self._label.color = 0xffffff
else:
Expand All @@ -117,12 +117,14 @@ def update_colors(self) -> None:

self._set_led(self.color)

def _set_led(self, color:tuple[int, int, int]) -> None:
def _set_led(self, color:list[int, int, int] | str) -> None:
""" set and update the led color
Args:
color (tuple): the led color (R, G, B)
color (list | string): the led color (R, G, B) | rrggbb
"""
if isinstance(color, str):
color = (int(color[0:2], 16), int(color[2:4], 16), int(color[4:6], 16))
self._macropad.pixels[self._index] = color
self._macropad.pixels.show()

Expand All @@ -131,7 +133,7 @@ def clear_props(self) -> None:
"""
self._label.text = ""
self._type = None
self._color = (0, 0, 0)
self._color = '000000'
self._func = None
self._func_args = None

Expand All @@ -158,7 +160,7 @@ def _on_pressed(self) -> None:
""" Action that triggered when Key is pressed
"""
if self._func:
self._set_led((255, 255, 255))
self._set_led('ffffff')
self.call_func()

def _on_released(self) -> None:
Expand Down
8 changes: 7 additions & 1 deletion webui/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -8272,6 +8272,8 @@ readers do not read off random characters that represent icons */
--key-control-border-radius: 10px;
--dialog-button-size: 40px;
--dialog-gap: calc(var(--dialog-button-size) / 10);
--macro-visible-count: 10;
--macro-entry-min-width: 400px;
--macro-entry-height: 30px;
}

Expand Down Expand Up @@ -8602,13 +8604,14 @@ body {
border: 1px solid var(--color-grey);
box-sizing: border-box;
padding: var(--dialog-gap);
max-height: calc(var(--macro-entry-height) * 5 + var(--dialog-gap) * 6);
max-height: calc(var(--macro-entry-height) * var(--macro-visible-count) + var(--dialog-gap) * (var(--macro-visible-count) + 1));
overflow: auto;
}
.dialog-container .dialog .dialog-content .dialog-inputs .input-macros .input-sortable .macro-entry-container {
display: flex;
gap: var(--dialog-gap);
align-items: center;
min-width: var(--macro-entry-min-width);
height: var(--macro-entry-height);
padding: var(--dialog-gap);
background-color: var(--color-green);
Expand All @@ -8620,6 +8623,9 @@ body {
cursor: grab;
}
.dialog-container .dialog .dialog-content .dialog-inputs .input-macros .input-sortable .macro-entry-container .macro-entry-content {
display: flex;
flex-grow: 1;
align-items: center;
text-wrap: nowrap;
}
.dialog-container .dialog .dialog-content .dialog-inputs .input-macros .input-sortable .macro-entry-container .macro-entry-controls {
Expand Down
Loading

0 comments on commit abba97d

Please sign in to comment.