Files
DSC-Configuration-Compiler/Compiler.ps1
2026-04-14 15:01:50 +02:00

3994 lines
145 KiB
PowerShell

using namespace System.Windows.Forms
using namespace System.Drawing
#region Class Definition
class BaseComponent {
static [SettingsManager] $SettingsManager
static [LogManager] $LogManager
static [AccessibilityManager] $AccessibilityManager
static [void] InitializeShared([SettingsManager]$SettingsManager, [LogManager]$LogManager) {
[BaseComponent]::SettingsManager = $SettingsManager
[BaseComponent]::LogManager = $LogManager
[BaseComponent]::AccessibilityManager = [AccessibilityManager]::new($SettingsManager, $LogManager)
}
[object] GetSetting([string]$key) {
return [BaseComponent]::SettingsManager.Get($key)
}
[object] GetSetting([string]$key, [object]$defaultValue) {
return [BaseComponent]::SettingsManager.Get($key, $defaultValue)
}
[void] SetSetting([string]$key, [object]$value) {
[BaseComponent]::SettingsManager.Set($key, $value)
}
[void] LogInfo([string]$message) {
if ($null -ne [BaseComponent]::LogManager) {
[BaseComponent]::LogManager.Info($message)
}
}
}
class SettingsManager {
[System.String]$SettingsPath
[System.Collections.Hashtable]$Settings
SettingsManager([System.String]$appName) {
$appDataPath = [Environment]::GetFolderPath('ApplicationData')
$appFolder = Join-Path $appDataPath $appName
if (-not (Test-Path $appFolder)) {
New-Item -Path $appFolder -ItemType Directory -Force | Out-Null
}
$this.SettingsPath = Join-Path $appFolder "settings.json"
$this.Load()
$this.EnsureDefaults()
}
[void] Load() {
if (Test-Path $this.SettingsPath) {
try {
$json = Get-Content $this.SettingsPath -Raw | ConvertFrom-Json
$this.Settings = @{}
foreach ($prop in $json.PSObject.Properties) {
$this.Settings[$prop.Name] = $prop.Value
}
} catch {
Write-Warning "Fehler beim Laden der Settings: $_"
$this.Settings = @{}
}
} else {
$this.Settings = @{}
}
}
# NEU: Stellt sicher, dass Standard-Einstellungen vorhanden sind
[void] EnsureDefaults() {
if (-not $this.Settings.ContainsKey("MenuStructure")) {
$this.Settings["MenuStructure"] = $this.GetDefaultMenuStructure()
$this.Save()
}
if (-not $this.Settings.ContainsKey("WindowWidth")) {
$this.Settings["WindowWidth"] = 1024
}
if (-not $this.Settings.ContainsKey("WindowHeight")) {
$this.Settings["WindowHeight"] = 768
}
if (-not $this.Settings.ContainsKey("SplitterDistance")) {
$this.Settings["SplitterDistance"] = 200
}
if (-not $this.Settings.ContainsKey("TemplatePath")) {
$this.Settings["TemplatePath"] = (Join-Path -Path $this.Settings["RootPath"] -ChildPath "Templates")
}
if (-not $this.Settings.ContainsKey("FunctionsPath")) {
$this.Settings["FunctionsPath"] = (Join-Path -Path $this.Settings["RootPath"] -ChildPath "Functions")
}
if (-not $this.Settings.ContainsKey("DeploymentPath")) {
$this.Settings["DeploymentPath"] = (Join-Path -Path $this.Settings["RootPath"] -ChildPath "Deployments")
}
}
# NEU: Standard-Menüstruktur
[object] GetDefaultMenuStructure() {
return @(
@{
Name = "Datei"
Text = "Datei"
Items = @(
@{ Name = "Import"; Text = "Import" }
@{ Name = "Export"; Text = "Export" }
@{ Name = "Refresh"; Text = "Aktualisieren" }
@{ Type = "Separator" }
@{ Name = "Exit"; Text = "Beenden" }
)
},
@{
Name = "Settings"
Text = "Einstellungen"
Items = @(
@{ Name = "OpenFolder"; Text = "Ordner wählen..." }
@{ Name = "ResetMenu"; Text = "Menü zurücksetzen" }
)
},
@{
Name = "TemplateDesigner"
Text = "Template Designer"
},
@{
Name = "Help"
Text = "Hilfe"
Items = @(
@{ Name = "About"; Text = "Über..." }
)
}
)
}
[void] Save() {
try {
$this.Settings | ConvertTo-Json -Depth 10 | Set-Content $this.SettingsPath -Encoding UTF8
} catch {
Write-Warning "Fehler beim Speichern der Settings: $_"
}
}
[object] Get([System.String]$key) {
return $this.Settings[$key]
}
[object] Get([System.String]$key, [object]$defaultValue) {
if ($this.Settings.ContainsKey($key)) {
return $this.Settings[$key]
}
return $defaultValue
}
[void] Set([System.String]$key, [object]$value) {
$this.Settings[$key] = $value
$this.Save()
}
[bool] Contains([System.String]$key) {
return $this.Settings.ContainsKey($key)
}
[void] Remove([System.String]$key) {
if ($this.Settings.ContainsKey($key)) {
$this.Settings.Remove($key)
$this.Save()
}
}
[System.Collections.Hashtable] GetAll() {
return $this.Settings
}
# NEU: Holt die Menüstruktur
[System.Array] GetMenuStructure() {
if ($this.Settings.ContainsKey("MenuStructure")) {
# Konvertiere PSCustomObject zurück zu Hashtable
return $this.ConvertToHashtable($this.Settings["MenuStructure"])
}
return $this.GetDefaultMenuStructure()
}
# NEU: Setzt eine neue Menüstruktur
[void] SetMenuStructure([System.Array]$menuStructure) {
$this.Settings["MenuStructure"] = $menuStructure
$this.Save()
}
# NEU: Setzt Menü auf Standard zurück
[void] ResetMenuStructure() {
$this.Settings["MenuStructure"] = $this.GetDefaultMenuStructure()
$this.Save()
}
# Hilfsfunktion: Konvertiert PSCustomObject zu Hashtable (für JSON-Deserialisierung)
hidden [object] ConvertToHashtable([object]$obj) {
if ($obj -is [System.Management.Automation.PSCustomObject]) {
$hash = @{}
foreach ($property in $obj.PSObject.Properties) {
$hash[$property.Name] = $this.ConvertToHashtable($property.Value)
}
return $hash
}
elseif ($obj -is [System.Array] -or $obj -is [System.Collections.ArrayList]) {
$array = @()
foreach ($item in $obj) {
$array += $this.ConvertToHashtable($item)
}
return $array
}
else {
return $obj
}
}
}
class StateManager {
[System.Collections.Hashtable] $State = @{}
[System.Collections.ArrayList] $Buttons = @()
[System.Collections.Hashtable] $MenuItems = @{}
[System.Collections.ArrayList] $Forms = @()
# Registriert einen Button mit seiner Bedingung
[void] RegisterButton([ButtonBuilder]$buttonBuilder) {
$this.Buttons.Add($buttonBuilder) | Out-Null
}
# NEU: Registriert ein Menü-Item
[void] RegisterMenuItem([string]$menuName, [MenuBuilder]$menuBuilder) {
$this.MenuItems[$menuName] = $menuBuilder
}
# Registriert einen Button mit seiner Bedingung
[void] RegisterForm([System.Object]$form) {
$this.Forms.Add($form) | Out-Null
}
# Setzt einen State-Wert und aktualisiert alle Buttons und Menüs
[void] SetState([string]$key, [object]$value) {
$this.State[$key] = $value
$this.UpdateAll()
}
[void] SetStates([hashtable]$states) {
foreach ($key in $states.Keys) {
$this.State[$key] = $states[$key]
}
$this.UpdateAll()
}
# Holt einen State-Wert
[object] GetState([string]$key) {
return $this.State[$key]
}
[hashtable] GetAllStates() {
return $this.State.Clone()
}
# Aktualisiert alle registrierten Buttons
[void] UpdateAllButtons() {
foreach ($button in $this.Buttons) {
$button.UpdateEnabledState()
}
}
# NEU: Aktualisiert alle registrierten Menü-Items
[void] UpdateAllMenuItems() {
foreach ($menuName in $this.MenuItems.Keys) {
$this.MenuItems[$menuName].UpdateMenuItemState($menuName)
}
}
# Aktualisiert alle registrierten Buttons
[void] UpdateAllForms() {
foreach ($form in $this.Forms) {
$form.UpdateVisibleState()
}
}
# NEU: Aktualisiert alles (Buttons + Menüs)
[void] UpdateAll() {
$this.UpdateAllButtons()
$this.UpdateAllMenuItems()
$this.UpdateAllForms()
}
}
class LogManager {
[System.String]$LogPath
[bool]$EnableConsole = $false
LogManager([System.String]$appName) {
$appDataPath = [Environment]::GetFolderPath('ApplicationData')
$logFolder = Join-Path $appDataPath "$appName\Logs"
if (-not (Test-Path $logFolder)) {
New-Item -Path $logFolder -ItemType Directory -Force | Out-Null
}
$timestamp = Get-Date -Format "yyyyMMdd"
$this.LogPath = Join-Path $logFolder "log_$timestamp.txt"
}
[void] Info([string]$message) {
$this.Write("INFO", $message)
}
[void] Warning([string]$message) {
$this.Write("WARN", $message)
}
[void] Error([string]$message) {
$this.Write("ERROR", $message)
}
hidden [void] Write([string]$level, [string]$message) {
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$logLine = "[$timestamp] [$level] $message"
Add-Content -Path $this.LogPath -Value $logLine
if ($this.EnableConsole) {
Write-Host $logLine
}
}
}
class AccessibilityManager {
[SettingsManager] $SettingsManager
[LogManager] $LogManager
[System.Collections.ArrayList] $FontControls = @()
[System.Collections.ArrayList] $Forms = @()
[System.Collections.ArrayList] $LayoutContainers = @()
[hashtable] $AccessibilitySettings = @{}
AccessibilityManager([SettingsManager]$SettingsManager, [LogManager]$LogManager) {
$this.SettingsManager = $SettingsManager
$this.LogManager = $LogManager
$this.InitializeDefaults()
}
# Initialisiert Standard-Accessibility-Einstellungen
[void] InitializeDefaults() {
$this.AccessibilitySettings = @{
FontSize = @{ Min = 6; Max = 32; Default = 9; Step = 1 }
FontSizeStep = @{ Min = 1; Max = 5; Default = 1 }
HighContrast = @{ Default = $false }
KeyboardShortcuts = @{ Default = $true }
ScreenReaderSupport = @{ Default = $false }
}
# Stelle sicher, dass alle Settings existieren
foreach ($key in $this.AccessibilitySettings.Keys) {
if (-not $this.SettingsManager.Contains($key)) {
$this.SettingsManager.Set($key, $this.AccessibilitySettings[$key].Default)
}
}
}
# Registriert ein Form für Accessibility-Features
[void] RegisterForm([System.Windows.Forms.Form]$form) {
if (-not $this.Forms.Contains($form)) {
$this.Forms.Add($form) | Out-Null
$this.AttachMouseWheelHandler($form)
$this.AttachKeyboardShortcuts($form)
$this.LogManager.Info("Form registriert für Accessibility-Features")
}
}
# Registriert Container für automatisches Layout-Update
[void] RegisterLayoutContainer([System.Windows.Forms.Control]$container) {
if (-not $this.LayoutContainers.Contains($container)) {
$this.LayoutContainers.Add($container) | Out-Null
$this.LogManager.Info("Layout-Container registriert: $($container.GetType().Name)")
}
}
# Registriert ein Control für Font-Updates
[void] RegisterFontControl([System.Windows.Forms.Control]$control) {
if (-not $this.FontControls.Contains($control)) {
$this.FontControls.Add($control) | Out-Null
$this.ApplyFontSize($control)
}
}
# Registriert mehrere Controls
[void] RegisterFontControls([System.Windows.Forms.Control[]]$controls) {
foreach ($control in $controls) {
$this.RegisterFontControl($control)
}
}
# Registriert alle Controls eines Forms/Containers rekursiv
[void] RegisterAllControls([System.Windows.Forms.Control]$container) {
# Registriere das Container-Control selbst (wenn es Text hat)
if ($container.GetType().GetProperty("Font") -ne $null) {
$this.RegisterFontControl($container)
}
# Durchlaufe alle Child-Controls rekursiv
foreach ($control in $container.Controls) {
$this.RegisterAllControls($control)
}
$this.LogManager.Info("Alle Controls von '$($container.GetType().Name)' registriert (Total: $($this.FontControls.Count))")
}
# Optional: Registriert nur bestimmte Control-Typen
[void] RegisterControlsByType([System.Windows.Forms.Control]$container, [Type[]]$types) {
foreach ($control in $container.Controls) {
if ($types -contains $control.GetType()) {
$this.RegisterFontControl($control)
}
# Rekursiv durch Child-Controls
if ($control.Controls.Count -gt 0) {
$this.RegisterControlsByType($control, $types)
}
}
}
# Fügt MouseWheel-Handler für Strg + Mausrad hinzu
hidden [void] AttachMouseWheelHandler([System.Windows.Forms.Form]$form) {
$form.Add_MouseWheel({
param($sender, $e)
if ([System.Windows.Forms.Control]::ModifierKeys -eq [System.Windows.Forms.Keys]::Control) {
$delta = if ($e.Delta -gt 0) { 1 } else { -1 }
[BaseComponent]::AccessibilityManager.ChangeFontSize($delta)
$e.Handled = $true
}
}.GetNewClosure())
}
# Fügt Tastatur-Shortcuts hinzu
hidden [void] AttachKeyboardShortcuts([System.Windows.Forms.Form]$form) {
$form.KeyPreview = $true
$form.Add_KeyDown({
param($sender, $e)
# Strg + 0: Reset auf Standard
if ($e.Control -and $e.KeyCode -eq [System.Windows.Forms.Keys]::D0) {
[BaseComponent]::AccessibilityManager.ResetFontSize()
$e.Handled = $true
}
# Strg + Plus: Größer
if ($e.Control -and ($e.KeyCode -eq [System.Windows.Forms.Keys]::Add -or $e.KeyCode -eq [System.Windows.Forms.Keys]::Oemplus)) {
[BaseComponent]::AccessibilityManager.ChangeFontSize(1)
$e.Handled = $true
}
# Strg + Minus: Kleiner
if ($e.Control -and ($e.KeyCode -eq [System.Windows.Forms.Keys]::Subtract -or $e.KeyCode -eq [System.Windows.Forms.Keys]::OemMinus)) {
[BaseComponent]::AccessibilityManager.ChangeFontSize(-1)
$e.Handled = $true
}
# F11: High Contrast Toggle (optional)
if ($e.KeyCode -eq [System.Windows.Forms.Keys]::F11) {
[BaseComponent]::AccessibilityManager.ToggleHighContrast()
$e.Handled = $true
}
}.GetNewClosure())
}
# Ändert die Schriftgröße
[void] ChangeFontSize([int]$delta) {
$settings = $this.AccessibilitySettings["FontSize"]
$currentSize = $this.SettingsManager.Get("FontSize", $settings.Default)
$step = $this.SettingsManager.Get("FontSizeStep", 1)
$newSize = $currentSize + ($delta * $step)
# Begrenzung
if ($newSize -lt $settings.Min) { $newSize = $settings.Min }
if ($newSize -gt $settings.Max) { $newSize = $settings.Max }
if ($newSize -ne $currentSize) {
$this.SettingsManager.Set("FontSize", $newSize)
$this.UpdateAllFonts()
$this.LogManager.Info("Schriftgröße geändert: $currentSize -> $newSize")
}
}
# Setzt Schriftgröße zurück
[void] ResetFontSize() {
$defaultSize = $this.AccessibilitySettings["FontSize"].Default
$this.SettingsManager.Set("FontSize", $defaultSize)
$this.UpdateAllFonts()
$this.LogManager.Info("Schriftgröße zurückgesetzt auf: $defaultSize")
}
# Wendet Schriftgröße auf ein Control an
hidden [void] ApplyFontSize([System.Windows.Forms.Control]$control) {
$fontSize = $this.SettingsManager.Get("FontSize", 9)
try {
$control.Font = New-Object System.Drawing.Font($control.Font.FontFamily, $fontSize)
} catch {
$this.LogManager.Warning("Fehler beim Setzen der Schriftgröße für Control: $_")
}
}
# Aktualisiert alle registrierten Controls
[void] UpdateAllFonts() {
foreach ($control in $this.FontControls) {
if ($null -ne $control -and -not $control.IsDisposed) {
$this.ApplyFontSize($control)
}
}
$this.UpdateAllLayouts()
}
# Aktualisiert das Layout aller registrierten Container
hidden [void] UpdateAllLayouts() {
foreach ($container in $this.LayoutContainers) {
if ($null -ne $container -and -not $container.IsDisposed) {
# GroupBoxes: AutoSize aktivieren
if ($container -is [System.Windows.Forms.GroupBox]) {
$container.AutoSize = $true
$container.AutoSizeMode = 'GrowAndShrink'
}
# FlowLayoutPanel: PerformLayout erzwingen
if ($container -is [System.Windows.Forms.FlowLayoutPanel]) {
foreach ($child in $container.Controls) {
if ($child -is [System.Windows.Forms.GroupBox]) {
$child.AutoSize = $true
$child.AutoSizeMode = 'GrowAndShrink'
# Breite anpassen
$child.Width = $container.ClientSize.Width - 20
}
}
$container.PerformLayout()
$container.Refresh()
}
# Panel: PerformLayout
if ($container -is [System.Windows.Forms.Panel]) {
$container.PerformLayout()
}
}
}
$this.LogManager.Info("Layout-Update abgeschlossen")
}
# Schaltet High Contrast Modus um
[void] ToggleHighContrast() {
$currentState = $this.SettingsManager.Get("HighContrast", $false)
$newState = -not $currentState
$this.SettingsManager.Set("HighContrast", $newState)
$this.ApplyHighContrast($newState)
$this.LogManager.Info("High Contrast: $newState")
}
# Wendet High Contrast auf alle Forms an
hidden [void] ApplyHighContrast([bool]$enabled) {
foreach ($form in $this.Forms) {
if ($null -ne $form -and -not $form.IsDisposed) {
if ($enabled) {
# Form-Hintergrund
$form.BackColor = [System.Drawing.Color]::Black
$form.ForeColor = [System.Drawing.Color]::White
# NEU: Rekursiv alle Controls anpassen
$this.ApplyHighContrastToControls($form, $enabled)
} else {
$form.BackColor = [System.Drawing.SystemColors]::Control
$form.ForeColor = [System.Drawing.SystemColors]::ControlText
# NEU: Rekursiv alle Controls zurücksetzen
$this.ApplyHighContrastToControls($form, $enabled)
}
}
}
}
# NEU: Wendet High Contrast rekursiv auf alle Controls an
hidden [void] ApplyHighContrastToControls([System.Windows.Forms.Control]$control, [bool]$enabled) {
if ($enabled) {
# Schwarzer Hintergrund → Weiße Schrift
switch ($control.GetType().Name) {
'Panel' {
$control.BackColor = [System.Drawing.Color]::Black
$control.ForeColor = [System.Drawing.Color]::White
}
'FlowLayoutPanel' {
$control.BackColor = [System.Drawing.Color]::Black
$control.ForeColor = [System.Drawing.Color]::White
}
'GroupBox' {
$control.BackColor = [System.Drawing.Color]::Black
$control.ForeColor = [System.Drawing.Color]::White
}
'Label' {
$control.ForeColor = [System.Drawing.Color]::White
# Transparent oder schwarz
if ($control.BackColor -ne [System.Drawing.Color]::Transparent) {
$control.BackColor = [System.Drawing.Color]::Black
}
}
'Button' {
$control.BackColor = [System.Drawing.Color]::FromArgb(40, 40, 40)
$control.ForeColor = [System.Drawing.Color]::White
$control.FlatStyle = 'Flat'
}
'TextBox' {
$control.BackColor = [System.Drawing.Color]::FromArgb(30, 30, 30)
$control.ForeColor = [System.Drawing.Color]::White
}
'TreeView' {
$control.BackColor = [System.Drawing.Color]::FromArgb(20, 20, 20)
$control.ForeColor = [System.Drawing.Color]::White
}
'ListBox' {
$control.BackColor = [System.Drawing.Color]::FromArgb(20, 20, 20)
$control.ForeColor = [System.Drawing.Color]::White
}
'DataGridView' {
$control.BackgroundColor = [System.Drawing.Color]::Black
$control.ForeColor = [System.Drawing.Color]::White
$control.DefaultCellStyle.BackColor = [System.Drawing.Color]::FromArgb(30, 30, 30)
$control.DefaultCellStyle.ForeColor = [System.Drawing.Color]::White
$control.ColumnHeadersDefaultCellStyle.BackColor = [System.Drawing.Color]::FromArgb(50, 50, 50)
$control.ColumnHeadersDefaultCellStyle.ForeColor = [System.Drawing.Color]::White
}
'TabControl' {
$control.BackColor = [System.Drawing.Color]::Black
$control.ForeColor = [System.Drawing.Color]::White
}
'TabPage' {
$control.BackColor = [System.Drawing.Color]::Black
$control.ForeColor = [System.Drawing.Color]::White
}
}
} else {
# Zurück zu Standard-Farben
switch ($control.GetType().Name) {
'Panel' {
$control.BackColor = [System.Drawing.SystemColors]::Control
$control.ForeColor = [System.Drawing.SystemColors]::ControlText
}
'FlowLayoutPanel' {
$control.BackColor = [System.Drawing.SystemColors]::Control
$control.ForeColor = [System.Drawing.SystemColors]::ControlText
}
'GroupBox' {
$control.BackColor = [System.Drawing.SystemColors]::Control
$control.ForeColor = [System.Drawing.SystemColors]::ControlText
}
'Label' {
$control.ForeColor = [System.Drawing.SystemColors]::ControlText
if ($control.BackColor -ne [System.Drawing.Color]::Transparent) {
$control.BackColor = [System.Drawing.SystemColors]::Control
}
}
'Button' {
$control.BackColor = [System.Drawing.SystemColors]::Control
$control.ForeColor = [System.Drawing.SystemColors]::ControlText
$control.FlatStyle = 'Standard'
}
'TextBox' {
$control.BackColor = [System.Drawing.SystemColors]::Window
$control.ForeColor = [System.Drawing.SystemColors]::WindowText
}
'TreeView' {
$control.BackColor = [System.Drawing.SystemColors]::Window
$control.ForeColor = [System.Drawing.SystemColors]::WindowText
}
'ListBox' {
$control.BackColor = [System.Drawing.SystemColors]::Window
$control.ForeColor = [System.Drawing.SystemColors]::WindowText
}
'DataGridView' {
$control.BackgroundColor = [System.Drawing.SystemColors]::Control
$control.ForeColor = [System.Drawing.SystemColors]::ControlText
$control.DefaultCellStyle.BackColor = [System.Drawing.SystemColors]::Window
$control.DefaultCellStyle.ForeColor = [System.Drawing.SystemColors]::WindowText
$control.ColumnHeadersDefaultCellStyle.BackColor = [System.Drawing.SystemColors]::Control
$control.ColumnHeadersDefaultCellStyle.ForeColor = [System.Drawing.SystemColors]::ControlText
}
'TabControl' {
$control.BackColor = [System.Drawing.SystemColors]::Control
$control.ForeColor = [System.Drawing.SystemColors]::ControlText
}
'TabPage' {
$control.BackColor = [System.Drawing.SystemColors]::Control
$control.ForeColor = [System.Drawing.SystemColors]::ControlText
}
}
}
# Rekursiv für alle Child-Controls
foreach ($child in $control.Controls) {
$this.ApplyHighContrastToControls($child, $enabled)
}
}
# Gibt aktuelle Accessibility-Einstellungen zurück
[hashtable] GetCurrentSettings() {
return @{
FontSize = $this.SettingsManager.Get("FontSize", 9)
HighContrast = $this.SettingsManager.Get("HighContrast", $false)
KeyboardShortcuts = $this.SettingsManager.Get("KeyboardShortcuts", $true)
}
}
# Setzt eine spezifische Accessibility-Einstellung
[void] SetAccessibilitySetting([string]$key, [object]$value) {
$this.SettingsManager.Set($key, $value)
# Wende Änderung sofort an
switch ($key) {
"FontSize" { $this.UpdateAllFonts() }
"HighContrast" { $this.ApplyHighContrast($value) }
}
}
}
class FormBuilder : BaseComponent {
[System.String] $Title
[System.Windows.Forms.Form] $Form
[MenuBuilder] $Menu
[StatusStripBuilder] $StatusBar
FormBuilder($Title){
$this.Form = New-Object System.Windows.Forms.Form
$this.Form.Text = $Title
$this.Form.StartPosition = "CenterScreen"
# HIER wird RegisterForm automatisch aufgerufen:
[BaseComponent]::AccessibilityManager.RegisterForm($this.Form)
}
# Registriert ein Control für Accessibility-Features
[FormBuilder] RegisterAccessibleControl([System.Windows.Forms.Control]$control) {
[BaseComponent]::AccessibilityManager.RegisterFontControl($control)
return $this
}
# Registriert mehrere Controls
[FormBuilder] RegisterAccessibleControls([System.Windows.Forms.Control[]]$controls) {
[BaseComponent]::AccessibilityManager.RegisterFontControls($controls)
return $this
}
# NEU: Registriert automatisch ALLE Controls des Forms
[FormBuilder] RegisterAllAccessibleControls() {
[BaseComponent]::AccessibilityManager.RegisterAllControls($this.Form)
return $this
}
# NEU: Registriert nur bestimmte Control-Typen (z.B. nur TextBoxen und Labels)
[FormBuilder] RegisterAccessibleControlsByType([Type[]]$types) {
[BaseComponent]::AccessibilityManager.RegisterControlsByType($this.Form, $types)
return $this
}
[FormBuilder] AddMenu([MenuBuilder]$menuBuilder) {
$this.Menu = $menuBuilder
$this.Form.Controls.Add($menuBuilder.GetMenuStrip())
return $this
}
# Fügt eine StatusBar hinzu
[FormBuilder] AddStatusBar([StatusStripBuilder]$statusBar) {
$this.StatusBar = $statusBar
$this.Form.Controls.Add($statusBar.GetStatusStrip())
return $this
}
# Fügt ein SplitPanel hinzu
[FormBuilder] AddSplitPanel([SplitPanelBuilder]$splitPanel) {
$this.Form.Controls.Add($splitPanel.GetSplitContainer())
return $this
}
# Fügt ein beliebiges Control hinzu
[FormBuilder] AddControl([System.Windows.Forms.Control]$control) {
$this.Form.Controls.Add($control)
return $this
}
# Fügt mehrere Controls hinzu
[FormBuilder] AddControls([System.Windows.Forms.Control[]]$controls) {
foreach ($control in $controls) {
$this.Form.Controls.Add($control)
}
return $this
}
[void] SetTitle($Title) {
$this.Form.Text = $Title
}
# Setzt die Größe des Forms
[FormBuilder] SetSize([int]$width, [int]$height) {
$this.Form.Size = New-Object System.Drawing.Size($width, $height)
return $this
}
# Setzt nur die Breite
[FormBuilder] SetWidth([int]$width) {
$this.Form.Width = $width
return $this
}
# Setzt nur die Höhe
[FormBuilder] SetHeight([int]$height) {
$this.Form.Height = $height
return $this
}
# Setzt die Mindestgröße
[FormBuilder] SetMinimumSize([int]$width, [int]$height) {
$this.Form.MinimumSize = New-Object System.Drawing.Size($width, $height)
return $this
}
# Setzt die Maximalgröße
[FormBuilder] SetMaximumSize([int]$width, [int]$height) {
$this.Form.MaximumSize = New-Object System.Drawing.Size($width, $height)
return $this
}
# Setzt die Startposition
[FormBuilder] SetStartPosition([System.String]$position) {
$this.Form.StartPosition = [System.Windows.Forms.FormStartPosition]::$position
return $this
}
# Setzt die Location (Position auf dem Bildschirm)
[FormBuilder] SetLocation([int]$x, [int]$y) {
$this.Form.Location = New-Object System.Drawing.Point($x, $y)
return $this
}
# Setzt den WindowState
[FormBuilder] SetWindowState([System.String]$state) {
$this.Form.WindowState = [System.Windows.Forms.FormWindowState]::$state
return $this
}
[FormBuilder] AddLoadHandler([scriptblock]$handler) {
$this.Form.Add_Load($handler)
return $this
}
# Shown Event (wenn Form zum ersten Mal angezeigt wird)
[FormBuilder] AddShownHandler([scriptblock]$handler) {
$this.Form.Add_Shown($handler)
return $this
}
# FormClosing Event (bevor Form geschlossen wird - kann abgebrochen werden)
[FormBuilder] AddFormClosingHandler([scriptblock]$handler) {
$this.Form.Add_FormClosing($handler)
return $this
}
# FormClosed Event (nachdem Form geschlossen wurde)
[FormBuilder] AddFormClosedHandler([scriptblock]$handler) {
$this.Form.Add_FormClosed($handler)
return $this
}
# Resize Event
[FormBuilder] AddResizeHandler([scriptblock]$handler) {
$this.Form.Add_Resize($handler)
return $this
}
# Move Event
[FormBuilder] AddMoveHandler([scriptblock]$handler) {
$this.Form.Add_Move($handler)
return $this
}
# KeyDown Event
[FormBuilder] AddKeyDownHandler([scriptblock]$handler) {
$this.Form.Add_KeyDown($handler)
return $this
}
# Activate Event (wenn Form aktiviert wird)
[FormBuilder] AddActivateHandler([scriptblock]$handler) {
$this.Form.Add_Activated($handler)
return $this
}
# Deactivate Event
[FormBuilder] AddDeactivateHandler([scriptblock]$handler) {
$this.Form.Add_Deactivate($handler)
return $this
}
# Generischer Event-Handler für alle Events
[FormBuilder] AddEventHandler([System.String]$eventName, [scriptblock]$handler) {
$this.Form."Add_$eventName"($handler)
return $this
}
[void] Show(){
[void]$this.Form.ShowDialog()
}
}
class MenuBuilder : BaseComponent{
[System.Windows.Forms.MenuStrip] $MenuStrip
[System.Collections.Hashtable] $MenuItems = @{}
[System.Collections.Hashtable] $MenuConditions = @{}
[StateManager] $StateManager = $null
MenuBuilder() {
$this.MenuStrip = New-Object System.Windows.Forms.MenuStrip
$this.MenuStrip.Dock = 'Top'
}
# NEU: Setzt den StateManager
[MenuBuilder] WithStateManager([StateManager]$stateManager) {
$this.StateManager = $stateManager
return $this
}
# Fügt ein Hauptmenü-Element hinzu - JETZT MIT RETURN
[MenuBuilder] AddMainMenu([System.String]$name, [System.String]$text) {
$menuItem = New-Object System.Windows.Forms.ToolStripMenuItem $text
$this.MenuStrip.Items.Add($menuItem) | Out-Null
$this.MenuItems[$name] = $menuItem
return $this | Out-Null
}
# Fügt ein Untermenü-Element hinzu - JETZT MIT RETURN
[MenuBuilder] AddSubMenu([System.String]$parentName, [System.String]$name, [System.String]$text) {
if ($this.MenuItems.ContainsKey($parentName)) {
$menuItem = New-Object System.Windows.Forms.ToolStripMenuItem $text
$this.MenuItems[$parentName].DropDownItems.Add($menuItem) | Out-Null
$this.MenuItems[$name] = $menuItem
return $this | Out-Null
}
throw "Parent menu '$parentName' nicht gefunden"
}
# NEU: Fügt mehrere Untermenüs auf einmal hinzu
[MenuBuilder] AddSubMenus([System.String]$parentName, [hashtable[]]$items) {
foreach ($item in $items) {
if ($item.Type -eq "Separator") {
$this.AddSeparator($parentName)
}
else {
$this.AddSubMenu($parentName, $item.Name, $item.Text)
if ($item.Handler) {
$this.SetClickHandler($item.Name, $item.Handler)
}
}
}
return $this
}
# NEU: Erstellt komplettes Menü aus einer Struktur
[MenuBuilder] BuildFromStructure([hashtable[]]$structure) {
foreach ($mainMenu in $structure) {
$this.AddMainMenu($mainMenu.Name, $mainMenu.Text)
if ($mainMenu.Items) {
$this.AddSubMenus($mainMenu.Name, $mainMenu.Items)
}
}
return $this
}
# Fügt einen Separator hinzu - JETZT MIT RETURN
[MenuBuilder] AddSeparator([System.String]$parentName) {
if ($this.MenuItems.ContainsKey($parentName)) {
$this.MenuItems[$parentName].DropDownItems.Add('-') | Out-Null
}
return $this | Out-Null
}
# Setzt einen Event-Handler für ein Menü-Element - JETZT MIT RETURN
[MenuBuilder] SetClickHandler([System.String]$menuName, [scriptblock]$handler) {
if ($this.MenuItems.ContainsKey($menuName)) {
$this.MenuItems[$menuName].Add_Click($handler)
}
return $this | Out-Null
}
# NEU: Setzt einen Click-Handler mit Enable-Bedingung
[MenuBuilder] SetClickHandler([System.String]$menuName, [scriptblock]$handler, [scriptblock]$enableCondition) {
if ($this.MenuItems.ContainsKey($menuName)) {
$this.MenuItems[$menuName].Add_Click($handler)
$this.MenuConditions[$menuName] = $enableCondition
# Initial den Status setzen
$this.UpdateMenuItemState($menuName)
# Bei StateManager registrieren
if ($null -ne $this.StateManager) {
$this.StateManager.RegisterMenuItem($menuName, $this)
}
}
return $this | Out-Null
}
# NEU: Setzt mehrere Click-Handler auf einmal
[MenuBuilder] SetClickHandlers([System.Collections.Hashtable]$handlers) {
foreach ($key in $handlers.Keys) {
$this.SetClickHandler($key, $handlers[$key])
}
return $this | Out-Null
}
# NEU: Setzt mehrere Click-Handler mit Bedingungen
[MenuBuilder] SetClickHandlersWithConditions([System.Collections.Hashtable]$handlers) {
foreach ($key in $handlers.Keys) {
$config = $handlers[$key]
if ($config.Condition) {
$this.SetClickHandler($key, $config.Handler, $config.Condition)
} else {
$this.SetClickHandler($key, $config.Handler)
}
}
return $this | Out-Null
}
# NEU: Aktualisiert den Enabled-Status eines Menü-Items
[void] UpdateMenuItemState([System.String]$menuName) {
if ($this.MenuItems.ContainsKey($menuName) -and $this.MenuConditions.ContainsKey($menuName)) {
try {
$result = & $this.MenuConditions[$menuName]
$this.MenuItems[$menuName].Enabled = [bool]$result
} catch {
Write-Warning "Fehler beim Evaluieren der Menu-Bedingung für '$menuName': $_"
$this.MenuItems[$menuName].Enabled = $false
}
}
}
# NEU: Aktualisiert alle Menü-Items mit Bedingungen
[void] UpdateAllMenuItems() {
foreach ($menuName in $this.MenuConditions.Keys) {
$this.UpdateMenuItemState($menuName)
}
}
# Gibt das MenuStrip-Objekt zurück
[System.Windows.Forms.MenuStrip] GetMenuStrip() {
return $this.MenuStrip
}
# Aktiviert/Deaktiviert ein Menü-Element - JETZT MIT RETURN
[MenuBuilder] SetEnabled([System.String]$menuName, [bool]$enabled) {
if ($this.MenuItems.ContainsKey($menuName)) {
$this.MenuItems[$menuName].Enabled = $enabled
}
return $this
}
# NEU: Holt ein Menü-Item
[System.Windows.Forms.ToolStripMenuItem] GetMenuItem([System.String]$menuName) {
if ($this.MenuItems.ContainsKey($menuName)) {
return $this.MenuItems[$menuName]
}
return $null
}
}
class StatusStripBuilder : BaseComponent{
[System.Windows.Forms.StatusStrip] $StatusStrip
[System.Collections.Hashtable] $Labels = @{}
StatusStripBuilder() {
$this.StatusStrip = New-Object System.Windows.Forms.StatusStrip
}
# Fügt ein Label zur StatusBar hinzu
[System.Windows.Forms.ToolStripStatusLabel] AddLabel([System.String]$name, [System.String]$text) {
$label = New-Object System.Windows.Forms.ToolStripStatusLabel
$label.Text = $text
$this.StatusStrip.Items.Add($label) | Out-Null
$this.Labels[$name] = $label
return $label
}
# Fügt ein Label mit Spring-Eigenschaft hinzu (füllt verfügbaren Platz)
[System.Windows.Forms.ToolStripStatusLabel] AddSpringLabel([System.String]$name, [System.String]$text) {
$label = New-Object System.Windows.Forms.ToolStripStatusLabel
$label.Text = $text
$label.Spring = $true
$label.TextAlign = [System.Drawing.ContentAlignment]::MiddleLeft
$this.StatusStrip.Items.Add($label) | Out-Null
$this.Labels[$name] = $label
return $label
}
# Setzt den Text eines Labels
[void] SetText([System.String]$labelName, [System.String]$text) {
if ($this.Labels.ContainsKey($labelName)) {
$this.Labels[$labelName].Text = $text
}
}
# Fügt einen Separator hinzu
[void] AddSeparator() {
$separator = New-Object System.Windows.Forms.ToolStripSeparator
$this.StatusStrip.Items.Add($separator) | Out-Null
}
# Fügt eine ProgressBar hinzu
[System.Windows.Forms.ToolStripProgressBar] AddProgressBar([System.String]$name) {
$progressBar = New-Object System.Windows.Forms.ToolStripProgressBar
$progressBar.Size = New-Object System.Drawing.Size(100, 16)
$this.StatusStrip.Items.Add($progressBar) | Out-Null
$this.Labels[$name] = $progressBar
return $progressBar
}
# Setzt den Fortschritt einer ProgressBar
[void] SetProgress([System.String]$progressBarName, [int]$value) {
if ($this.Labels.ContainsKey($progressBarName)) {
$this.Labels[$progressBarName].Value = $value
}
}
# Gibt das StatusStrip-Objekt zurück
[System.Windows.Forms.StatusStrip] GetStatusStrip() {
return $this.StatusStrip
}
# Zeigt/Versteckt ein Element
[void] SetVisible([System.String]$itemName, [bool]$visible) {
if ($this.Labels.ContainsKey($itemName)) {
$this.Labels[$itemName].Visible = $visible
}
}
# Setzt die Hintergrundfarbe eines Labels
[void] SetBackColor([System.String]$labelName, [System.Drawing.Color]$color) {
if ($this.Labels.ContainsKey($labelName)) {
$this.Labels[$labelName].BackColor = $color
}
}
# Setzt die Textfarbe eines Labels
[void] SetForeColor([System.String]$labelName, [System.Drawing.Color]$color) {
if ($this.Labels.ContainsKey($labelName)) {
$this.Labels[$labelName].ForeColor = $color
}
}
}
class SplitPanelBuilder : BaseComponent{
[System.Windows.Forms.SplitContainer] $SplitContainer
[Int] $DesiredPanel1MinSize = 100
[Int] $DesiredPanel2MinSize = 250
[Int] $DesiredSplitterDistance = 200
[Double] $SplitterDistanceRatio = 0.0
SplitPanelBuilder([System.String]$orientation) {
$this.SplitContainer = New-Object System.Windows.Forms.SplitContainer
$this.SplitContainer.Dock = 'Fill'
if ($orientation -eq 'Horizontal') {
$this.SplitContainer.Orientation = 'Horizontal'
} else {
$this.SplitContainer.Orientation = 'Vertical'
}
}
# Konstruktor mit MinSize-Optionen - Verzögerte Initialisierung
SplitPanelBuilder([System.String]$orientation, [int]$splitterDistance, [int]$panel1MinSize, [int]$panel2MinSize) {
$this.SplitContainer = New-Object System.Windows.Forms.SplitContainer
$this.SplitContainer.Dock = 'Fill'
$this.SplitContainer.Orientation = $orientation
# Speichere die gewünschten Werte für spätere Initialisierung
$this.DesiredPanel1MinSize = $panel1MinSize
$this.DesiredPanel2MinSize = $panel2MinSize
$this.DesiredSplitterDistance = $splitterDistance
# Setze nur die absolut notwendigen Anfangswerte
$this.SplitContainer.Panel1MinSize = [Math]::Min($panel1MinSize, 25)
$this.SplitContainer.Panel2MinSize = 25
}
# Konstruktor mit Verhältnis (Ratio) für SplitterDistance
SplitPanelBuilder([System.String]$orientation, [double]$splitterRatio, [int]$panel1MinSize, [int]$panel2MinSize) {
$this.SplitContainer = New-Object System.Windows.Forms.SplitContainer
$this.SplitContainer.Dock = 'Fill'
$this.SplitContainer.Orientation = $orientation
# Speichere die gewünschten Werte
$this.DesiredPanel1MinSize = $panel1MinSize
$this.DesiredPanel2MinSize = $panel2MinSize
$this.SplitterDistanceRatio = $splitterRatio
# Setze nur die absolut notwendigen Anfangswerte
$this.SplitContainer.Panel1MinSize = [Math]::Min($panel1MinSize, 25)
$this.SplitContainer.Panel2MinSize = 25
}
# Initialisiert den SplitContainer mit den finalen Werten (nach Form.Shown)
[void] InitializeAfterShown([System.Windows.Forms.Form]$form) {
# Bestimme verfügbare Breite/Höhe aus dem SplitContainer selbst
$availableSize = if ($this.SplitContainer.Orientation -eq 'Vertical') {
$this.SplitContainer.Width
} else {
$this.SplitContainer.Height
}
# Sicherheitscheck: Mindestgröße
if ($availableSize -lt 100) {
Write-Warning "SplitContainer zu klein: $availableSize px. Verwende ClientSize."
$availableSize = if ($this.SplitContainer.Orientation -eq 'Vertical') {
$form.ClientSize.Width
} else {
$form.ClientSize.Height
}
}
# Panel2MinSize anpassen falls nötig
$proposedPanel2 = $this.DesiredPanel2MinSize
$maxAllowed = $availableSize - $this.DesiredPanel1MinSize - $this.SplitContainer.SplitterWidth
if ($maxAllowed -lt 25) {
# Nicht genug Platz - verwende Minimalkonfiguration
$this.SplitContainer.Panel1MinSize = 25
$this.SplitContainer.Panel2MinSize = 25
$this.SplitContainer.SplitterDistance = 25
Write-Warning "Nicht genug Platz für gewünschte MinSizes. Verwende Minimalwerte."
return
}
if ($proposedPanel2 -gt $maxAllowed) {
$proposedPanel2 = [Math]::Max(25, [int]($maxAllowed / 2))
}
# Panel1MinSize setzen
$this.SplitContainer.Panel1MinSize = $this.DesiredPanel1MinSize
# Panel2MinSize setzen
$this.SplitContainer.Panel2MinSize = $proposedPanel2
# SplitterDistance berechnen und setzen
if ($this.SplitterDistanceRatio -gt 0) {
# Wenn Ratio angegeben wurde
$desired = [int]($availableSize * $this.SplitterDistanceRatio)
} else {
# Wenn fester Wert angegeben wurde
$desired = $this.DesiredSplitterDistance
}
# Validierung mit strengeren Grenzen
$minAllowed = $this.SplitContainer.Panel1MinSize
$maxAllowed = $availableSize - $this.SplitContainer.Panel2MinSize - $this.SplitContainer.SplitterWidth
if ($desired -lt $minAllowed) {
$desired = $minAllowed
}
if ($desired -gt $maxAllowed) {
$desired = $maxAllowed
}
# Finale Sicherheitsprüfung
if ($desired -lt 1) {
$desired = $minAllowed
}
$this.SplitContainer.SplitterDistance = $desired
}
# Setzt Padding für Panel mit Berücksichtigung der Menühöhe
[void] SetPanelPaddingWithMenu([int]$panelNumber, [System.Windows.Forms.MenuStrip]$menu, [int]$left, [int]$right, [int]$bottom) {
try {
$menuHeight = $menu.Height
$topPadding = $menuHeight + 6
} catch {
$topPadding = 36 # Fallback
}
$padding = New-Object System.Windows.Forms.Padding($left, $topPadding, $right, $bottom)
if ($panelNumber -eq 1) {
$this.SplitContainer.Panel1.Padding = $padding
} else {
$this.SplitContainer.Panel2.Padding = $padding
}
}
[System.Windows.Forms.SplitterPanel] GetPanel1() {
return $this.SplitContainer.Panel1
}
# KORREKTUR: Gibt $this zurück für Fluent API
[SplitPanelBuilder] AddToPanel1([System.Windows.Forms.Control]$control) {
$this.SplitContainer.Panel1.Controls.Add($control)
return $this
}
# KORREKTUR: Gibt $this zurück für Fluent API
[SplitPanelBuilder] ClearPanel1() {
$this.SplitContainer.Panel1.Controls.Clear()
return $this
}
[System.Windows.Forms.SplitterPanel] GetPanel2() {
return $this.SplitContainer.Panel2
}
# KORREKTUR: Gibt $this zurück für Fluent API
[SplitPanelBuilder] AddToPanel2([System.Windows.Forms.Control]$control) {
$this.SplitContainer.Panel2.Controls.Add($control)
return $this
}
# KORREKTUR: Gibt $this zurück für Fluent API
[SplitPanelBuilder] ClearPanel2() {
$this.SplitContainer.Panel2.Controls.Clear()
return $this
}
# Berechnet die optimale SplitterDistance basierend auf den Controls in Panel1
[void] AutoSizeSplitterToPanel1Content() {
$maxSize = 0
foreach ($control in $this.SplitContainer.Panel1.Controls) {
if ($this.SplitContainer.Orientation -eq 'Vertical') {
# Bei vertikaler Orientierung: Breite berechnen
$requiredSize = $control.Right + $control.Margin.Right
} else {
# Bei horizontaler Orientierung: Höhe berechnen
$requiredSize = $control.Bottom + $control.Margin.Bottom
}
if ($requiredSize -gt $maxSize) {
$maxSize = $requiredSize
}
}
# Padding von Panel1 berücksichtigen
if ($this.SplitContainer.Orientation -eq 'Vertical') {
$maxSize += $this.SplitContainer.Panel1.Padding.Right
} else {
$maxSize += $this.SplitContainer.Panel1.Padding.Bottom
}
# Sicherheitsabstand hinzufügen
$maxSize += 10
# Mit Constraints validieren und setzen
$this.SetSplitterDistance($maxSize)
}
# Setzt die Splitter-Position mit Validierung
[SplitPanelBuilder] SetSplitterDistance([int]$distance) {
$minDistance = $this.SplitContainer.Panel1MinSize
$maxDistance = $this.SplitContainer.Width - $this.SplitContainer.Panel2MinSize
if ($distance -lt $minDistance) {
$this.SplitContainer.SplitterDistance = $minDistance
}
elseif ($distance -gt $maxDistance) {
$this.SplitContainer.SplitterDistance = $maxDistance
}
else {
$this.SplitContainer.SplitterDistance = $distance
}
return $this
}
# Fixiert den Splitter
[SplitPanelBuilder] SetFixedPanel([System.String]$panel) {
switch ($panel) {
'Panel1' { $this.SplitContainer.FixedPanel = 'Panel1' }
'Panel2' { $this.SplitContainer.FixedPanel = 'Panel2' }
default { $this.SplitContainer.FixedPanel = 'None' }
}
return $this
}
# Verhindert das Verschieben des Splitters
[SplitPanelBuilder] SetIsSplitterFixed([bool]$fixed) {
$this.SplitContainer.IsSplitterFixed = $fixed
return $this
}
# Setzt die Splitter-Breite
[SplitPanelBuilder] SetSplitterWidth([int]$width) {
$this.SplitContainer.SplitterWidth = $width
return $this
}
# Gibt das SplitContainer-Objekt zurück
[System.Windows.Forms.SplitContainer] GetSplitContainer() {
return $this.SplitContainer
}
}
class FlowLayoutPanelBuilder {
[System.Windows.Forms.FlowLayoutPanel]$control
FlowLayoutPanelBuilder() {
$this.control = New-Object System.Windows.Forms.FlowLayoutPanel
# Standard-Einstellungen
$this.control.Dock = 'Fill'
$this.control.AutoScroll = $true
$this.control.FlowDirection = 'TopDown'
$this.control.WrapContents = $false
}
[FlowLayoutPanelBuilder] SetDock([System.String]$dock) {
$this.control.Dock = [System.Windows.Forms.DockStyle]::$dock
return $this
}
[FlowLayoutPanelBuilder] SetAutoScroll([bool]$autoScroll) {
$this.control.AutoScroll = $autoScroll
return $this
}
[FlowLayoutPanelBuilder] SetFlowDirection([System.String]$direction) {
$this.control.FlowDirection = [System.Windows.Forms.FlowDirection]::$direction
return $this
}
[FlowLayoutPanelBuilder] SetWrapContents([bool]$wrap) {
$this.control.WrapContents = $wrap
return $this
}
[FlowLayoutPanelBuilder] SetPadding([int]$all) {
$this.control.Padding = New-Object System.Windows.Forms.Padding($all)
return $this
}
[FlowLayoutPanelBuilder] SetPadding([int]$left, [int]$top, [int]$right, [int]$bottom) {
$this.control.Padding = New-Object System.Windows.Forms.Padding($left, $top, $right, $bottom)
return $this
}
[FlowLayoutPanelBuilder] SetBackColor([System.Drawing.Color]$color) {
$this.control.BackColor = $color
return $this
}
[FlowLayoutPanelBuilder] SetWidth([int]$width) {
$this.control.Width = $width
return $this
}
[FlowLayoutPanelBuilder] SetHeight([int]$height) {
$this.control.Height = $height
return $this
}
[FlowLayoutPanelBuilder] SetSize([int]$width, [int]$height) {
$this.control.Width = $width
$this.control.Height = $height
return $this
}
[FlowLayoutPanelBuilder] SetBorderStyle([System.String]$style) {
$this.control.BorderStyle = [System.Windows.Forms.BorderStyle]::$style
return $this
}
[FlowLayoutPanelBuilder] AddControl([System.Windows.Forms.Control]$childControl) {
$this.control.Controls.Add($childControl)
return $this
}
[FlowLayoutPanelBuilder] AddControls([System.Windows.Forms.Control[]]$controls) {
foreach ($ctrl in $controls) {
$this.control.Controls.Add($ctrl)
}
return $this
}
[FlowLayoutPanelBuilder] ClearControls() {
$this.control.Controls.Clear()
return $this
}
[System.Windows.Forms.FlowLayoutPanel] AddTo([System.Windows.Forms.Control]$parent) {
$parent.Controls.Add($this.control)
return $this.control
}
[System.Windows.Forms.FlowLayoutPanel] Build() {
return $this.control
}
}
class ButtonBuilder : BaseComponent {
[System.Windows.Forms.Button] $Button
[scriptblock] $EnableCondition = $null
[StateManager] $StateManager = $null
ButtonBuilder() {
$this.Button = New-Object System.Windows.Forms.Button
$this.Button.Font = New-Object System.Drawing.Font("Segoe UI", $this.GetSetting("FontSize"))
$this.SetSize(40, 40)
$this.Button.Margin = New-Object System.Windows.Forms.Padding(5)
}
ButtonBuilder([System.String]$text) {
$this.Button = New-Object System.Windows.Forms.Button
$this.Button.Text = $text
$this.Button.Font = New-Object System.Drawing.Font("Segoe UI", $this.GetSetting("FontSize"))
$this.SetSize(40, 40)
}
# Konstruktor mit Text und Höhe
ButtonBuilder([System.String]$text, [int]$height) {
$this.Button = New-Object System.Windows.Forms.Button
$this.Button.Text = $text
$this.Button.Height = $height
$this.Button.Font = New-Object System.Drawing.Font("Segoe UI", $this.GetSetting("FontSize"))
}
# Setzt den Text
[ButtonBuilder] SetText([System.String]$text) {
$this.Button.Text = $text
return $this
}
# Setzt die Höhe
[ButtonBuilder] SetHeight([int]$height) {
$this.Button.Height = $height
return $this
}
# Setzt die Breite
[ButtonBuilder] SetWidth([int]$width) {
$this.Button.Width = $width
return $this
}
# Setzt die Größe
[ButtonBuilder] SetSize([int]$width, [int]$height) {
$this.Button.Size = New-Object System.Drawing.Size($width, $height)
return $this
}
# Setzt das Dock
[ButtonBuilder] SetDock([System.String]$dock) {
$this.Button.Dock = $dock
return $this
}
# Setzt die Position
[ButtonBuilder] SetLocation([int]$x, [int]$y) {
$this.Button.Location = New-Object System.Drawing.Point($x, $y)
return $this
}
# Setzt die Schriftart
[ButtonBuilder] SetFont([System.String]$fontFamily, [int]$fontSize) {
$this.Button.Font = New-Object System.Drawing.Font($fontFamily, $fontSize)
return $this
}
# Setzt die Schriftart mit Stil
[ButtonBuilder] SetFont([System.String]$fontFamily, [int]$fontSize, [System.Drawing.FontStyle]$fontStyle) {
$this.Button.Font = New-Object System.Drawing.Font($fontFamily, $fontSize, $fontStyle)
return $this
}
# Setzt die Hintergrundfarbe
[ButtonBuilder] SetBackColor([System.Drawing.Color]$color) {
$this.Button.BackColor = $color
return $this
}
# Setzt die Textfarbe
[ButtonBuilder] SetForeColor([System.Drawing.Color]$color) {
$this.Button.ForeColor = $color
return $this
}
# Setzt den Enabled-Status
[ButtonBuilder] SetEnabled([bool]$enabled) {
$this.Button.Enabled = $enabled
return $this
}
# Setzt die Sichtbarkeit
[ButtonBuilder] SetVisible([bool]$visible) {
$this.Button.Visible = $visible
return $this
}
# Setzt das FlatStyle
[ButtonBuilder] SetFlatStyle([System.String]$style) {
switch ($style) {
'Flat' { $this.Button.FlatStyle = 'Flat' }
'Popup' { $this.Button.FlatStyle = 'Popup' }
'Standard' { $this.Button.FlatStyle = 'Standard' }
'System' { $this.Button.FlatStyle = 'System' }
}
return $this
}
# Setzt ein MDL2-Icon
[ButtonBuilder] SetMDL2Icon([System.String]$unicodeChar) {
$this.Button.Font = New-Object System.Drawing.Font("Segoe MDL2 Assets", 14)
$this.Button.Text = $unicodeChar
return $this
}
# Setzt ein Fluent-Icon
[ButtonBuilder] SetFluentIcon([System.String]$unicodeChar) {
$this.Button.Font = New-Object System.Drawing.Font("Segoe Fluent Icons", 14)
$this.Button.Text = $unicodeChar
return $this
}
# NEU: Bindet Button an StateManager (ohne Bedingung)
[ButtonBuilder] WithStateManager([StateManager]$stateManager) {
$this.StateManager = $stateManager
return $this
}
# NEU: Kombinierte Methode - Bedingung + StateManager
[ButtonBuilder] BindEnabled([scriptblock]$condition, [StateManager]$stateManager) {
$this.EnableCondition = $condition
$this.StateManager = $stateManager
$this.UpdateEnabledState()
return $this
}
# Original-Methode - nur Bedingung, kein StateManager
[ButtonBuilder] BindEnabled([scriptblock]$condition) {
$this.EnableCondition = $condition
$this.UpdateEnabledState()
return $this
}
# Aktualisiert den Enabled-Status basierend auf der Bedingung
[void] UpdateEnabledState() {
if ($null -ne $this.EnableCondition) {
try {
$result = & $this.EnableCondition
$this.Button.Enabled = [bool]$result
} catch {
Write-Warning "Fehler beim Evaluieren der Enable-Bedingung: $_"
$this.Button.Enabled = $false
}
}
}
# Setzt den Click-Handler
[ButtonBuilder] SetClickHandler([scriptblock]$handler) {
$this.Button.Add_Click($handler)
return $this
}
# Setzt einen Tooltip
[ButtonBuilder] SetToolTip([System.String]$text) {
$tooltip = New-Object System.Windows.Forms.ToolTip
$tooltip.SetToolTip($this.Button, $text)
return $this
}
# Setzt das Anchor
[ButtonBuilder] SetAnchor([System.Windows.Forms.AnchorStyles]$anchor) {
$this.Button.Anchor = $anchor
return $this
}
# Gibt das Button-Objekt zurück
[System.Windows.Forms.Button] GetButton() {
return $this.Button
}
# Fügt den Button zu einem Control hinzu
[void] AddTo([System.Windows.Forms.Control]$parent) {
$parent.Controls.Add($this.Button)
}
# NEU: Build mit Auto-Registrierung beim StateManager
[System.Windows.Forms.Button] Build() {
# Auto-Registrierung wenn StateManager gesetzt
if ($null -ne $this.StateManager -and $null -ne $this.EnableCondition) {
$this.StateManager.RegisterButton($this)
}
return $this.Button
}
}
class LabelBuilder : BaseComponent {
[System.Windows.Forms.Label] $Label
LabelBuilder([System.String]$text) {
$this.Label = New-Object System.Windows.Forms.Label
$this.Label.Text = $text
$this.Label.Font = New-Object System.Drawing.Font("Segoe UI", $this.GetSetting("FontSize"))
}
# Konstruktor mit Text und Höhe
LabelBuilder([System.String]$text, [int]$height) {
$this.Label = New-Object System.Windows.Forms.Label
$this.Label.Text = $text
$this.Label.Height = $height
$this.Label.Font = New-Object System.Drawing.Font("Segoe UI", $this.GetSetting("FontSize"))
}
# Setzt den Text
[LabelBuilder] SetText([System.String]$text) {
$this.Label.Text = $text
return $this
}
# Setzt die Höhe
[LabelBuilder] SetHeight([int]$height) {
$this.Label.Height = $height
return $this
}
# Setzt die Breite
[LabelBuilder] SetWidth([int]$width) {
$this.Label.Width = $width
return $this
}
# Setzt die Größe
[LabelBuilder] SetSize([int]$width, [int]$height) {
$this.Label.Size = New-Object System.Drawing.Size($width, $height)
return $this
}
# Setzt das Dock
[LabelBuilder] SetDock([System.String]$dock) {
$this.Label.Dock = $dock
return $this
}
# Setzt die Position
[LabelBuilder] SetLocation([int]$x, [int]$y) {
$this.Label.Location = New-Object System.Drawing.Point($x, $y)
return $this
}
# Setzt die Schriftart
[LabelBuilder] SetFont([System.String]$fontFamily, [int]$fontSize) {
$this.Label.Font = New-Object System.Drawing.Font($fontFamily, $fontSize)
return $this
}
# Setzt die Schriftart mit Stil
[LabelBuilder] SetFont([System.String]$fontFamily, [int]$fontSize, [System.Drawing.FontStyle]$fontStyle) {
$this.Label.Font = New-Object System.Drawing.Font($fontFamily, $fontSize, $fontStyle)
return $this
}
# Setzt die Hintergrundfarbe
[LabelBuilder] SetBackColor([System.Drawing.Color]$color) {
$this.Label.BackColor = $color
return $this
}
# Setzt die Textfarbe
[LabelBuilder] SetForeColor([System.Drawing.Color]$color) {
$this.Label.ForeColor = $color
return $this
}
# Setzt die Textausrichtung
[LabelBuilder] SetTextAlign([System.Drawing.ContentAlignment]$alignment) {
$this.Label.TextAlign = $alignment
return $this
}
# Setzt AutoSize
[LabelBuilder] SetAutoSize([bool]$autoSize) {
$this.Label.AutoSize = $autoSize
return $this
}
# Setzt den Enabled-Status
[LabelBuilder] SetEnabled([bool]$enabled) {
$this.Label.Enabled = $enabled
return $this
}
# Setzt die Sichtbarkeit
[LabelBuilder] SetVisible([bool]$visible) {
$this.Label.Visible = $visible
return $this
}
# Setzt BorderStyle
[LabelBuilder] SetBorderStyle([System.String]$style) {
switch ($style) {
'None' { $this.Label.BorderStyle = 'None' }
'FixedSingle' { $this.Label.BorderStyle = 'FixedSingle' }
'Fixed3D' { $this.Label.BorderStyle = 'Fixed3D' }
}
return $this
}
# Setzt das Padding
[LabelBuilder] SetPadding([int]$left, [int]$top, [int]$right, [int]$bottom) {
$this.Label.Padding = New-Object System.Windows.Forms.Padding($left, $top, $right, $bottom)
return $this
}
# Setzt das Margin
[LabelBuilder] SetMargin([int]$left, [int]$top, [int]$right, [int]$bottom) {
$this.Label.Margin = New-Object System.Windows.Forms.Padding($left, $top, $right, $bottom)
return $this
}
# Setzt das Padding (alle Seiten gleich)
[LabelBuilder] SetPadding([int]$all) {
$this.Label.Padding = New-Object System.Windows.Forms.Padding($all)
return $this
}
# Setzt das Anchor
[LabelBuilder] SetAnchor([System.Windows.Forms.AnchorStyles]$anchor) {
$this.Label.Anchor = $anchor
return $this
}
# Setzt einen Tooltip
[LabelBuilder] SetToolTip([System.String]$text) {
$tooltip = New-Object System.Windows.Forms.ToolTip
$tooltip.SetToolTip($this.Label, $text)
return $this
}
# Setzt das UseMnemonic (für & Zeichen)
[LabelBuilder] SetUseMnemonic([bool]$useMnemonic) {
$this.Label.UseMnemonic = $useMnemonic
return $this
}
# Gibt das Label-Objekt zurück
[System.Windows.Forms.Label] GetLabel() {
return $this.Label
}
# Fügt das Label zu einem Control hinzu
[void] AddTo([System.Windows.Forms.Control]$parent) {
$parent.Controls.Add($this.Label)
}
[System.Windows.Forms.Label] Build() {
return $this.Label
}
}
class TreeViewBuilder : BaseComponent {
[System.Windows.Forms.TreeView]$control
TreeViewBuilder() {
$this.control = New-Object System.Windows.Forms.TreeView
# Standard-Einstellungen
$this.control.Dock = 'Fill'
$this.control.HideSelection = $false
$this.control.ShowPlusMinus = $true
$this.control.ShowRootLines = $true
$this.control.FullRowSelect = $true
}
[TreeViewBuilder] SetDock([System.String]$dock) {
$this.control.Dock = [System.Windows.Forms.DockStyle]::$dock
return $this
}
[TreeViewBuilder] SetFont([System.String]$family, [float]$size) {
$this.control.Font = New-Object System.Drawing.Font($family, $size)
return $this
}
[TreeViewBuilder] SetFont([System.String]$family, [float]$size, [System.Drawing.FontStyle]$style) {
$this.control.Font = New-Object System.Drawing.Font($family, $size, $style)
return $this
}
[TreeViewBuilder] SetHideSelection([bool]$hide) {
$this.control.HideSelection = $hide
return $this
}
[TreeViewBuilder] SetShowPlusMinus([bool]$show) {
$this.control.ShowPlusMinus = $show
return $this
}
[TreeViewBuilder] SetShowRootLines([bool]$show) {
$this.control.ShowRootLines = $show
return $this
}
[TreeViewBuilder] SetFullRowSelect([bool]$select) {
$this.control.FullRowSelect = $select
return $this
}
[TreeViewBuilder] SetShowLines([bool]$show) {
$this.control.ShowLines = $show
return $this
}
[TreeViewBuilder] SetCheckBoxes([bool]$show) {
$this.control.CheckBoxes = $show
return $this
}
[TreeViewBuilder] SetImageList([System.Windows.Forms.ImageList]$imageList) {
$this.control.ImageList = $imageList
return $this
}
[TreeViewBuilder] SetBackColor([System.Drawing.Color]$color) {
$this.control.BackColor = $color
return $this
}
[TreeViewBuilder] SetForeColor([System.Drawing.Color]$color) {
$this.control.ForeColor = $color
return $this
}
[TreeViewBuilder] AddNode([System.String]$name) {
$this.control.Nodes.Add([System.Windows.Forms.TreeNode]::new($name)) | Out-Null
return $this
}
[TreeViewBuilder] AddNode([System.Windows.Forms.TreeNode]$node) {
$this.control.Nodes.Add($node) | Out-Null
return $this
}
[TreeViewBuilder] AddNodes([System.Windows.Forms.TreeNode[]]$nodes) {
foreach ($node in $nodes) {
$this.control.Nodes.Add($node) | Out-Null
}
return $this
}
# NEU: Lädt Hashtable/Template in TreeView
[TreeViewBuilder] LoadTemplate([object]$template, [System.String]$rootName = "Template") {
$this.control.Nodes.Clear()
$rootNode = $this.control.Nodes.Add($rootName)
try {
if ($template -is [System.Collections.IDictionary]) {
# WICHTIG: Keine Sortierung, Keys in Original-Reihenfolge
foreach ($key in $template.Keys) {
$this.AddTreeNodeRecursive($rootNode, $template[$key], $key, "")
}
} else {
$this.AddTreeNodeRecursive($rootNode, $template, $rootName, "")
}
} catch {
$rootNode.Nodes.Add("Fehler beim Lesen: $($_.Exception.Message)") | Out-Null
}
$rootNode.ExpandAll()
return $this
}
# NEU: Rekursive Methode zum Hinzufügen von Nodes
hidden [void] AddTreeNodeRecursive([System.Windows.Forms.TreeNode]$parentNode, [object]$value, [System.String]$name, [System.String]$path) {
$currentPath = if ($path -eq "") { $name } else { "$path.$name" }
if ($value -is [System.Collections.IDictionary]) {
$node = $parentNode.Nodes.Add($name, $name)
$node.Tag = @{ Type = "Hashtable"; Path = $currentPath; Value = $value }
# WICHTIG: KEIN Sort-Object! Behält die Original-Reihenfolge bei
foreach ($k in $value.Keys) {
$this.AddTreeNodeRecursive($node, $value[$k], $k, $currentPath)
}
}
elseif ($value -is [System.Collections.IEnumerable] -and -not ($value -is [string])) {
$node = $parentNode.Nodes.Add($name, $name)
$node.Tag = @{ Type = "Array"; Path = $currentPath; Value = $value }
$i = 0
foreach ($item in $value) {
$this.AddTreeNodeRecursive($node, $item, "[$i]", $currentPath)
$i++
}
}
else {
$displayText = "$name = $value"
$node = $parentNode.Nodes.Add($name, $displayText)
$node.Tag = @{ Type = "Value"; Path = $currentPath; Key = $name; Value = $value }
}
}
# NEU: Löscht alle Nodes
[TreeViewBuilder] ClearNodes() {
$this.control.Nodes.Clear()
return $this
}
[TreeViewBuilder] AddEventHandler([System.String]$eventName, [scriptblock]$handler) {
$this.control."Add_$eventName"($handler)
return $this
}
[System.Windows.Forms.TreeView] AddTo([System.Windows.Forms.Control]$parent) {
$parent.Controls.Add($this.control)
return $this.control
}
[System.Windows.Forms.TreeView] Build() {
return $this.control
}
}
class DataGridViewBuilder : BaseComponent{
[System.Windows.Forms.DataGridView] $control
DataGridViewBuilder() {
$this.control = New-Object System.Windows.Forms.DataGridView
$this.control.Dock = "Fill"
$this.control.ColumnHeadersHeight = 30
$this.control.AutoSizeColumnsMode = "Fill"
}
[DataGridViewBuilder] SetAllowAddRows([Boolean] $enabled) {
$this.control.AllowUserToAddRows = $enabled
return $this
}
[DataGridViewBuilder] SetHeaderColumns([System.Array] $Columns) {
foreach($Column in $Columns){
$this.control.Columns.Add($Column,$Column)
}
return $this
}
[DataGridViewBuilder] SetHeaderColumnReadOnly([System.String] $Name) {
$this.control.Columns[$Name].ReadOnly = $true
return $this
}
[System.Windows.Forms.DataGridView] Build() {
return $this.control
}
}
class GroupBoxBuilder : BaseComponent {
[System.Windows.Forms.GroupBox]$control
[bool]$autoSizeToContent = $false
GroupBoxBuilder([System.String]$text) {
$this.control = New-Object System.Windows.Forms.GroupBox
$this.control.Text = $text
$this.control.Font = New-Object System.Drawing.Font("Segoe UI", $this.GetSetting("FontSize"),[System.Drawing.FontStyle]::Bold)
#$this.control.AutoSizeMode = [System.Windows.Forms.AutoSizeMode]::GrowOnly
}
[GroupBoxBuilder] SetText([System.String]$text) {
$this.control.Text = $text
return $this
}
[GroupBoxBuilder] SetWidth([int]$width) {
$this.control.Width = $width
return $this
}
[GroupBoxBuilder] SetHeight([int]$height) {
$this.control.Height = $height
return $this
}
[GroupBoxBuilder] SetSize([int]$width, [int]$height) {
$this.control.Width = $width
$this.control.Height = $height
return $this
}
[GroupBoxBuilder] SetFont([System.String]$family, [float]$size) {
$this.control.Font = New-Object System.Drawing.Font($family, $size)
return $this
}
[GroupBoxBuilder] SetFont([System.String]$family, [float]$size, [System.Drawing.FontStyle]$style) {
$this.control.Font = New-Object System.Drawing.Font($family, $size, $style)
return $this
}
[GroupBoxBuilder] SetMargin([int]$all) {
$this.control.Margin = New-Object System.Windows.Forms.Padding($all)
return $this
}
[GroupBoxBuilder] SetMargin([int]$left, [int]$top, [int]$right, [int]$bottom) {
$this.control.Margin = New-Object System.Windows.Forms.Padding($left, $top, $right, $bottom)
return $this
}
[GroupBoxBuilder] SetPadding([int]$all) {
$this.control.Padding = New-Object System.Windows.Forms.Padding($all)
return $this
}
[GroupBoxBuilder] SetPadding([int]$left, [int]$top, [int]$right, [int]$bottom) {
$this.control.Padding = New-Object System.Windows.Forms.Padding($left, $top, $right, $bottom)
return $this
}
[GroupBoxBuilder] SetDock([System.String]$dock) {
$this.control.Dock = [System.Windows.Forms.DockStyle]::$dock
return $this
}
[GroupBoxBuilder] SetBackColor([System.Drawing.Color]$color) {
$this.control.BackColor = $color
return $this
}
[GroupBoxBuilder] SetForeColor([System.Drawing.Color]$color) {
$this.control.ForeColor = $color
return $this
}
[GroupBoxBuilder] SetAutoSize([bool]$autoSize) {
$this.control.AutoSize = $autoSize
return $this
}
[GroupBoxBuilder] SetAutoSizeMode([System.String]$autoSizeMode) {
$this.control.AutoSizeMode = [System.Windows.Forms.AutoSizeMode]::$autoSizeMode
return $this
}
[GroupBoxBuilder] AddControl([System.Windows.Forms.Control]$childControl) {
$this.control.Controls.Add($childControl)
return $this
}
[GroupBoxBuilder] AddControls([System.Windows.Forms.Control[]]$controls) {
foreach ($ctrl in $controls) {
$this.control.Controls.Add($ctrl)
}
return $this
}
[System.Windows.Forms.GroupBox] AddTo([System.Windows.Forms.Control]$parent) {
$parent.Controls.Add($this.control)
return $this.control
}
[System.Windows.Forms.GroupBox] Build() {
return $this.control
}
}
class ListBoxBuilder : BaseComponent {
[System.Windows.Forms.ListBox]$control
ListBoxBuilder() {
$this.control = New-Object System.Windows.Forms.ListBox
# Standard-Einstellungen
$this.control.DisplayMember = 'BaseName'
$this.control.ValueMember = 'FullName'
$this.control.Dock = 'Fill'
$this.control.Font = New-Object System.Drawing.Font("Segoe UI", $this.GetSetting("FontSize"))
}
[ListBoxBuilder] SetDock([System.String]$dock) {
$this.control.Dock = [System.Windows.Forms.DockStyle]::$dock
return $this
}
[ListBoxBuilder] SetFont([System.String]$family, [float]$size) {
$this.control.Font = New-Object System.Drawing.Font($family, $size)
return $this
}
[ListBoxBuilder] SetFont([System.String]$family, [float]$size, [System.Drawing.FontStyle]$style) {
$this.control.Font = New-Object System.Drawing.Font($family, $size, $style)
return $this
}
[ListBoxBuilder] SetSelectionMode([System.String]$mode) {
$this.control.SelectionMode = [System.Windows.Forms.SelectionMode]::$mode
return $this
}
[ListBoxBuilder] SetBackColor([System.Drawing.Color]$color) {
$this.control.BackColor = $color
return $this
}
[ListBoxBuilder] SetForeColor([System.Drawing.Color]$color) {
$this.control.ForeColor = $color
return $this
}
[ListBoxBuilder] SetBorderStyle([System.String]$style) {
$this.control.BorderStyle = [System.Windows.Forms.BorderStyle]::$style
return $this
}
[ListBoxBuilder] SetHorizontalScrollbar([bool]$show) {
$this.control.HorizontalScrollbar = $show
return $this
}
[ListBoxBuilder] SetIntegralHeight([bool]$integral) {
$this.control.IntegralHeight = $integral
return $this
}
[ListBoxBuilder] SetSorted([bool]$sorted) {
$this.control.Sorted = $sorted
return $this
}
[ListBoxBuilder] SetHeight([Int]$height) {
$this.control.Height = $height
return $this
}
[ListBoxBuilder] AddItem([object]$item) {
$this.control.Items.Add($item) | Out-Null
return $this
}
[ListBoxBuilder] AddItems([object[]]$items) {
foreach ($item in $items) {
$this.control.Items.Add($item) | Out-Null
}
return $this
}
[ListBoxBuilder] ClearItems() {
$this.control.Items.Clear()
return $this
}
[ListBoxBuilder] SetDataSource([object]$dataSource) {
$this.control.DataSource = $dataSource
return $this
}
[ListBoxBuilder] SetDisplayMember([System.String]$member) {
$this.control.DisplayMember = $member
return $this
}
[ListBoxBuilder] SetValueMember([System.String]$member) {
$this.control.ValueMember = $member
return $this
}
[ListBoxBuilder] AddSelectedIndexChangedHandler([scriptblock]$handler) {
$this.control.Add_SelectedIndexChanged($handler)
return $this
}
[ListBoxBuilder] AddMouseDoubleClickHandler([scriptblock]$handler) {
$this.control.Add_MouseDoubleClick($handler)
return $this
}
[ListBoxBuilder] AddEventHandler([System.String]$eventName, [scriptblock]$handler) {
$this.control."Add_$eventName"($handler)
return $this
}
[System.Windows.Forms.ListBox] AddTo([System.Windows.Forms.Control]$parent) {
$parent.Controls.Add($this.control)
return $this.control
}
[System.Windows.Forms.ListBox] Build() {
return $this.control
}
}
class PanelBuilder : BaseComponent{
[System.Windows.Forms.Panel]$control
[scriptblock] $EnableCondition = $null
[StateManager] $StateManager = $null
PanelBuilder() {
$this.control = New-Object System.Windows.Forms.Panel
}
[PanelBuilder] SetDock([System.String]$dock) {
$this.control.Dock = [System.Windows.Forms.DockStyle]::$dock
return $this
}
[PanelBuilder] SetWidth([int]$width) {
$this.control.Width = $width
return $this
}
[PanelBuilder] SetHeight([int]$height) {
$this.control.Height = $height
return $this
}
[PanelBuilder] SetSize([int]$width, [int]$height) {
$this.control.Size = New-Object System.Drawing.Size($width, $height)
return $this
}
[PanelBuilder] SetLocation([int]$x, [int]$y) {
$this.control.Location = New-Object System.Drawing.Point($x, $y)
return $this
}
[PanelBuilder] SetBackColor([System.Drawing.Color]$color) {
$this.control.BackColor = $color
return $this
}
[PanelBuilder] SetForeColor([System.Drawing.Color]$color) {
$this.control.ForeColor = $color
return $this
}
[PanelBuilder] SetBorderStyle([System.String]$style) {
$this.control.BorderStyle = [System.Windows.Forms.BorderStyle]::$style
return $this
}
[PanelBuilder] SetAutoScroll([bool]$autoScroll) {
$this.control.AutoScroll = $autoScroll
return $this
}
[PanelBuilder] SetPadding([int]$all) {
$this.control.Padding = New-Object System.Windows.Forms.Padding($all)
return $this
}
[PanelBuilder] SetPadding([int]$left, [int]$top, [int]$right, [int]$bottom) {
$this.control.Padding = New-Object System.Windows.Forms.Padding($left, $top, $right, $bottom)
return $this
}
[PanelBuilder] SetMargin([int]$all) {
$this.control.Margin = New-Object System.Windows.Forms.Padding($all)
return $this
}
[PanelBuilder] SetMargin([int]$left, [int]$top, [int]$right, [int]$bottom) {
$this.control.Margin = New-Object System.Windows.Forms.Padding($left, $top, $right, $bottom)
return $this
}
[PanelBuilder] SetAnchor([System.Windows.Forms.AnchorStyles]$anchor) {
$this.control.Anchor = $anchor
return $this
}
[PanelBuilder] SetVisible([bool]$visible) {
$this.control.Visible = $visible
return $this
}
[PanelBuilder] SetEnabled([bool]$enabled) {
$this.control.Enabled = $enabled
return $this
}
[PanelBuilder] SetAutoSize([bool]$autoSize) {
$this.control.AutoSize = $autoSize
return $this
}
[PanelBuilder] SetAutoSizeMode([System.String]$mode) {
$this.control.AutoSizeMode = [System.Windows.Forms.AutoSizeMode]::$mode
return $this
}
[PanelBuilder] AddControl([System.Windows.Forms.Control]$childControl) {
$this.control.Controls.Add($childControl)
return $this
}
[PanelBuilder] AddControls([System.Windows.Forms.Control[]]$controls) {
foreach ($ctrl in $controls) {
$this.control.Controls.Add($ctrl)
}
return $this
}
[PanelBuilder] ClearControls() {
$this.control.Controls.Clear()
return $this
}
[PanelBuilder] AddEventHandler([System.String]$eventName, [scriptblock]$handler) {
$this.control."Add_$eventName"($handler)
return $this
}
[PanelBuilder] SetName([System.String]$name) {
$this.control.Name = $name
return $this
}
[PanelBuilder] SetTag([object]$tag) {
$this.control.Tag = $tag
return $this
}
[System.Windows.Forms.Panel] AddTo([System.Windows.Forms.Control]$parent) {
$parent.Controls.Add($this.control)
return $this.control
}
[PanelBuilder] BindEnabled([scriptblock]$condition, [StateManager]$stateManager) {
$this.EnableCondition = $condition
$this.StateManager = $stateManager
$this.UpdateVisibleState()
return $this
}
# Aktualisiert den Visible-Status basierend auf der Bedingung
[void] UpdateVisibleState() {
if ($null -ne $this.EnableCondition) {
try {
$result = & $this.EnableCondition
$this.control.Visible = [bool]$result
} catch {
Write-Warning "Fehler beim Evaluieren der Visible-Bedingung: $_"
$this.control.Visible = $false
}
}
}
[System.Windows.Forms.Panel] Build() {
if ($null -ne $this.StateManager -and $null -ne $this.EnableCondition) {
$this.StateManager.RegisterForm($this)
}
return $this.control
}
[System.Windows.Forms.Panel] GetPanel() {
return $this.control
}
}
class DialogBuilder : BaseComponent {
[object] $Dialog # Kann FileDialog oder FolderBrowserDialog sein
[System.String] $DialogType
# Privater Konstruktor
hidden DialogBuilder([System.String]$type) {
$this.DialogType = $type
switch ($type) {
"Open" {
$this.Dialog = New-Object System.Windows.Forms.OpenFileDialog
$this.Dialog.Multiselect = $false
$this.Dialog.Filter = "Alle Dateien (*.*)|*.*"
$this.Dialog.FilterIndex = 1
$this.Dialog.RestoreDirectory = $true
}
"Save" {
$this.Dialog = New-Object System.Windows.Forms.SaveFileDialog
$this.Dialog.OverwritePrompt = $true
$this.Dialog.Filter = "Alle Dateien (*.*)|*.*"
$this.Dialog.FilterIndex = 1
$this.Dialog.RestoreDirectory = $true
}
"Folder" {
$this.Dialog = New-Object System.Windows.Forms.FolderBrowserDialog
$this.Dialog.ShowNewFolderButton = $true
}
}
}
# === FACTORY-METHODEN ===
static [DialogBuilder] OpenFile() {
return [DialogBuilder]::new("Open")
}
static [DialogBuilder] SaveFile() {
return [DialogBuilder]::new("Save")
}
static [DialogBuilder] SelectFolder() {
return [DialogBuilder]::new("Folder")
}
# === GEMEINSAME METHODEN (FileDialog) ===
# Setzt den Titel
[DialogBuilder] SetTitle([System.String]$title) {
if ($this.DialogType -eq "Folder") {
$this.Dialog.Description = $title
} else {
$this.Dialog.Title = $title
}
return $this
}
# Setzt den Filter (nur File-Dialoge)
[DialogBuilder] SetFilter([System.String]$filter) {
if ($this.DialogType -ne "Folder") {
$this.Dialog.Filter = $filter
} else {
Write-Warning "Filter ist nur für File-Dialoge verfügbar"
}
return $this
}
# Setzt den aktiven Filter-Index (nur File-Dialoge)
[DialogBuilder] SetFilterIndex([int]$index) {
if ($this.DialogType -ne "Folder") {
$this.Dialog.FilterIndex = $index
}
return $this
}
# Setzt das Initial-Verzeichnis
[DialogBuilder] SetInitialDirectory([System.String]$path) {
if ($this.DialogType -eq "Folder") {
if (Test-Path $path) {
$this.Dialog.SelectedPath = $path
} else {
Write-Warning "Pfad existiert nicht: $path"
}
} else {
if (Test-Path $path) {
$this.Dialog.InitialDirectory = $path
} else {
Write-Warning "Pfad existiert nicht: $path"
}
}
return $this
}
# Setzt den Standard-Dateinamen (nur File-Dialoge)
[DialogBuilder] SetFileName([System.String]$fileName) {
if ($this.DialogType -ne "Folder") {
$this.Dialog.FileName = $fileName
}
return $this
}
# Prüft ob Datei existieren muss (nur File-Dialoge)
[DialogBuilder] SetCheckFileExists([bool]$check) {
if ($this.DialogType -ne "Folder") {
$this.Dialog.CheckFileExists = $check
}
return $this
}
# Prüft ob Pfad existieren muss (nur File-Dialoge)
[DialogBuilder] SetCheckPathExists([bool]$check) {
if ($this.DialogType -ne "Folder") {
$this.Dialog.CheckPathExists = $check
}
return $this
}
# Wiederherstellt letztes Verzeichnis (nur File-Dialoge)
[DialogBuilder] SetRestoreDirectory([bool]$restore) {
if ($this.DialogType -ne "Folder") {
$this.Dialog.RestoreDirectory = $restore
}
return $this
}
# Validiert Namen gegen ungültige Zeichen (nur File-Dialoge)
[DialogBuilder] SetValidateNames([bool]$validate) {
if ($this.DialogType -ne "Folder") {
$this.Dialog.ValidateNames = $validate
}
return $this
}
# Dereferenziert Links/Shortcuts (nur File-Dialoge)
[DialogBuilder] SetDereferenceLinks([bool]$dereference) {
if ($this.DialogType -ne "Folder") {
$this.Dialog.DereferenceLinks = $dereference
}
return $this
}
# Setzt die Standard-Erweiterung (nur File-Dialoge)
[DialogBuilder] SetDefaultExt([System.String]$ext) {
if ($this.DialogType -ne "Folder") {
$this.Dialog.DefaultExt = $ext.TrimStart('.')
}
return $this
}
# Fügt automatisch Erweiterung hinzu (nur File-Dialoge)
[DialogBuilder] SetAddExtension([bool]$add) {
if ($this.DialogType -ne "Folder") {
$this.Dialog.AddExtension = $add
}
return $this
}
# Setzt Custom Places (nur File-Dialoge)
[DialogBuilder] AddCustomPlace([System.String]$path) {
if ($this.DialogType -ne "Folder") {
if (Test-Path $path) {
$this.Dialog.CustomPlaces.Add($path)
}
}
return $this
}
# Setzt mehrere Custom Places (nur File-Dialoge)
[DialogBuilder] AddCustomPlaces([System.String[]]$paths) {
if ($this.DialogType -ne "Folder") {
foreach ($path in $paths) {
if (Test-Path $path) {
$this.Dialog.CustomPlaces.Add($path)
}
}
}
return $this
}
# === OPENFILEDIALOG-SPEZIFISCH ===
# Aktiviert/Deaktiviert Mehrfachauswahl
[DialogBuilder] SetMultiselect([bool]$multiselect) {
if ($this.DialogType -eq "Open") {
$this.Dialog.Multiselect = $multiselect
} else {
Write-Warning "Multiselect ist nur für OpenFileDialog verfügbar"
}
return $this
}
# Zeigt Read-Only Checkbox
[DialogBuilder] SetShowReadOnly([bool]$show) {
if ($this.DialogType -eq "Open") {
$this.Dialog.ShowReadOnly = $show
}
return $this
}
# Setzt Read-Only Status
[DialogBuilder] SetReadOnlyChecked([bool]$checked) {
if ($this.DialogType -eq "Open") {
$this.Dialog.ReadOnlyChecked = $checked
}
return $this
}
# === SAVEFILEDIALOG-SPEZIFISCH ===
# Warnt bei Überschreiben
[DialogBuilder] SetOverwritePrompt([bool]$prompt) {
if ($this.DialogType -eq "Save") {
$this.Dialog.OverwritePrompt = $prompt
}
return $this
}
# Warnt beim Erstellen neuer Dateien
[DialogBuilder] SetCreatePrompt([bool]$prompt) {
if ($this.DialogType -eq "Save") {
$this.Dialog.CreatePrompt = $prompt
}
return $this
}
# === FOLDERBROWSERDIALOG-SPEZIFISCH ===
# Zeigt "Neuer Ordner"-Button
[DialogBuilder] SetShowNewFolderButton([bool]$show) {
if ($this.DialogType -eq "Folder") {
$this.Dialog.ShowNewFolderButton = $show
}
return $this
}
# Setzt die Beschreibung (Folder-spezifisch)
[DialogBuilder] SetDescription([System.String]$description) {
if ($this.DialogType -eq "Folder") {
$this.Dialog.Description = $description
}
return $this
}
# Setzt den Root-Folder (Folder-spezifisch)
[DialogBuilder] SetRootFolder([System.String]$specialFolder) {
if ($this.DialogType -eq "Folder") {
try {
$this.Dialog.RootFolder = [System.Environment+SpecialFolder]::$specialFolder
} catch {
Write-Warning "Ungültiger SpecialFolder: $specialFolder"
}
}
return $this
}
# Setzt den ausgewählten Pfad (Folder-spezifisch)
[DialogBuilder] SetSelectedPath([System.String]$path) {
if ($this.DialogType -eq "Folder") {
if (Test-Path $path) {
$this.Dialog.SelectedPath = $path
} else {
Write-Warning "Pfad existiert nicht: $path"
}
}
return $this
}
# Verwendet die neue Folder-Browser-Darstellung (Vista-Style)
[DialogBuilder] SetUseDescriptionForTitle([bool]$use) {
if ($this.DialogType -eq "Folder") {
$this.Dialog.UseDescriptionForTitle = $use
}
return $this
}
# === VOREINGESTELLTE FILTER ===
# Schnell-Methode für häufige Filter (nur File-Dialoge)
[DialogBuilder] SetCommonFilter([System.String]$type) {
if ($this.DialogType -eq "Folder") {
Write-Warning "Filter sind für FolderBrowserDialog nicht verfügbar"
return $this
}
switch ($type) {
'Text' {
$this.Dialog.Filter = "Text-Dateien (*.txt)|*.txt|Alle Dateien (*.*)|*.*"
$this.Dialog.DefaultExt = "txt"
}
'PowerShell' {
$this.Dialog.Filter = "PowerShell-Dateien (*.ps1;*.psm1;*.psd1)|*.ps1;*.psm1;*.psd1|Alle Dateien (*.*)|*.*"
$this.Dialog.DefaultExt = "ps1"
}
'PSD1' {
$this.Dialog.Filter = "PowerShell Data-Dateien (*.psd1)|*.psd1|Alle Dateien (*.*)|*.*"
$this.Dialog.DefaultExt = "psd1"
}
'JSON' {
$this.Dialog.Filter = "JSON-Dateien (*.json)|*.json|Alle Dateien (*.*)|*.*"
$this.Dialog.DefaultExt = "json"
}
'XML' {
$this.Dialog.Filter = "XML-Dateien (*.xml)|*.xml|Alle Dateien (*.*)|*.*"
$this.Dialog.DefaultExt = "xml"
}
'CSV' {
$this.Dialog.Filter = "CSV-Dateien (*.csv)|*.csv|Alle Dateien (*.*)|*.*"
$this.Dialog.DefaultExt = "csv"
}
'Excel' {
$this.Dialog.Filter = "Excel-Dateien (*.xlsx;*.xls)|*.xlsx;*.xls|Alle Dateien (*.*)|*.*"
$this.Dialog.DefaultExt = "xlsx"
}
'Image' {
$this.Dialog.Filter = "Bild-Dateien (*.png;*.jpg;*.jpeg;*.gif;*.bmp)|*.png;*.jpg;*.jpeg;*.gif;*.bmp|Alle Dateien (*.*)|*.*"
$this.Dialog.DefaultExt = "png"
}
'All' {
$this.Dialog.Filter = "Alle Dateien (*.*)|*.*"
}
default {
Write-Warning "Unbekannter Filter-Typ: $type"
}
}
return $this
}
# === SHOW UND BUILD ===
# Zeigt den Dialog und gibt das Ergebnis zurück
[System.Collections.Hashtable] Show() {
$result = @{
Result = $false
FileName = $null
FileNames = @()
SafeFileName = $null
SafeFileNames = @()
SelectedPath = $null
}
$dialogResult = $this.Dialog.ShowDialog()
if ($dialogResult -eq 'OK') {
$result.Result = $true
if ($this.DialogType -eq "Folder") {
$result.SelectedPath = $this.Dialog.SelectedPath
$result.FileName = $this.Dialog.SelectedPath
} else {
$result.FileName = $this.Dialog.FileName
$result.SafeFileName = $this.Dialog.SafeFileName
if ($this.DialogType -eq "Open") {
$result.FileNames = $this.Dialog.FileNames
$result.SafeFileNames = $this.Dialog.SafeFileNames
} else {
$result.FileNames = @($this.Dialog.FileName)
$result.SafeFileNames = @($this.Dialog.SafeFileName)
}
}
}
return $result
}
# Zeigt den Dialog mit Custom Parent Window
[System.Collections.Hashtable] Show([System.Windows.Forms.IWin32Window]$owner) {
$result = @{
Result = $false
FileName = $null
FileNames = @()
SafeFileName = $null
SafeFileNames = @()
SelectedPath = $null
}
$dialogResult = $this.Dialog.ShowDialog($owner)
if ($dialogResult -eq 'OK') {
$result.Result = $true
if ($this.DialogType -eq "Folder") {
$result.SelectedPath = $this.Dialog.SelectedPath
$result.FileName = $this.Dialog.SelectedPath
} else {
$result.FileName = $this.Dialog.FileName
$result.SafeFileName = $this.Dialog.SafeFileName
if ($this.DialogType -eq "Open") {
$result.FileNames = $this.Dialog.FileNames
$result.SafeFileNames = $this.Dialog.SafeFileNames
} else {
$result.FileNames = @($this.Dialog.FileName)
$result.SafeFileNames = @($this.Dialog.SafeFileName)
}
}
}
return $result
}
# Gibt das Dialog-Objekt zurück (für erweiterte Szenarien)
[object] Build() {
return $this.Dialog
}
# Dispose des Dialogs
[void] Dispose() {
if ($null -ne $this.Dialog) {
$this.Dialog.Dispose()
}
}
}
class TemplateBuilder : BaseComponent{
[System.Collections.Specialized.OrderedDictionary] $Template
# Konstruktor: Pfad zu PSD1-Datei
TemplateBuilder([System.String]$TemplatePath) {
$this.Template = $this.ConvertFromPowerShellDataString($TemplatePath)
}
# Konstruktor: Hashtable direkt übergeben
TemplateBuilder([hashtable]$TemplateHashtable) {
$this.Template = $this.ConvertHashtableToOrdered($TemplateHashtable)
}
# Konstruktor: OrderedDictionary direkt übergeben
TemplateBuilder([System.Collections.Specialized.OrderedDictionary]$TemplateOrdered) {
$this.Template = $TemplateOrdered
}
# Hilfsmethode: Konvertiert eine normale Hashtable in OrderedDictionary (rekursiv)
hidden [System.Collections.Specialized.OrderedDictionary] ConvertHashtableToOrdered([hashtable]$Hashtable) {
$ordered = New-Object System.Collections.Specialized.OrderedDictionary
foreach ($key in $Hashtable.Keys) {
$value = $Hashtable[$key]
# Rekursive Konvertierung für verschachtelte Hashtables
if ($value -is [hashtable]) {
$ordered[$key] = $this.ConvertHashtableToOrdered($value)
}
# Array mit Hashtables
elseif ($value -is [array]) {
$arrayResult = @()
foreach ($item in $value) {
if ($item -is [hashtable]) {
$arrayResult += $this.ConvertHashtableToOrdered($item)
}
else {
$arrayResult += $item
}
}
$ordered[$key] = $arrayResult
}
else {
$ordered[$key] = $value
}
}
return $ordered
}
# Concat mit einer dynamischen Anzahl von Argumenten
static [string] Concat([object[]]$input) {
return (($input | ForEach-Object { [string]$_ }) -join '')
}
# ToLower-Methode
static [string] ToLower([object[]]$input) {
if ($input.Count -lt 1) {
return ""
}
return ([string]$input[0]).ToLowerInvariant()
}
# ToUpper-Methode
static [string] ToUpper([object[]]$input) {
if ($input.Count -lt 1) {
return ""
}
return ([string]$input[0]).ToUpperInvariant()
}
# FirstIndexOf-Methode
static [string] FirstIndexOf([object[]] $input){
if ($input.Count -lt 1) {
return ""
}
return [string]$input[0]
}
# LastIndexOf-Methode
static [string] LastIndexOf([object[]] $input){
if ($input.Count -lt 1) {
return ""
}
return [string]$input[-1]
}
# IndexOf-Methode
static [string] IndexOf([object[]] $input){
if ($input.Count -lt 2) {
throw "IndexOf benötigt mindestens zwei Argumente."
}
return [string]$input[[int]$input[-1]]
}
# Substring-Methode
static [String] Substring([object[]] $input){
if($input.Count -eq 2){
return ([string]$input[0]).Substring([int]$input[1])
}elseif($input.Count -eq 3){
return ([string]$input[0]).Substring([int]$input[1],[int]$input[2])
}else{
throw "Substring erwartet zwei oder drei Argumente."
}
}
# Replace-Methode
static [String] Replace([object[]] $input){
if ($input.Count -lt 3) {
throw "Replace erwartet drei Argumente."
}
return ([string]$input[0]).Replace([string]$input[1],[string]$input[2])
}
hidden [System.Collections.Specialized.OrderedDictionary] ResolveDeploymentParameterDefaultValues(){
$TemplateClone = $this.Template
if($TemplateClone.Contains("Parameters")){
foreach($Parameter in $this.Template.Parameters.GetEnumerator()){
if(!$Parameter.Value.Contains("Value")){
$TemplateClone.Parameters[$Parameter.Name].Value = $this.Template.Parameters[$Parameter.Name].DefaultValue
}
}
}
return $TemplateClone
}
[System.Collections.Specialized.OrderedDictionary] ResolveDeploymentDataVariables(){
$TemplateClone = $this.ResolveDeploymentParameterDefaultValues()
# Erst Variables auflösen (können Parameter-Referenzen enthalten)
if ($TemplateClone.Variables) {
$resolvedVariables = New-Object System.Collections.Specialized.OrderedDictionary
# WICHTIG: Keys-Array erstellen, um Collection-Modification zu vermeiden
$varKeys = @($TemplateClone.Variables.Keys)
foreach ($varKey in $varKeys) {
$resolvedVariables[$varKey] = $this.ResolveValue($TemplateClone.Variables[$varKey],$TemplateClone.Parameters,$TemplateClone.Variables)
}
$TemplateClone.Variables = $resolvedVariables
}
# Dann den Rest des Templates auflösen
# WICHTIG: Keys-Array erstellen, um Collection-Modification zu vermeiden
$templateKeys = @($TemplateClone.Keys)
foreach ($key in $templateKeys) {
if ($key -ne 'Variables' -and $key -ne 'Parameters') {
$TemplateClone[$key] = $this.ResolveValue($TemplateClone[$key],$TemplateClone.Parameters,$TemplateClone.Variables)
}
}
return $TemplateClone
}
hidden [System.Collections.Specialized.OrderedDictionary] ConvertFromPowerShellDataString($TemplatePath){
$errors = $null
$tokens = $null
$ast = [System.Management.Automation.Language.Parser]::ParseFile(
$TemplatePath,
[ref]$tokens,
[ref]$errors
)
if ($errors) {
throw "Fehler beim Parsen der Datei: $($errors[0].Message)"
}
$hashtableAst = $ast.Find({
$args[0] -is [System.Management.Automation.Language.HashtableAst]
}, $true)
if (-not $hashtableAst) {
throw "Keine Hashtable im $TemplatePath gefunden"
}
$this.Template = $this.ConvertToOrderedHashtable($hashtableAst)
return $this.Template
}
hidden [System.Collections.Specialized.OrderedDictionary] ConvertToOrderedHashtable([System.Management.Automation.Language.HashtableAst]$HashtableAst){
$ordered = New-Object System.Collections.Specialized.OrderedDictionary
$sortedKvps = $HashtableAst.KeyValuePairs | Sort-Object { $_.Item1.Extent.StartOffset }
foreach ($kvp in $sortedKvps) {
$key = [string]$this.ConvertAstValue($kvp.Item1)
$value = $this.ConvertAstValue($kvp.Item2)
$ordered.Add($key, $value)
}
return $ordered
}
hidden [System.Object] ConvertAstValue([System.Management.Automation.Language.Ast]$Ast) {
if ($null -eq $Ast) {
return $null
}
if ($Ast -is [System.Management.Automation.Language.PipelineAst]) {
if ($Ast.PipelineElements.Count -eq 1 -and $Ast.PipelineElements[0] -is [System.Management.Automation.Language.CommandExpressionAst]) {
return $this.ConvertAstValue($Ast.PipelineElements[0].Expression)
}
return $Ast.SafeGetValue()
}
if ($Ast -is [System.Management.Automation.Language.CommandExpressionAst]) {
return $this.ConvertAstValue($Ast.Expression)
}
if ($Ast -is [System.Management.Automation.Language.ParenExpressionAst]) {
return $this.ConvertAstValue($Ast.Pipeline)
}
if ($Ast -is [System.Management.Automation.Language.ArrayExpressionAst]) {
return $this.ConvertAstValue($Ast.SubExpression)
}
if ($Ast -is [System.Management.Automation.Language.StatementBlockAst]) {
if ($Ast.Statements.Count -eq 1 -and $Ast.Statements[0] -is [System.Management.Automation.Language.PipelineAst]) {
return $this.ConvertAstValue($Ast.Statements[0])
}
throw "Nicht unterstützter Ausdruck in PSD1-Datei: $($Ast.Extent.Text)"
}
if ($Ast -is [System.Management.Automation.Language.ArrayLiteralAst]) {
$result = @()
foreach ($element in $Ast.Elements) {
$result += $this.ConvertAstValue($element)
}
return $result
}
if ($Ast -is [System.Management.Automation.Language.HashtableAst]) {
return $this.ConvertToOrderedHashtable($Ast)
}
if ($Ast -is [System.Management.Automation.Language.VariableExpressionAst]) {
switch ($Ast.VariablePath.UserPath) {
'true' { return $true }
'false' { return $false }
'null' { return $null }
default { return $Ast.Extent.Text }
}
}
try {
return $Ast.SafeGetValue()
}
catch {
return $Ast.Extent.Text
}
}
hidden [System.Object] ResolveValue($Value, $Parameters, $Variables){
$resolutionStack = [System.Collections.Generic.List[string]]::new()
return $this.ResolveValueInternal($Value, $Parameters, $Variables, $resolutionStack)
}
hidden [System.Object] ResolveValueInternal($Value, $Parameters, $Variables, [System.Collections.Generic.List[string]]$ResolutionStack){
if ($Value -is [string]) {
$trimmedValue = $Value.Trim()
if ($this.IsTemplateExpression($trimmedValue)) {
return $this.EvaluateTemplateExpression($trimmedValue.Substring(1, $trimmedValue.Length - 2), $Parameters, $Variables, $ResolutionStack)
}
return $this.ResolveInlineTemplateExpressions($Value, $Parameters, $Variables, $ResolutionStack)
}
elseif ($Value -is [System.Collections.IDictionary]) {
$resolved = New-Object System.Collections.Specialized.OrderedDictionary
foreach ($key in $Value.Keys) {
$resolved[$key] = $this.ResolveValueInternal($Value[$key], $Parameters, $Variables, $ResolutionStack)
}
return $resolved
}
elseif ($Value -is [array]) {
$resolved = @()
foreach ($item in $Value) {
$resolved += $this.ResolveValueInternal($item, $Parameters, $Variables, $ResolutionStack)
}
return $resolved
}
else {
return $Value
}
}
hidden [bool] IsTemplateExpression([string]$Value) {
if ([string]::IsNullOrWhiteSpace($Value)) {
return $false
}
if (-not ($Value.StartsWith('[') -and $Value.EndsWith(']'))) {
return $false
}
return $this.IsFunctionInvocation($Value.Substring(1, $Value.Length - 2))
}
hidden [bool] IsFunctionInvocation([string]$Value) {
return $Value.Trim() -match '^[A-Za-z_][A-Za-z0-9_]*\s*\(.*\)$'
}
hidden [string] ResolveInlineTemplateExpressions([string]$Value, $Parameters, $Variables, [System.Collections.Generic.List[string]]$ResolutionStack) {
$resolved = $Value
$matches = [regex]::Matches($Value, '\[[^\[\]]+\]')
for ($i = $matches.Count - 1; $i -ge 0; $i--) {
$match = $matches[$i]
$expressionText = $match.Value.Substring(1, $match.Value.Length - 2)
if (-not $this.IsFunctionInvocation($expressionText)) {
continue
}
$replacement = $this.EvaluateTemplateExpression($expressionText, $Parameters, $Variables, $ResolutionStack)
$resolved = $resolved.Remove($match.Index, $match.Length).Insert($match.Index, [string]$replacement)
}
return $resolved
}
hidden [System.Object] EvaluateTemplateExpression([string]$ExpressionText, $Parameters, $Variables, [System.Collections.Generic.List[string]]$ResolutionStack) {
$trimmedExpression = $ExpressionText.Trim()
if ($trimmedExpression -notmatch '^([A-Za-z_][A-Za-z0-9_]*)\s*\((.*)\)$') {
return $ExpressionText
}
$functionName = $matches[1]
$argumentsText = $matches[2]
$resolvedArguments = @()
$result = $null
foreach ($argument in $this.SplitExpressionArguments($argumentsText)) {
$resolvedArguments += ,($this.ResolveExpressionToken($argument, $Parameters, $Variables, $ResolutionStack))
}
switch ($functionName.ToLowerInvariant()) {
'parameter' { $result = $this.GetParameterValue([string]$resolvedArguments[0], $Parameters); break }
'parameters' { $result = $this.GetParameterValue([string]$resolvedArguments[0], $Parameters); break }
'variable' { $result = $this.GetVariableValue([string]$resolvedArguments[0], $Parameters, $Variables, $ResolutionStack); break }
'variables' { $result = $this.GetVariableValue([string]$resolvedArguments[0], $Parameters, $Variables, $ResolutionStack); break }
'concat' { $result = [TemplateBuilder]::Concat($resolvedArguments); break }
'tolower' { $result = [TemplateBuilder]::ToLower($resolvedArguments); break }
'toupper' { $result = [TemplateBuilder]::ToUpper($resolvedArguments); break }
'firstindexof' { $result = [TemplateBuilder]::FirstIndexOf($resolvedArguments); break }
'lastindexof' { $result = [TemplateBuilder]::LastIndexOf($resolvedArguments); break }
'indexof' { $result = [TemplateBuilder]::IndexOf($resolvedArguments); break }
'substring' { $result = [TemplateBuilder]::Substring($resolvedArguments); break }
'replace' { $result = [TemplateBuilder]::Replace($resolvedArguments); break }
default {
throw "Nicht unterstützte Template-Funktion '$functionName'"
return $null
}
}
return $result
}
hidden [string[]] SplitExpressionArguments([string]$ArgumentsText) {
$arguments = New-Object 'System.Collections.Generic.List[string]'
if ([string]::IsNullOrWhiteSpace($ArgumentsText)) {
return $arguments.ToArray()
}
$builder = New-Object System.Text.StringBuilder
$depth = 0
$inSingleQuote = $false
$inDoubleQuote = $false
for ($i = 0; $i -lt $ArgumentsText.Length; $i++) {
$char = $ArgumentsText[$i]
if ($char -eq "'" -and -not $inDoubleQuote) {
[void]$builder.Append($char)
if ($inSingleQuote -and $i + 1 -lt $ArgumentsText.Length -and $ArgumentsText[$i + 1] -eq "'") {
$i++
[void]$builder.Append($ArgumentsText[$i])
continue
}
$inSingleQuote = -not $inSingleQuote
continue
}
if ($char -eq '"' -and -not $inSingleQuote) {
$inDoubleQuote = -not $inDoubleQuote
[void]$builder.Append($char)
continue
}
if (-not $inSingleQuote -and -not $inDoubleQuote) {
if ($char -eq '(') {
$depth++
}
elseif ($char -eq ')') {
$depth--
}
elseif ($char -eq ',' -and $depth -eq 0) {
$arguments.Add($builder.ToString().Trim())
[void]$builder.Clear()
continue
}
}
[void]$builder.Append($char)
}
if ($builder.Length -gt 0 -or $ArgumentsText.Trim().Length -gt 0) {
$arguments.Add($builder.ToString().Trim())
}
return $arguments.ToArray()
}
hidden [System.Object] ResolveExpressionToken([string]$Token, $Parameters, $Variables, [System.Collections.Generic.List[string]]$ResolutionStack) {
$trimmedToken = $Token.Trim()
if ([string]::IsNullOrWhiteSpace($trimmedToken)) {
return ''
}
if ($this.IsTemplateExpression($trimmedToken)) {
return $this.EvaluateTemplateExpression($trimmedToken.Substring(1, $trimmedToken.Length - 2), $Parameters, $Variables, $ResolutionStack)
}
if ($this.IsFunctionInvocation($trimmedToken)) {
return $this.EvaluateTemplateExpression($trimmedToken, $Parameters, $Variables, $ResolutionStack)
}
if (($trimmedToken.StartsWith("'") -and $trimmedToken.EndsWith("'")) -or ($trimmedToken.StartsWith('"') -and $trimmedToken.EndsWith('"'))) {
return $this.UnquoteString($trimmedToken)
}
if ($trimmedToken -match '^\$?true$') {
return $true
}
if ($trimmedToken -match '^\$?false$') {
return $false
}
if ($trimmedToken -match '^\$?null$') {
return $null
}
if ($trimmedToken -match '^-?\d+$') {
return [int]$trimmedToken
}
if ($trimmedToken -match '^-?\d+\.\d+$') {
return [double]$trimmedToken
}
return $trimmedToken
}
hidden [string] UnquoteString([string]$Value) {
if ($Value.StartsWith("'") -and $Value.EndsWith("'")) {
return ($Value.Substring(1, $Value.Length - 2) -replace "''", "'")
}
if ($Value.StartsWith('"') -and $Value.EndsWith('"')) {
return $Value.Substring(1, $Value.Length - 2)
}
return $Value
}
hidden [System.Object] GetParameterValue([string]$ParameterName, $Parameters) {
if ($null -eq $Parameters -or -not $Parameters.Contains($ParameterName)) {
throw "Parameter '$ParameterName' nicht gefunden"
}
$parameter = $Parameters[$ParameterName]
if ($parameter -is [System.Collections.IDictionary]) {
if ($parameter.Contains('Value') -and $null -ne $parameter.Value) {
return $parameter.Value
}
if ($parameter.Contains('DefaultValue')) {
return $parameter.DefaultValue
}
}
return $parameter
}
hidden [System.Object] GetVariableValue([string]$VariableName, $Parameters, $Variables, [System.Collections.Generic.List[string]]$ResolutionStack) {
if ($null -eq $Variables -or -not $Variables.Contains($VariableName)) {
throw "Variable '$VariableName' nicht gefunden"
return $null
}
if ($ResolutionStack.Contains($VariableName)) {
$cycle = @($ResolutionStack.ToArray()) + $VariableName
throw "Zirkuläre Variablenreferenz erkannt: $($cycle -join ' -> ')"
return $null
}
$ResolutionStack.Add($VariableName)
$resolvedValue = $null
try {
$resolvedValue = $this.ResolveValueInternal($Variables[$VariableName], $Parameters, $Variables, $ResolutionStack)
}
finally {
[void]$ResolutionStack.Remove($VariableName)
}
return $resolvedValue
}
}
class TabControlBuilder : BaseComponent{
[System.Windows.Forms.TabControl] $control
TabControlBuilder() {
$this.control = New-Object System.Windows.Forms.TabControl
}
[TabControlBuilder] SetDock([System.String]$dock) {
$this.control.Dock = [System.Windows.Forms.DockStyle]::$dock
return $this
}
[TabControlBuilder] SetWidth([Int]$width) {
$this.control.Width = $width
return $this
}
[TabControlBuilder] SetVisible([Boolean]$visible) {
$this.control.Visible = $visible
return $this
}
[TabControlBuilder] SetSelectedIndex([int]$index) {
$this.control.SelectedIndex = $index
return $this
}
[TabControlBuilder] AddTabPage([System.Windows.Forms.TabPage]$tabPage) {
$this.control.TabPages.Add($tabPage) | Out-Null
return $this
}
[System.Windows.Forms.TabControl] Build() {
return $this.control
}
}
class TabPageBuilder : BaseComponent{
[System.Windows.Forms.TabPage]$control
TabPageBuilder([System.String]$text) {
$this.control = New-Object System.Windows.Forms.TabPage
$this.control.Text = $text
}
[TabPageBuilder] SetPadding([int]$all) {
$this.control.Padding = New-Object System.Windows.Forms.Padding($all)
return $this
}
[TabPageBuilder] AddControl([System.Windows.Forms.Control]$childControl) {
$this.control.Controls.Add($childControl)
return $this
}
[void] AddTo([System.Windows.Forms.Control]$parent) {
$parent.Controls.Add($this.control)
}
[System.Windows.Forms.TabPage] Build() {
return $this.control
}
}
class ListViewBuilder : BaseComponent {
[System.Windows.Forms.ListView]$control
ListViewBuilder() {
$this.control = New-Object System.Windows.Forms.ListView
$this.control.View = 'Details'
}
[ListViewBuilder] SetDock([System.String]$dock) {
$this.control.Dock = [System.Windows.Forms.DockStyle]::$dock
return $this
}
[ListViewBuilder] SetView([System.String]$view) {
$this.control.View = [System.Windows.Forms.View]::$view
return $this
}
[ListViewBuilder] SetFullRowSelect([bool]$select) {
$this.control.FullRowSelect = $select
return $this
}
[ListViewBuilder] SetGridLines([bool]$gridLines) {
$this.control.GridLines = $gridLines
return $this
}
[ListViewBuilder] AddColumn([System.String]$text, [int]$width) {
$this.control.Columns.Add($text, $width) | Out-Null
return $this
}
[ListViewBuilder] AddDoubleClickHandler([scriptblock]$handler) {
$this.control.Add_DoubleClick($handler)
return $this
}
[System.Windows.Forms.ListView] Build() {
return $this.control
}
}
#endregion
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$settingsManager = [SettingsManager]::new("DSC Tool")
# Verwendung
$logManager = [LogManager]::new("DSC Tool")
$logManager.Info("Anwendung gestartet")
[BaseComponent]::InitializeShared($settingsManager, $logManager)
foreach($function in $(Get-ChildItem -Path $settingsManager.Get("FunctionsPath") -Recurse -Filter "*.ps1" -File)){
$logManager.Info("Lade Funktion: $($function.FullName)")
try{
. $function.FullName
}catch{
$logManager.Error("Fehler beim Laden: $_")
}
}
$stateManager = [StateManager]::new()
$stateManager.SetStates(@{
hasSelection = $false
isMerged = $false
isResolved = $false
})
# Menü erstellen
$menuBuilder = (
[MenuBuilder]::new().
BuildFromStructure($settingsManager.GetMenuStructure()).
WithStateManager($stateManager)
)
$menuHandlers = @{
"Import" = @{
Handler = {
Import-ConfigurationData
$statusBar.SetText("Status", "Deployment importiert.")
}
Condition = {
-not $stateManager.GetState("isMerged")
}
}
"Export" = @{
Handler = {
Export-ConfigurationData
$statusBar.SetText("Status", "Deployment exportiert.")
}
Condition = {
$stateManager.GetState("isMerged") -eq $true
}
}
"Refresh" = @{
Handler = {
$statusBar.SetText("Status", "Wird aktualisiert...")
}
}
"Exit" = {
$form.Form.Close()
}
"OpenFolder" = @{
Handler = {
$result = [DialogBuilder]::SelectFolder().
SetDescription("Wählen Sie den Root-Ordner für Templates").
SetSelectedPath($settingsManager.Get("RootPath", "C:\")).
SetShowNewFolderButton($true).
SetUseDescriptionForTitle($true).
Show()
if ($result.Result) {
$settingsManager.Set("RootPath", $result.SelectedPath)
$statusBar.SetText("Status", "Ordner gesetzt: $($result.SelectedPath)")
#Load-Templates
}
}
}
"ResetMenu" = {
$result = [System.Windows.Forms.MessageBox]::Show(
"Möchten Sie das Menü auf die Standardeinstellungen zurücksetzen?`n`nDie Anwendung wird danach neu gestartet.",
"Menü zurücksetzen",
[System.Windows.Forms.MessageBoxButtons]::YesNo,
[System.Windows.Forms.MessageBoxIcon]::Question
)
if ($result -eq 'Yes') {
$settingsManager.ResetMenuStructure()
[System.Windows.Forms.MessageBox]::Show(
"Menü wurde zurückgesetzt. Bitte starten Sie die Anwendung neu.",
"Erfolg",
[System.Windows.Forms.MessageBoxButtons]::OK,
[System.Windows.Forms.MessageBoxIcon]::Information
)
$form.Form.Close()
}
}
"About" = {
[System.Windows.Forms.MessageBox]::Show(
"DSC Tool v1.0`n`nEin modernes Tool zur Verwaltung von DSC-Konfigurationen.`n`n© 2024",
"Über DSC Tool",
[System.Windows.Forms.MessageBoxButtons]::OK,
[System.Windows.Forms.MessageBoxIcon]::Information
)
}
}
# Handler setzen
$menuBuilder.SetClickHandlersWithConditions($menuHandlers)
# StatusBar erstellen
$statusBar = [StatusStripBuilder]::new()
# FlowLayoutPanel erstellen
$flow = (
[FlowLayoutPanelBuilder]::new().
SetPadding(6).
Build()
)
## Rechte Seite
# Rechtes Label
$tabControl = (
[TabControlBuilder]::new().
SetDock("Fill").
Build()
)
$buttonClear = (
[ButtonBuilder]::new().
SetFluentIcon([char]0xed62).
SetToolTip("Clear").
Build()
)
$tabControlButtonPanel = (
[FlowLayoutPanelBuilder]::new().
SetDock("Right").
SetPadding(6).
SetWidth(52).
SetFlowDirection("TopDown").
SetWrapContents($false).
AddControls(@($buttonClear)).
Build()
)
$tabPanel = (
[PanelBuilder]::new().
SetDock("Top").
SetHeight(200).
BindEnabled({
$stateManager.GetState("isResolved") -eq $true
}, $stateManager).
AddControls(@($tabControl,$tabControlButtonPanel)).
Build()
)
$rightLabel = (
[LabelBuilder]::new("Datei-Inhalt / Details").
SetDock('Top').
SetHeight(24).
SetFont("Segoe UI", 9, [System.Drawing.FontStyle]::Bold).
SetTextAlign([System.Drawing.ContentAlignment]::MiddleLeft).
SetPadding(5, 0, 0, 0).
Build()
)
# TreeView
$treeView = (
[TreeViewBuilder]::new().
SetFont("Consolas", 10).
AddNode("Keine Auswahl").
Build()
)
$buttonImport = (
[ButtonBuilder]::new().
SetFluentIcon([char]0xed25).
SetToolTip("Import - Datei laden").
BindEnabled({
-not $stateManager.GetState("isMerged")
}, $stateManager).
SetClickHandler({
Import-ConfigurationData
}).
Build()
)
$buttonMerge = (
[ButtonBuilder]::new().
SetFluentIcon([char]0xe9f5).
SetToolTip("Merge - Ausgewählte Dateien zusammenführen").
BindEnabled({
$selectionList.Items.Count -gt 0 -and $stateManager.GetState("isMerged") -eq $false
}, $stateManager).
SetClickHandler({
param($s, $e)
if($selectionList.Items.Count -gt 0){
Merge-Templates
$stateManager.SetState("isResolved",$true)
}else{
[System.Windows.Forms.MessageBox]::Show("Keine Einträge vorhanden","Info",[System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Information)
}
}).
Build()
)
$buttonClear = (
[ButtonBuilder]::new().
SetFluentIcon([char]0xed62).
SetToolTip("Clear - TreeView leeren").
BindEnabled({
$treeView.Nodes.Count -gt 0
}, $stateManager).
SetClickHandler({
$treeView.Nodes.Clear()
$treeView.Nodes.Add("Keine Auswahl") | Out-Null
$statusBar.SetText("Status", "TreeView geleert")
$stateManager.SetStates(@{
"isMerged" = $false
"isResolved" = $false
})
}).
Build()
)
$buttonExport = (
[ButtonBuilder]::new().
SetFluentIcon([char]0xe74e).
SetToolTip("Export - Als PSD1 speichern").
BindEnabled({
$stateManager.GetState("isResolved") -eq $true
}, $stateManager).
SetClickHandler({
Export-ConfigurationData
}).
Build()
)
$treeButtonPanel = (
[FlowLayoutPanelBuilder]::new().
SetDock("Right").
SetPadding(6).
SetWidth(52).
SetFlowDirection("TopDown").
SetWrapContents($false).
AddControls(@($buttonImport, $buttonMerge, $buttonClear, $buttonExport)).
Build()
)
$treeViewPanel = (
[PanelBuilder]::new().
SetDock("Fill").
AddControls(@($treeView,$treeButtonPanel)).
Build()
)
$selectionLabel = (
[LabelBuilder]::new("Ausgewählte Dateien").
SetHeight(20).
SetDock("Bottom").
Build()
)
$selectionList = (
[ListBoxBuilder]::new().
SetFont("Segoe UI", 9).
SetDock('Fill'). # Füllt die GroupBox aus
SetHeight(120).
Build()
)
$buttonMoveUp = (
[ButtonBuilder]::new().
SetFluentIcon([char]0xe74a).
SetToolTip("Element nach oben verschieben").
BindEnabled({
$selectionList.Items.Count -gt 1
}, $stateManager).
SetClickHandler({
$SelectedIndex = $selectionList.SelectedIndex
if ($SelectedIndex -gt 0) {
$item = $selectionList.Items[$SelectedIndex]
$selectionList.Items.RemoveAt($SelectedIndex)
$selectionList.Items.Insert($SelectedIndex-1, $item)
$selectionList.SelectedIndex = $SelectedIndex-1
$stateManager.SetState("isMerged",$false)
}
}).
Build()
)
$buttonRemoveSelection = (
[ButtonBuilder]::new().
SetFluentIcon([char]0xe894).
SetToolTip("Element löschen").
BindEnabled({
$selectionList.Items.Count -gt 0
}, $stateManager).
SetClickHandler({
$SelectedIndex = $selectionList.SelectedIndex
if ($SelectedIndex -ge 0) {
$removed = $selectionList.Items[$SelectedIndex]
$resp = [System.Windows.Forms.MessageBox]::Show("Eintrag wirklich löschen?`r`n$($removed.FullName)","Bestätigen",[System.Windows.Forms.MessageBoxButtons]::YesNo,[System.Windows.Forms.MessageBoxIcon]::Question)
if ($resp -eq [System.Windows.Forms.DialogResult]::Yes) {
$selectionList.Items.RemoveAt($SelectedIndex)
$stateManager.SetState("hasSelection", $selectionList.Items.Count -gt 0)
$stateManager.UpdateAllButtons()
$statusBar.SetText("Status","Eintrag entfernt: $($removed.FullName)")
if ($selectionList.Items.Count -eq 0) {
Update-TreeView
} else {
Merge-Templates
}
}
} else {
[System.Windows.Forms.MessageBox]::Show("Kein Eintrag ausgewählt","Info",[System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Information)
}
}).
Build()
)
$buttonClearSelection = (
[ButtonBuilder]::new().
SetFluentIcon([char]0xe74d).
SetToolTip("Element löschen").
BindEnabled({
$selectionList.Items.Count -gt 0
}, $stateManager).
SetClickHandler({
if ($SelectedIndex -ge 0) {
$selectionList.Items.Clear()
} else {
[System.Windows.Forms.MessageBox]::Show("Kein Eintrag vorhanden","Info",[System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Information)
}
Update-TreeView
}).
Build()
)
$buttonMoveDown = (
[ButtonBuilder]::new().
SetFluentIcon([char]0xe74b).
SetToolTip("Element nach unten verschieben").
BindEnabled({
$selectionList.Items.Count -gt 1
}, $stateManager).
SetClickHandler({
$SelectedIndex = $selectionList.SelectedIndex
if ($SelectedIndex -ge 0 -and $SelectedIndex -lt ($selectionList.Items.Count - 1)) {
$item = $selectionList.Items[$SelectedIndex]
$selectionList.Items.RemoveAt($SelectedIndex)
$selectionList.Items.Insert($SelectedIndex+1, $item)
$selectionList.SelectedIndex = $SelectedIndex+1
$stateManager.SetState("isMerged",$false)
}
}).
Build()
)
$selectionButtonPanel = (
[FlowLayoutPanelBuilder]::new().
SetDock("Right").
SetPadding(6).
SetWidth(48).
SetFlowDirection("TopDown").
SetWrapContents($false).
AddControls(@($buttonMoveUp,$buttonRemoveSelection,$buttonClearSelection,$buttonMoveDown)).
Build()
)
$selectionBottomPanel = (
[PanelBuilder]::new().
SetDock('Bottom').
SetHeight(200).
AddControls(@($selectionList,$selectionButtonPanel)).
Build()
)
# SplitPanel erstellen
$splitPanel = (
[SplitPanelBuilder]::new('Vertical', 0.30, 100, 150).
AddToPanel1($flow).
ClearPanel2().
AddToPanel2($treeViewPanel).
AddToPanel2($rightLabel).
AddToPanel2($selectionLabel).
AddToPanel2($selectionBottomPanel).
AddToPanel2($tabPanel)
)
# Form erstellen
$form = (
[FormBuilder]::new("Test").
SetSize(
$settingsManager.Get("WindowWidth", 1024),
$settingsManager.Get("WindowHeight", 768)
).
AddMenu($menuBuilder).
AddStatusBar($statusBar).
AddSplitPanel($splitPanel).
AddKeyDownHandler({
param($s, $e)
# Ctrl+S für Export
if ($e.Control -and $e.KeyCode -eq 'S') {
if ($stateManager.GetState("isMerged")) {
Export-ConfigurationData
}
$e.Handled = $true
}
# Ctrl+O für Import
if ($e.Control -and $e.KeyCode -eq 'O') {
$buttonImport.PerformClick()
$e.Handled = $true
}
# F5 für Refresh
if ($e.KeyCode -eq 'F5') {
Load-Templates
$e.Handled = $true
}
# Ctrl+M für Merge
if ($e.Control -and $e.KeyCode -eq 'M') {
if ($selectionList.Items.Count -gt 0) {
Merge-Templates
}
$e.Handled = $true
}
}).
AddLoadHandler({
# Beim Laden der Form
$rootPath = $settingsManager.Get("RootPath")
if ($rootPath -and (Test-Path $rootPath)) {
$statusBar.AddLabel("Status", "Lade gespeicherten Pfad: $rootPath")
}
Load-Templates
# Registriere Layout-Container für automatisches Resize
[BaseComponent]::AccessibilityManager.RegisterLayoutContainer($flow)
# Registriere alle Controls für Accessibility
$form.RegisterAllAccessibleControls() | Out-Null
}).
AddFormClosedHandler({
# Settings speichern
$settingsManager.Set("WindowWidth", $form.Form.Width)
$settingsManager.Set("WindowHeight", $form.Form.Height)
$settingsManager.Set("SplitterDistance", $splitPanel.SplitContainer.SplitterDistance)
# Ressourcen freigeben
$treeView.Dispose()
$selectionList.Dispose()
$flow.Dispose()
}).
AddShownHandler({
# ZUERST: SplitPanel initialisieren
$splitPanel.InitializeAfterShown($form.Form)
# DANN: Padding setzen
$splitPanel.SetPanelPaddingWithMenu(1, $menuBuilder.GetMenuStrip(), 6, 6, 6)
$splitPanel.SetPanelPaddingWithMenu(2, $menuBuilder.GetMenuStrip(), 6, 6, $($statusBar.GetStatusStrip().Height + 6))
foreach($Groupbox in $flow.Controls){
# GroupBox-Breite anpassen
$Groupbox.Width = $flow.ClientSize.Width - 20
}
$splitPanel.AutoSizeSplitterToPanel1Content()
# Focus setzen
$treeView.Focus()
# StatusBar Update
$statusBar.SetText("Status", "Initialisierung abgeschlossen")
})
)
# Initial alle Button-States aktualisieren
$stateManager.UpdateAllButtons()
$form.Show()