Files
DSC-Configuration-Compiler/Compiler.ps1

4000 lines
145 KiB
PowerShell
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<<<<<<< HEAD
$formsType = 'System.Windows.Forms.Form' -as [type]
if ($null -eq $formsType) {
=======
 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
>>>>>>> 7dd71be14c5216e6f7f99d006643ed1139a69376
Add-Type -AssemblyName System.Windows.Forms
}
$drawingType = 'System.Drawing.Color' -as [type]
if ($null -eq $drawingType) {
Add-Type -AssemblyName System.Drawing
}
if ([System.Threading.Thread]::CurrentThread.GetApartmentState() -ne [System.Threading.ApartmentState]::STA) {
$powershell = (Get-Command powershell.exe -ErrorAction SilentlyContinue).Source
if ($powershell) {
& $powershell -NoProfile -ExecutionPolicy Bypass -STA -File $PSCommandPath @args
exit $LASTEXITCODE
}
}
<<<<<<< HEAD
$coreScript = Join-Path -Path $PSScriptRoot -ChildPath 'Compiler.Core.ps1'
& $coreScript @args
=======
$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()
>>>>>>> 7dd71be14c5216e6f7f99d006643ed1139a69376