KeSp_controller/ui/tabs/tab_macros.slint
Mae PUGIN 3e54361d0d refactor: Modularize main.rs (2478 → 58 lines), flat architecture
Split monolithic main.rs into domain modules:
- context.rs: AppContext shared state, BgMsg enum, serial_spawn helper
- models.rs: UI model builders, keycap labels, key entries, layout preview
- config.rs: keyboard config export/import via binary protocol
- dispatch.rs: BgMsg handler + WPM/layout timers
- keymap.rs: key selection, layer switch/rename, heatmap toggle
- key_selector.rs: dispatch_keycode router, apply_keycode, hex/MT/LT
- macros.rs: macro CRUD, shortcut presets, step builder
- advanced.rs: combos, KO, leaders, tap dance, BT, tama, autoshift
- settings.rs: OTA flash, config backup, keyboard layout
- flasher.rs: ESP32 bootloader flash
- layout.rs: layout JSON preview, load/export
- connection.rs: serial connect/disconnect, tab auto-refresh
- stats.rs: stats refresh

Rename logic/ → protocol/ with cleaner file names.
Remove unused original-src/ directory.
Fix DarkLineEdit double styling, add rename popup, macro shortcuts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 12:02:22 +02:00

178 lines
7.4 KiB
Text

import { ScrollView } from "std-widgets.slint";
import { DarkLineEdit } from "../components/dark_line_edit.slint";
import { Theme } from "../theme.slint";
import { DarkButton } from "../components/dark_button.slint";
import { DarkComboBox } from "../components/dark_combo_box.slint";
import { MacroBridge, AppState, ConnectionState, KeymapBridge } from "../globals.slint";
export component TabMacros inherits Rectangle {
background: Theme.bg-primary;
VerticalLayout {
padding: 16px;
spacing: 12px;
// Header
HorizontalLayout {
spacing: 8px;
Text { text: "Macros"; color: Theme.fg-primary; font-size: 20px; font-weight: 700; vertical-alignment: center; }
Rectangle { horizontal-stretch: 1; }
DarkButton {
text: "Refresh";
enabled: AppState.connection == ConnectionState.connected;
clicked => { MacroBridge.refresh-macros(); }
}
}
// New macro builder
Rectangle {
background: Theme.bg-secondary;
border-radius: 8px;
VerticalLayout {
padding: 12px;
spacing: 10px;
Text { text: "Add / Edit Macro"; color: Theme.accent-cyan; font-size: 13px; font-weight: 600; }
HorizontalLayout {
spacing: 8px;
Text { text: "Slot:"; color: Theme.fg-secondary; font-size: 12px; vertical-alignment: center; }
Text { text: "#" + MacroBridge.new-slot-idx; color: Theme.accent-purple; font-size: 12px; font-weight: 600; vertical-alignment: center; }
Text { text: "Name:"; color: Theme.fg-secondary; font-size: 12px; vertical-alignment: center; }
DarkLineEdit {
horizontal-stretch: 1;
text <=> MacroBridge.new-name;
placeholder-text: "macro name";
}
}
// Steps display
Text { text: "Steps:"; color: Theme.fg-secondary; font-size: 12px; }
// Show added steps as tags
HorizontalLayout {
spacing: 4px;
height: 30px;
for step in MacroBridge.new-steps : Rectangle {
width: self.preferred-width + 12px;
preferred-width: step-text.preferred-width;
height: 26px;
border-radius: 4px;
background: step.is-delay ? Theme.accent-orange : Theme.accent-purple;
step-text := Text {
text: step.label;
color: Theme.fg-primary;
font-size: 10px;
horizontal-alignment: center;
vertical-alignment: center;
}
}
if MacroBridge.new-steps.length == 0 : Text {
text: "(empty - add keys and delays below)";
color: Theme.fg-secondary;
font-size: 11px;
vertical-alignment: center;
}
}
// Action buttons
HorizontalLayout {
spacing: 6px;
alignment: start;
DarkButton {
text: "Add Key";
clicked => {
KeymapBridge.selector-target = "macro-step";
KeymapBridge.key-selector-open = true;
}
}
DarkButton { text: "T 50ms"; clicked => { MacroBridge.add-delay-step(50); } }
DarkButton { text: "T 100ms"; clicked => { MacroBridge.add-delay-step(100); } }
DarkButton { text: "T 200ms"; clicked => { MacroBridge.add-delay-step(200); } }
Rectangle { horizontal-stretch: 1; }
DarkButton { text: "Undo"; clicked => { MacroBridge.remove-last-step(); } }
DarkButton { text: "Clear"; clicked => { MacroBridge.clear-steps(); } }
}
// Common shortcuts
HorizontalLayout {
spacing: 6px;
alignment: start;
Text { text: "Shortcuts:"; color: Theme.fg-secondary; font-size: 11px; vertical-alignment: center; }
DarkButton { text: "Ctrl+C"; clicked => { MacroBridge.add-shortcut("ctrl+c"); } }
DarkButton { text: "Ctrl+V"; clicked => { MacroBridge.add-shortcut("ctrl+v"); } }
DarkButton { text: "Ctrl+X"; clicked => { MacroBridge.add-shortcut("ctrl+x"); } }
DarkButton { text: "Ctrl+Z"; clicked => { MacroBridge.add-shortcut("ctrl+z"); } }
DarkButton { text: "Ctrl+Y"; clicked => { MacroBridge.add-shortcut("ctrl+y"); } }
DarkButton { text: "Ctrl+S"; clicked => { MacroBridge.add-shortcut("ctrl+s"); } }
DarkButton { text: "Ctrl+A"; clicked => { MacroBridge.add-shortcut("ctrl+a"); } }
DarkButton { text: "Alt+F4"; clicked => { MacroBridge.add-shortcut("alt+f4"); } }
}
// Save
HorizontalLayout {
spacing: 8px;
alignment: start;
DarkButton {
text: "Save Macro";
enabled: AppState.connection == ConnectionState.connected;
clicked => { MacroBridge.save-macro(); }
}
if MacroBridge.new-steps-text != "" : Text {
text: MacroBridge.new-steps-text;
color: Theme.fg-secondary;
font-size: 10px;
vertical-alignment: center;
overflow: elide;
}
}
}
}
// Macro list
ScrollView {
vertical-stretch: 1;
VerticalLayout {
spacing: 4px;
if MacroBridge.macros.length == 0 : Text {
text: "No macros configured";
color: Theme.fg-secondary;
font-size: 11px;
}
for macro in MacroBridge.macros : Rectangle {
background: Theme.bg-secondary;
border-radius: 4px;
height: 36px;
HorizontalLayout {
padding-left: 8px;
padding-right: 8px;
spacing: 8px;
Text { text: "#" + macro.slot; color: Theme.accent-purple; font-size: 12px; vertical-alignment: center; width: 30px; }
Text { text: macro.name; color: Theme.fg-primary; font-size: 12px; font-weight: 600; vertical-alignment: center; width: 100px; }
Text { text: macro.steps; color: Theme.fg-secondary; font-size: 10px; vertical-alignment: center; horizontal-stretch: 1; overflow: elide; }
DarkButton { text: "Del"; clicked => { MacroBridge.delete-macro(macro.slot); } }
}
}
}
}
}
}