Add free-text notes per button/encoder action
Lets you record what a binding actually does (e.g. "Save in Fusion
360") alongside the auto-generated label ("Strg+S"). Notes live in a
new "note" field on every action dict, purely local like profile
names -- the firmware struct has no room for strings, and
pack_config/unpack_config already only touch type/data so the extra
key round-trips harmlessly.
Two things had to be handled carefully: changing a button's key/type
must not wipe its note (all set_button_*/set_encoder_* setters and the
edit dialog now carry the previous note forward), and re-reading from
the board must not erase notes either, since the firmware doesn't know
about them -- versapad_combined.merge_notes() restores them onto the
freshly-fetched state by button/encoder index.
Editable via the Programmiermodus dialog (new text field), visible on
both the desktop card (grown from 84 to 114px to fit it) and the
browser view. MCP server gets set_button_note()/set_encoder_note() so
notes can be set programmatically too.
This commit is contained in:
parent
9f0ae12794
commit
4b5da69174
8 changed files with 173 additions and 41 deletions
|
|
@ -54,7 +54,7 @@ OK_GREEN = "#3ecf6e"
|
|||
WARN_RED = "#e0895a"
|
||||
|
||||
POLL_MS = 1500
|
||||
CARD_W, CARD_H = 150, 84
|
||||
CARD_W, CARD_H = 150, 114
|
||||
SERIAL_POLL_S = 1.5
|
||||
SERIAL_IDLE_S = 3.0
|
||||
|
||||
|
|
@ -97,9 +97,11 @@ Buttons setzen (profile 0-2, index 0-19):
|
|||
set_button_profile_switch(profile, index, target)
|
||||
set_button_none(profile, index)
|
||||
set_button_led(profile, index, r, g, b, anim, period_ms)
|
||||
set_button_note(profile, index, note) freie Notiz, was der Button tut
|
||||
|
||||
Encoder setzen (index 0-3, field 'sw'/'cw'/'ccw'):
|
||||
set_encoder_key / _consumer / _macro / _profile_switch / _none(...)
|
||||
set_encoder_note(profile, index, field, note)
|
||||
|
||||
Makro:
|
||||
set_macro(slot, steps) steps=[{"key":"Z","modifiers":["Strg"]}, ...]
|
||||
|
|
@ -460,7 +462,9 @@ class VersaPadViewer(tk.Tk):
|
|||
macro_slots = vproto.unpack_macros(raw_macros)
|
||||
|
||||
names = self.combined["profile_names"] if self.combined else None
|
||||
self.combined = vcomb.from_binary(cfg_dict, macro_slots, profile_names=names)
|
||||
previous = self.combined
|
||||
self.combined = vcomb.merge_notes(
|
||||
vcomb.from_binary(cfg_dict, macro_slots, profile_names=names), previous)
|
||||
self.profile = self.combined["active_profile"]
|
||||
self._status("vom Board geladen", True)
|
||||
self._update_tab_labels()
|
||||
|
|
@ -639,12 +643,16 @@ class VersaPadViewer(tk.Tk):
|
|||
tk.Label(card, text=label, bg=CARD_BG, fg=TEXT_EMPTY if empty else TEXT,
|
||||
font=("Segoe UI", 10, "normal" if empty else "bold"),
|
||||
wraplength=CARD_W - 20, justify="left", anchor="nw").place(
|
||||
x=10, y=26, width=CARD_W - 20, height=36)
|
||||
x=10, y=26, width=CARD_W - 20, height=30)
|
||||
|
||||
tk.Label(card, text=btn["note"], bg=CARD_BG, fg=TEXT_DIM,
|
||||
font=("Segoe UI", 8), wraplength=CARD_W - 20, justify="left", anchor="nw").place(
|
||||
x=10, y=58, width=CARD_W - 20, height=34)
|
||||
|
||||
anim = "" if empty else vp.ANIM_LABELS.get(btn["led"]["anim"], btn["led"]["anim"])
|
||||
tk.Label(card, text=anim, bg=CARD_BG, fg=TEXT_DIM,
|
||||
font=("Segoe UI", 7), anchor="sw").place(
|
||||
x=10, y=CARD_H - 20, width=CARD_W - 20, height=14)
|
||||
x=10, y=CARD_H - 18, width=CARD_W - 20, height=14)
|
||||
|
||||
if editable:
|
||||
card.configure(cursor="hand2")
|
||||
|
|
@ -661,17 +669,25 @@ class VersaPadViewer(tk.Tk):
|
|||
inner.pack(fill="both", expand=True, padx=10, pady=8)
|
||||
tk.Label(inner, text=f"Encoder {enc['index']}", bg=CARD_BG, fg=TEXT_DIM,
|
||||
font=("Segoe UI", 8, "bold")).pack(anchor="w", pady=(0, 4))
|
||||
for key, field, val in (("Druck", "sw", enc["sw_label"]), ("CW", "cw", enc["cw_label"]),
|
||||
("CCW", "ccw", enc["ccw_label"])):
|
||||
for key, field, val, note in (("Druck", "sw", enc["sw_label"], enc["sw_note"]),
|
||||
("CW", "cw", enc["cw_label"], enc["cw_note"]),
|
||||
("CCW", "ccw", enc["ccw_label"], enc["ccw_note"])):
|
||||
row = tk.Frame(inner, bg=CARD_BG)
|
||||
row.pack(fill="x", pady=1)
|
||||
tk.Label(row, text=key, bg=CARD_BG, fg=TEXT_DIM, font=("Segoe UI", 8)).pack(side="left")
|
||||
tk.Label(row, text=val or "—", bg=CARD_BG, fg=TEXT, font=("Segoe UI", 8, "bold")).pack(side="right")
|
||||
row.pack(fill="x", pady=(1, 4))
|
||||
top = tk.Frame(row, bg=CARD_BG)
|
||||
top.pack(fill="x")
|
||||
tk.Label(top, text=key, bg=CARD_BG, fg=TEXT_DIM, font=("Segoe UI", 8)).pack(side="left")
|
||||
tk.Label(top, text=val or "—", bg=CARD_BG, fg=TEXT, font=("Segoe UI", 8, "bold")).pack(side="right")
|
||||
note_label = tk.Label(row, text=note, bg=CARD_BG, fg=TEXT_DIM, font=("Segoe UI", 7),
|
||||
wraplength=150, justify="left", anchor="w")
|
||||
note_label.pack(fill="x")
|
||||
if editable:
|
||||
row.configure(cursor="hand2")
|
||||
handler = lambda e, ei=enc["index"], f=field, lbl=key: self._edit_encoder_action(ei, f, lbl)
|
||||
row.bind("<Button-1>", handler)
|
||||
for child in row.winfo_children():
|
||||
top.bind("<Button-1>", handler)
|
||||
note_label.bind("<Button-1>", handler)
|
||||
for child in top.winfo_children():
|
||||
child.bind("<Button-1>", handler)
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue