# ConfigForm **Datei:** `ConfigForm.cs` ## Verantwortung Hauptkonfigurationsfenster: zeigt alle 20 MX-Buttons und 4 Encoder, öffnet `ActionDialog` bei Klick, speichert Config + Makros auf das Board. ## Layout ``` ┌── Tasten (GroupBox) ──────────────────────────────────────────┐ │ TableLayoutPanel 4 Spalten × 5 Zeilen │ │ Jede Zelle = Button mit LED-Hintergrundfarbe + Aktionstext │ └───────────────────────────────────────────────────────────────┘ ┌── Encoder (GroupBox) ─────────────────────────────────────────┐ │ Header: SW / CW / CCW │ │ 4 Zeilen × 3 Buttons (ENC 0–3) │ └───────────────────────────────────────────────────────────────┘ [Auf Board speichern] [Ping] [Exportieren] [Importieren] [Schließen] ``` `FixedSingle`-Border, `StartPosition = CenterScreen`, kein Maximieren. ## MX-Button-Darstellung (RefreshMxButton) | Animation | Hintergrund | Textfarbe | |---|---|---| | ColorCycle | `(40, 40, 40)` dunkelgrau | Weiß | | Andere | `LedBase[mxIdx]` | Schwarz/Weiß nach Luminanz | Text = `action.Display + animName` (z.B. `"Strg+C [Blinken]"`). Luminanz-Formel für Textfarben-Kontrast: `(R*299 + G*587 + B*114) / 1000` ## mx_idx ↔ Physisches Layout ``` mx_idx = col * 5 + row (col=0..3, row=0..4) ``` Entspricht `key_id - 5` in der Firmware. Im TableLayoutPanel: Spalte=col, Zeile=row. ## Speichern (OnSave) ```csharp Task.Run(() => { _serial.SendConfig(_config); // ~300 ms Thread.Sleep(50); _serial.SendMacros(_macros); // ~250 ms InvokeOnUi(() => { /* Button-Text + Enabled zurücksetzen */ }); }); ``` Save-Button wird während der Übertragung deaktiviert, Text wechselt zu "Wird gesendet...". Save-Button ist nur aktiviert wenn Board verbunden (`_serial.IsConnected`). ## Import / Export - **Export**: `ConfigJson.Serialize(_config)` → `SaveFileDialog` → `.json`-Datei - **Import**: `OpenFileDialog` → Datei lesen → `ConfigJson.Deserialize()` → `RefreshAll()` Fehler (IO, JSON-Parse, falsche Version) werden per `MessageBox` angezeigt. ## RefreshAll Wird von `TrayApp` nach erfolgreicher Config vom Board aufgerufen (über `_configForm?.RefreshAll()`). Aktualisiert alle 20 MX-Buttons und 12 Encoder-Buttons ohne Dialog. ## Extensions (in derselben Datei) ```csharp // Statischer ToolTip für alle Controls public static void ToolTipText(this Control ctrl, string text) public static string TypeDescription(this DeviceAction a) ```