feat: KO creation with checkboxes (matching egui)

- Replace ModComboBox with Ctrl/Shift/Alt checkboxes for KO mods
- Build HID bitmask from checkboxes (Ctrl=0x01, Shift=0x02, Alt=0x04)
- Add DarkCheckbox component (Dracula theme)
- Descriptive label: "When you press [From] key, output [To] key instead"
- Read all KO fields from properties (no args in callback)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Mae PUGIN 2026-04-07 11:06:32 +02:00
parent 33adcc5aa4
commit e8f4ee41a6
4 changed files with 75 additions and 19 deletions

View file

@ -1083,13 +1083,18 @@ fn main() {
let tx = bg_tx.clone();
let window_weak = window.as_weak();
window.global::<AdvancedBridge>().on_create_ko(move |trig_code, trig_mod_idx, result_code, res_mod_idx| {
window.global::<AdvancedBridge>().on_create_ko(move || {
let Some(w) = window_weak.upgrade() else { return };
let trig = trig_code as u8;
let trig_mod = mod_idx_to_byte(trig_mod_idx);
let result = result_code as u8;
let res_mod = mod_idx_to_byte(res_mod_idx);
let next_idx = w.global::<AdvancedBridge>().get_key_overrides().row_count() as u8;
let adv = w.global::<AdvancedBridge>();
let trig = adv.get_new_ko_trigger_code() as u8;
let trig_mod = (adv.get_new_ko_trig_ctrl() as u8)
| ((adv.get_new_ko_trig_shift() as u8) << 1)
| ((adv.get_new_ko_trig_alt() as u8) << 2);
let result = adv.get_new_ko_result_code() as u8;
let res_mod = (adv.get_new_ko_res_ctrl() as u8)
| ((adv.get_new_ko_res_shift() as u8) << 1)
| ((adv.get_new_ko_res_alt() as u8) << 2);
let next_idx = adv.get_key_overrides().row_count() as u8;
let cmd = logic::protocol::cmd_koset(next_idx, trig, trig_mod, result, res_mod);
let serial = serial.clone();
let tx = tx.clone();
@ -1100,9 +1105,7 @@ fn main() {
let lines = ser.query_command("KO?").unwrap_or_default();
let _ = tx.send(BgMsg::TextLines("ko".into(), lines));
});
if let Some(w) = window_weak.upgrade() {
w.global::<AppState>().set_status_text("Creating key override...".into());
}
w.global::<AppState>().set_status_text("Creating key override...".into());
});
}

View file

@ -0,0 +1,45 @@
import { Theme } from "../theme.slint";
export component DarkCheckbox inherits Rectangle {
in property <string> text;
in-out property <bool> checked: false;
height: 24px;
min-width: box.width + label.preferred-width + 10px;
HorizontalLayout {
spacing: 4px;
alignment: start;
box := Rectangle {
width: 16px;
height: 16px;
y: (parent.height - self.height) / 2;
border-radius: 3px;
border-width: 1px;
border-color: root.checked ? Theme.accent-purple : Theme.button-border;
background: root.checked ? Theme.accent-purple : Theme.button-bg;
Text {
text: root.checked ? "v" : "";
color: #282a36;
font-size: 11px;
font-weight: 700;
horizontal-alignment: center;
vertical-alignment: center;
}
}
label := Text {
text: root.text;
color: Theme.fg-primary;
font-size: 11px;
vertical-alignment: center;
}
}
TouchArea {
clicked => { root.checked = !root.checked; }
mouse-cursor: pointer;
}
}

View file

@ -171,10 +171,14 @@ export global AdvancedBridge {
// KO creation: keycodes for trigger and result
in-out property <int> new-ko-trigger-code: 0;
in-out property <string> new-ko-trigger-name: "Pick...";
in-out property <int> new-ko-trig-mod-idx: 0; // 0=None,1=Ctrl,2=Shift,...
in-out property <bool> new-ko-trig-ctrl: false;
in-out property <bool> new-ko-trig-shift: false;
in-out property <bool> new-ko-trig-alt: false;
in-out property <int> new-ko-result-code: 0;
in-out property <string> new-ko-result-name: "Pick...";
in-out property <int> new-ko-res-mod-idx: 0;
in-out property <bool> new-ko-res-ctrl: false;
in-out property <bool> new-ko-res-shift: false;
in-out property <bool> new-ko-res-alt: false;
// Leader creation
in-out property <int> new-leader-seq0-code: 0;
in-out property <string> new-leader-seq0-name: "";
@ -200,7 +204,7 @@ export global AdvancedBridge {
callback set-trilayer(int, int, int);
callback bt-switch(int);
callback create-combo(); // reads r1,c1,r2,c2,result from properties
callback create-ko(int, int, int, int); // trigger_code, trig_mod_idx, result_code, res_mod_idx
callback create-ko(); // reads all fields from properties
callback create-leader(int, int); // result_code, result_mod_idx (sequence comes from seq0-3 properties)
// TAMA
in property <string> tama-status: "";

View file

@ -2,6 +2,7 @@ import { ScrollView } from "std-widgets.slint";
import { Theme } from "../theme.slint";
import { DarkButton } from "../components/dark_button.slint";
import { DarkComboBox } from "../components/dark_combo_box.slint";
import { DarkCheckbox } from "../components/dark_checkbox.slint";
import { AdvancedBridge, AppState, ConnectionState, KeymapBridge } from "../globals.slint";
component SectionHeader inherits Text {
@ -141,25 +142,28 @@ export component TabAdvanced inherits Rectangle {
padding: 10px;
spacing: 8px;
Text { text: "Add Key Override"; color: Theme.fg-secondary; font-size: 12px; font-weight: 600; }
Text { text: "When you press [From] key, output [To] key instead"; color: Theme.fg-secondary; font-size: 10px; }
HorizontalLayout {
spacing: 8px;
alignment: start;
Text { text: "Trigger:"; color: Theme.fg-secondary; font-size: 11px; vertical-alignment: center; }
Text { text: "From:"; color: Theme.fg-secondary; font-size: 11px; vertical-alignment: center; }
PickButton { label: AdvancedBridge.new-ko-trigger-name; target: "ko-trigger"; }
Text { text: "Mod:"; color: Theme.fg-secondary; font-size: 11px; vertical-alignment: center; }
ModComboBox { current-index <=> AdvancedBridge.new-ko-trig-mod-idx; }
DarkCheckbox { text: "Ctrl"; checked <=> AdvancedBridge.new-ko-trig-ctrl; }
DarkCheckbox { text: "Shift"; checked <=> AdvancedBridge.new-ko-trig-shift; }
DarkCheckbox { text: "Alt"; checked <=> AdvancedBridge.new-ko-trig-alt; }
}
HorizontalLayout {
spacing: 8px;
alignment: start;
Text { text: "Result:"; color: Theme.fg-secondary; font-size: 11px; vertical-alignment: center; }
Text { text: "To:"; color: Theme.fg-secondary; font-size: 11px; vertical-alignment: center; }
PickButton { label: AdvancedBridge.new-ko-result-name; target: "ko-result"; }
Text { text: "Mod:"; color: Theme.fg-secondary; font-size: 11px; vertical-alignment: center; }
ModComboBox { current-index <=> AdvancedBridge.new-ko-res-mod-idx; }
DarkCheckbox { text: "Ctrl"; checked <=> AdvancedBridge.new-ko-res-ctrl; }
DarkCheckbox { text: "Shift"; checked <=> AdvancedBridge.new-ko-res-shift; }
DarkCheckbox { text: "Alt"; checked <=> AdvancedBridge.new-ko-res-alt; }
}
DarkButton {
text: "Add Key Override";
clicked => { AdvancedBridge.create-ko(AdvancedBridge.new-ko-trigger-code, AdvancedBridge.new-ko-trig-mod-idx, AdvancedBridge.new-ko-result-code, AdvancedBridge.new-ko-res-mod-idx); }
clicked => { AdvancedBridge.create-ko(); }
}
}
}