Files
promptkey/gui/VarForm.ahk
T
Spark 348036daf3 feat(gui): Quick Picker, Gestionnaire, Éditeur, formulaire de variables, Paramètres
- Picker : recherche instantanée, aperçu, navigation clavier complète,
  raccourcis actifs seulement dans sa fenêtre (HotIfWinActive)
- Gestionnaire : arbre des catégories, favoris/récents/erreurs, aperçu,
  création depuis le presse-papiers, suppression par la corbeille
- Éditeur : métadonnées, insertion/déclaration de variables synchronisées,
  validation en direct, Tester (prévisualisation résolue, sans injection)
- VarForm : un contrôle par type de variable, requis validés, Échap annule
  toute l'injection et rend le focus
2026-10-11 10:17:30 -04:00

116 lines
4.3 KiB
AutoHotkey

; VarForm.ahk — Mini-formulaire des variables manuelles d'un prompt (architecture §10.4).
; Construit dynamiquement un contrôle par variable selon son type. Échap = annulation complète.
class VarForm {
GuiObj := ""
Controls := Map() ; nom -> Map(ctrl, def)
Callback := "" ; Func(values Map) ou Func("") si annulé
PromptRef := ""
; defaults : Map nom -> valeur proposée (défaut déclaré, surchargé par les derniers choix)
Show(prompt, varDefs, defaults, callback) {
this.PromptRef := prompt
this.Callback := callback
this.Controls := Map()
if (this.GuiObj != "")
this.GuiObj.Destroy()
g := Gui("+AlwaysOnTop -MaximizeBox", prompt.Title " — paramètres")
g.SetFont("s10", "Segoe UI")
this.GuiObj := g
for def in varDefs {
name := def["name"]
label := def["label"]
type := def["type"]
defaultVal := defaults.Has(name) ? String(defaults[name]) : def["default"]
g.Add("Text", "xm w340", label (def["required"] ? " *" : ""))
ctrl := ""
switch type {
case "enum":
choices := def["choices"].Length > 0 ? def["choices"] : [defaultVal]
ctrl := g.Add("ComboBox", "xm w340", choices)
idx := 0
for i, c in choices {
if (String(c) = defaultVal) {
idx := i
break
}
}
ctrl.Value := idx > 0 ? idx : 1
case "bool":
ctrl := g.Add("CheckBox", "xm w340", label)
ctrl.Value := (defaultVal = "true" || defaultVal = "1") ? 1 : 0
; Le libellé au-dessus fait doublon pour une case : on masque le texte de la case.
ctrl.Text := "Oui"
case "multiline":
ctrl := g.Add("Edit", "xm w340 r4", defaultVal)
case "password":
ctrl := g.Add("Edit", "xm w340 Password", "")
case "date":
ctrl := g.Add("Edit", "xm w340", defaultVal != "" ? defaultVal : FormatTime(, "yyyy-MM-dd"))
default: ; text, number
ctrl := g.Add("Edit", "xm w340", defaultVal)
}
this.Controls[name] := Map("ctrl", ctrl, "def", def)
}
btnOk := g.Add("Button", "xm w160 Default", "Insérer le prompt")
btnOk.OnEvent("Click", (*) => this.Submit())
btnCancel := g.Add("Button", "x+20 w160", "Annuler (Échap)")
btnCancel.OnEvent("Click", (*) => this.Cancel())
g.OnEvent("Escape", (*) => this.Cancel())
g.OnEvent("Close", (*) => this.Cancel())
g.Show()
; Focus sur le premier contrôle.
for name, entry in this.Controls {
entry["ctrl"].Focus()
break
}
}
Submit() {
values := Map()
for name, entry in this.Controls {
ctrl := entry["ctrl"]
def := entry["def"]
type := def["type"]
val := ""
if (type = "bool") {
if (def["choices"].Length >= 2)
val := ctrl.Value ? String(def["choices"][1]) : String(def["choices"][2])
else
val := ctrl.Value ? (def["default"] != "" ? def["default"] : "oui") : ""
} else if (type = "enum") {
val := ctrl.Text
} else {
val := ctrl.Value
}
if (def["required"] && Trim(val) = "") {
ctrl.Focus()
TrayTip("La variable « " def["label"] " » est requise.", "PromptKey")
return
}
if (type = "number" && val != "" && !IsNumber(val)) {
ctrl.Focus()
TrayTip("La variable « " def["label"] " » doit être un nombre.", "PromptKey")
return
}
values[name] := val
}
cb := this.Callback
this.GuiObj.Destroy()
this.GuiObj := ""
cb(values)
}
Cancel() {
cb := this.Callback
if (this.GuiObj != "") {
this.GuiObj.Destroy()
this.GuiObj := ""
}
if (cb != "")
cb("")
}
}