UIfiedOouiBase.ps1
using namespace System.Collections.Generic using namespace Ooui #region Ooui missing elements class Icon : Element { Icon() : base("i") { } } class Table : Element { Table() : base("table") { } } class TableHeader : Element { TableHeader() : base("thead") { } } class TableBody : Element { TableBody() : base("tbody") { } } class TableRow : Element { TableRow() : base("tr") { } } class TableHeaderCell : Element { TableHeaderCell() : base("th") { } } class TableDataCell : Element { TableDataCell() : base("td") { } } #endregion class OouiElement : UIElement { OouiElement() { $this.WrapNegatedProperty("Enable", "IsDisabled") $this.WrapNegatedProperty("Visible", "IsHidden") $this.AddNativeUIChild = { param ( [OouiElement] $element ) $this.NativeUI.AppendChild($element.NativeUI) | Out-Null } $this.RemoveNativeUIChild = { param ( [OouiElement] $element ) $this.NativeUI.RemoveChild($element.NativeUI) | Out-Null } } } class OouiHost : UIHost { $Shared = $false $Port = 8185 [ScriptBlock] $CreateElement OouiHost() { # Style documentation in https://getbootstrap.com/docs/4.5/components [UI]::HeadHtml = ' <link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/4.5.0/css/bootstrap.min.css" /> <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Roboto+Slab:400,700|Material+Icons" rel="stylesheet" type="text/css" /> <style> .card { margin: 20px; } .card-title { white-space: nowrap; margin-right: .75rem; } .card-icon { float: left; } </style> ' } [void] ShowFrame([ScriptBlock] $frameScriptBlock) { #$Global:SyncHash = [HashTable]::Synchronized(@{ # Window = $null # Errors = @() #}) $this.CreateElement = $frameScriptBlock if ($this.Shared) { $this.ShowSharedFrame() } else { $this.ShowNotSharedFrame() } } [void] ShowSharedFrame() { $frame = Invoke-Command -ScriptBlock $this.CreateElement [UI]::Port = $this.Port [UI]::Publish("/Form", $frame.NativeUI) } [void] ShowNotSharedFrame() { $notSharedForm = [NotSharedForm]::new($this.Port, "/Form") $notSharedForm.CreateElement = $this.CreateElement $notSharedForm.Publish() } } class NotSharedForm : Div { [Anchor] $Anchor [ScriptBlock] $CreateElement [int] $Port [string] $Path NotSharedForm([int]$port, [string]$path) { $this.Port = $port $this.Path = $path } Publish() { $hostWrapper = [OouiWrapper.OouiWrapper]::new($this.Port, $this.Path) $hostWrapper.Publish() Add-Member -InputObject $hostWrapper -MemberType NoteProperty -Name sb -Value $this.CreateElement | Out-Null Register-ObjectEvent -InputObject $hostWrapper -EventName OnPublish -MessageData $hostWrapper -Action { param ($hostWrapper) $window = Invoke-Command -ScriptBlock $event.MessageData.sb $event.MessageData.Frame = $window.NativeUI } | Out-Null } } class OouiWindow : WindowBase { OouiWindow() { $this.SetNativeUI([Div]::new()) $this.WrapProperty("Caption", "Title") $this.AddScriptBlockProperty("Loaded") $this.AddNativeUIChild = { param ( [OouiElement] $element ) $this.NativeUI.AppendChild($element.NativeUI) } } [void] ShowDialog() { } [void] OnLoaded() { Invoke-Command -ScriptBlock $this._Loaded -ArgumentList $this } } class OouiStackPanel : OouiElement { #Divs https://jsfiddle.net/rwe8hp6f/ OouiStackPanel() { $this.SetNativeUI([Div]::new()) $this.AddProperty("Orientation") $this.AddNativeUIChild = { param ( [OouiElement] $element ) $listItem = [Div]::new() if ($this._Orientation -eq [Orientation]::Horizontal) { $listItem.Style.float = "left" } else { $listItem.Style.clear = "both" #$listItem.Style.Display = "" } $this.NativeUI.AppendChild($listItem) | Out-Null $listItem.AppendChild($element.NativeUI) | Out-Null } } } class OouiIcon : OouiElement { OouiIcon() { $nativeUI = [Icon]::new() $nativeUI.ClassName = "material-icons" $this.SetNativeUI($nativeUI) Add-Member -InputObject $this -Name Kind -MemberType ScriptProperty -Value { $this.NativeUI.Text } -SecondValue { $this.NativeUI.Text = $args[0] } } } class OouiLabel : OouiElement { OouiLabel() { $this.SetNativeUI([Span]::new()) $this.WrapProperty("Caption", "Text") } } class OouiButton : OouiElement { hidden [OOuiIcon] $CurrentIcon = $null hidden [span] $CurrentSpan = $null hidden [String] $CaptionText = "" OouiButton() { $nativeUI = [Button]::new("") $nativeUI.ClassName = "btn btn-primary" $this.SetNativeUI($nativeUI) Add-Member -InputObject $this -Name Caption -MemberType ScriptProperty -Value { $this.CaptionText } -SecondValue { $this.RemoveChildren() $this.CaptionText = $args[0] $this.RefreshCaption() } Add-Member -InputObject $this -Name Icon -MemberType ScriptProperty -Value { $this.CurrentIcon } -SecondValue { $this.RemoveChildren() $this.CurrentIcon = $args[0] $this.RefreshCaption() } $this.AddScriptBlockProperty("Action") Register-ObjectEvent -InputObject $this.NativeUI -EventName Click -MessageData $this -Action { $this = $event.MessageData $this.Control.OnAction() } | Out-Null } [void] RemoveChildren() { if ($this.CurrentSpan -ne $null) { $this.NativeUI.RemoveChild($this.CurrentSpan) } if ($this.CurrentIcon -ne $null) { $this.NativeUI.RemoveChild($this.CurrentIcon.NativeUI) } } [void] RefreshCaption() { if ($this.CurrentIcon -ne $null) { $this.NativeUI.AppendChild($this.CurrentIcon.NativeUI) } if ($this.CaptionText -ne "") { $this.CurrentSpan = [Span]::new() $this.CurrentSpan.Text = $this.CaptionText $this.NativeUI.AppendChild($this.CurrentSpan) } } [void] OnAction() { Invoke-Command -ScriptBlock $this._Action -ArgumentList $this } } class OouiTextBox : OouiElement { OouiTextBox() { $this.SetNativeUI([TextInput]::new()) $this.WrapProperty("Text", "Value") $this.AddScriptBlockProperty("Change") Register-ObjectEvent -InputObject $this.NativeUI -EventName Change -MessageData $this -Action { $this = $event.MessageData $this.Control.OnChange() } | Out-Null } [void] OnChange() { Invoke-Command -ScriptBlock $this._Change -ArgumentList $this } } class OouiCheckBox : OouiElement { hidden [Div] $ListNativeUI hidden [Span] $LabelNativeUI hidden [Input] $CheckBoxNativeUI OouiCheckBox() { $this.ListNativeUI = [Div]::new() $this.LabelNativeUI = [Span]::new() $this.CheckBoxNativeUI = [Input]::new("CheckBox") $this.ListNativeUI.AppendChild($this.CheckBoxNativeUI) $this.ListNativeUI.AppendChild($this.LabelNativeUI) $this.SetNativeUI($this.ListNativeUI) $this.WrapProperty("Caption", "Text", "LabelNativeUI") $this.WrapProperty("IsChecked", "IsChecked", "CheckBoxNativeUI") $this.AddScriptBlockProperty("Click") Register-ObjectEvent -InputObject $this.CheckBoxNativeUI -EventName Change -MessageData $this -Action { $this = $event.MessageData $this.Control.OnClick() } | Out-Null } [void] OnClick() { Invoke-Command -ScriptBlock $this._Click -ArgumentList $this } } class OouiRadioButton : OouiElement { hidden [Div] $ListNativeUI hidden [Span] $LabelNativeUI hidden [Input] $RadioButtonNativeUI OouiRadioButton() { $this.ListNativeUI = [Div]::new() $this.LabelNativeUI = [Span]::new() $this.RadioButtonNativeUI = [Input]::new("Radio") $this.ListNativeUI.AppendChild($this.RadioButtonNativeUI) $this.ListNativeUI.AppendChild($this.LabelNativeUI) $this.SetNativeUI($this.ListNativeUI) $this.WrapProperty("Caption", "Text", "LabelNativeUI") $this.WrapProperty("IsChecked", "IsChecked", "RadioButtonNativeUI") $this.AddScriptBlockProperty("Click") Register-ObjectEvent -InputObject $this.RadioButtonNativeUI -EventName Change -MessageData $this -Action { $this = $event.MessageData $this.Control.OnClick() } | Out-Null } [void] OnClick() { Invoke-Command -ScriptBlock $this._Click -ArgumentList $this } } class OouiRadioGroup : OouiElement { hidden [String] $ChildName = "" OouiRadioGroup() { $this.SetNativeUI([Div]::new()) $this.AddNativeUIChild = { param ( [OouiElement] $element ) if ($this.Control.ChildName -eq "") { if ($this.Control.Name -ne "") { $this.Control.ChildName = $this.Control.Name } else { $this.Control.ChildName = "A" + [Guid]::NewGuid().ToString() } } $element.RadioButtonNativeUI.Name = $this.Control.ChildName $this.NativeUI.AppendChild($element.NativeUI) | Out-Null } } } class OouiList : OouiElement { [List[ListItem]] $Items = [List[ListItem]]::new() [List[OouiListColumn]] $Columns = [List[OouiListColumn]]::new() hidden [Table] $Table = [Table]::new() hidden [TableHeader] $TableHeader = [TableHeader]::new() hidden [TableRow] $HeaderRow = [TableRow]::new() hidden [List[TableHeaderCell]] $HeaderCells = [List[TableHeaderCell]]::new() hidden [TableBody] $TableBody = [TableBody]::new() hidden [List[TableRow]] $BodyRows = [List[TableRow]]::new() OouiList() { $this.SetNativeUI($this.Table) $this.NativeUI.ClassName = "UIList" $this.Table.AppendChild($this.TableHeader) $this.TableHeader.AppendChild($this.HeaderRow) $this.Table.AppendChild($this.TableBody) } [void] AddColumn([OouiListColumn] $listColumn) { $this.Columns.Add($listColumn) $cell = [TableHeaderCell]::new() $cell.Text = $listColumn.Title $this.HeaderRow.AppendChild($cell) $this.HeaderCells.Add($cell) } [void] AddItem([ListItem] $listItem) { $this.Items.Add($listItem) $row = [TableRow]::new() $this.BodyRows.Add($row) $listItem.Children | ForEach-Object { $cell = [TableDataCell]::new() Add-Member -InputObject $_.NativeUI -Name Form -MemberType NoteProperty -Value $this.Form Add-Member -InputObject $_.NativeUI -Name Parent -MemberType NoteProperty -Value $this $cell.AppendChild($_.NativeUI) $row.AppendChild($cell) } $this.TableBody.AppendChild($row) } [void] StyleComponents() { } [void] StyleCell($cell) { #$cell.NativeUI.Style.LineHeight = $this.LineHeight } [void] RemoveItem([ListItem] $listItem) { $itemIndex = $this.Items.IndexOf($listItem) $row = $this.BodyRows.Item($itemIndex) $this.BodyRows.Remove($row) $this.TableBody.RemoveChild($row) $this.Items.Remove($listItem) } [void] Clear() { $this.Items.ToArray() | ForEach-Object { $this.RemoveItem($_) } } [TableDataCell] GetCell([int] $RowIndex, [int] $ColumnIndex) { $row = $this.BodyRows.Item($RowIndex) $cell = $row.Children.Item($ColumnIndex) return $cell } } class OouiListColumn { [String] $Name [String] $Title } class OouiTabItem : OouiStackPanel { [String] $Caption = "" } class OouiTabControl : OouiStackPanel { [Ooui.List] $List = [Ooui.List]::new() OouiTabControl() { $this.NativeUI.AppendChild($this.List) $this.AddNativeUIChild = { param ( [OouiElement] $element ) $item = [Ooui.ListItem]::new() $item.ClassName = "nav-item" $anchor = [Ooui.Anchor]::new() $anchor.ClassName = "nav-link" $anchor.Text = $element.Caption Register-ObjectEvent -InputObject $anchor -EventName Click -MessageData @($this, $anchor) -Action { $event.MessageData $Control = $event.MessageData[0] $anchor = $event.MessageData[1] $Control.SelectTab($anchor.Text) } | Out-Null $item.AppendChild($anchor) | Out-Null $this.List.AppendChild($item) | Out-Null $this.NativeUI.AppendChild($element.NativeUI) | Out-Null $firstTab = $this.GetTabs() | Select-Object -First 1 $this.SelectTab($firstTab.Caption) } $this.RefreshStyle() } RefreshStyle() { $this.List.ClassName = "nav nav-pills" } [OOuiTabItem[]] GetTabs() { return $this.Children } [void] SelectTab([String] $tabCaption) { $this.GetTabs() | ForEach-Object { if ($_.Caption -eq $tabCaption) { $_.Visible = $true } else { $_.Visible = $false } } $this.List.Children | ForEach-Object { $anchor = $_.FirstChild if ($anchor.Text -eq $tabCaption) { $_.ClassName = "nav-item active" $anchor.ClassName = "nav-link active" } else { $_.ClassName = "nav-item" $anchor.ClassName = "nav-link" } } } } class OouiModal : OouiElement { [Div] $DialogDiv = [Div]::new() [Div] $DocumentDiv = [Div]::new() [Div] $ContentDiv = [Div]::new() [Div] $HeaderDiv = [Div]::new() [Heading] $TitleHeading = [Heading]::new(5) [Div] $BodyDiv = [Div]::new() OouiModal() { $this.DialogDiv.ClassName = "modal" $this.DialogDiv.Style.display = "none" $this.DialogDiv.SetAttribute("role", "dialog") $this.DocumentDiv.ClassName = "modal-dialog" $this.DocumentDiv.SetAttribute("role", "document") $this.DialogDiv.AppendChild($this.DocumentDiv) $this.ContentDiv.ClassName = "modal-content" $this.DocumentDiv.AppendChild($this.ContentDiv) $this.HeaderDiv.ClassName = "modal-header" $this.ContentDiv.AppendChild($this.HeaderDiv) $this.TitleHeading.ClassName = "modal-title" $this.HeaderDiv.AppendChild($this.TitleHeading) $this.BodyDiv.ClassName = "modal-body" $this.ContentDiv.AppendChild($this.BodyDiv) $this.SetNativeUI($this.DialogDiv) $this.AddNativeUIChild = { param ( [OouiElement] $element ) $this.BodyDiv.AppendChild($element.NativeUI) } $this.WrapProperty("Title", "Text", "TitleHeading") } [void] Show() { $this.DialogDiv.Style.display = "block" } [void] Hide() { $this.DialogDiv.Style.display = "none" } } class OouiTimer : OouiElement { [System.Timers.Timer] $Timer [Double] $Interval = 1000 OouiTimer() { $label = [Span]::new() $label.IsHidden = $true $this.SetNativeUI($label) $this.AddScriptBlockProperty("Elapsed") $this.Timer = New-Object System.Timers.Timer Register-ObjectEvent -InputObject $this.Timer -EventName Elapsed -MessageData $this -Action { $this = $event.MessageData $this.Control.OnElapsed() } } [void] OnElapsed() { Invoke-Command -ScriptBlock $this._Elapsed -ArgumentList $this } [void] Start() { $this.Timer.Interval = $this.Interval $this.Timer.Start() } [void] Stop() { $this.Timer.Stop() } } class OouiDatePicker : OouiElement { OouiDatePicker() { $this.SetNativeUI([Input]::new("Date")) $this.AddScriptBlockProperty("Change") Register-ObjectEvent -InputObject $this.NativeUI -EventName Change -MessageData $this -Action { $this = $event.MessageData $this.Control.OnChange() } | Out-Null Add-Member -InputObject $this -Name Value -MemberType ScriptProperty -Value { [DateTime]::Parse($this.NativeUI.Value) } -SecondValue { $this.NativeUI.Value = $args[0].ToString("yyyy-MM-dd") } } [void] OnChange() { Invoke-Command -ScriptBlock $this._Change -ArgumentList $this } } class OouiTimePicker : OouiElement { OouiTimePicker() { $this.SetNativeUI([Input]::new("Time")) $this.AddScriptBlockProperty("Change") Register-ObjectEvent -InputObject $this.NativeUI -EventName Change -MessageData $this -Action { $this = $event.MessageData $this.Control.OnChange() } | Out-Null Add-Member -InputObject $this -Name Value -MemberType ScriptProperty -Value { if ($this.IsTime($this.NativeUI.Value)) { $this.NativeUI.Value } else { "00:00" } } -SecondValue { if ($this.IsTime($args[0])) { $this.NativeUI.Value = $args[0] } else { "00:00" } } } hidden [Boolean] IsTime([String] $timeText) { [DateTime] $dateTime = [DateTime]::Today return [DateTime]::TryParse( "2000-01-01 " + $timeText, [ref] $dateTime) } [void] OnChange() { Invoke-Command -ScriptBlock $this._Change -ArgumentList $this } } class OouiBrowser : OouiStackPanel { [HashTable[]] $Data = [HashTable[]] @() [int] $PageRows = 10 [int] $CurrentPage = 0 [Boolean] $IsEditable = $true [HashTable] $CurrentRow #region Components Declaration hidden [OouiListColumn[]] $Columns = [OouiListColumn[]] @() hidden [OouiListColumn] $EditionColumn hidden [OouiList] $List = [OouiList]::new() hidden [OouiStackPanel] $ButtonPanel = [OouiStackPanel]::new() hidden [OouiButton] $FirstButton = [OouiButton]::new() hidden [OouiButton] $PreviousButton = [OouiButton]::new() hidden [OouiButton] $NextButton = [OouiButton]::new() hidden [OouiButton] $LastButton = [OouiButton]::new() hidden [OouiButton] $AddNewButton = [OouiButton]::new() #endregion OouiBrowser() { $this.AddScriptBlockProperty("AddNew") $this.AddScriptBlockProperty("Edit") $this.AddScriptBlockProperty("Delete") $this.AddChild($this.List) $this.AddButtons() } #region Components Creation hidden [void] AddButtons() { $this.ButtonPanel = [OouiStackPanel]::new() $this.ButtonPanel.Orientation = "Horizontal" $this.FirstButton.Action = { $this.Parent.Parent.OnMoveFirst() } $this.PreviousButton.Action = { $this.Parent.Parent.OnMovePrevious() } $this.NextButton.Action = { $this.Parent.Parent.OnMoveNext() } $this.LastButton.Action = { $this.Parent.Parent.OnMoveLast() } $this.AddNewButton.Action = { $this.Parent.Parent.OnAddNew() } $this.ButtonPanel.AddChild($this.FirstButton) $this.ButtonPanel.AddChild($this.PreviousButton) $this.ButtonPanel.AddChild($this.NextButton) $this.ButtonPanel.AddChild($this.LastButton) $this.ButtonPanel.AddChild($this.AddNewButton) $this.StyleComponents() $this.AddChild($this.ButtonPanel) } [void] AddColumn([OouiListColumn] $listColumn) { $this.Columns += $listColumn $this.List.AddColumn($listColumn) } [void] CreateList() { $this.List.Clear() $this.CreateEditable() 0..($this.PageRows - 1) | ForEach-Object { $listItem = $this.GetInitialListItem($_) $this.List.AddItem($listItem) } } hidden [ListItem] GetInitialListItem([int] $rowIndex) { $hash = $this.GetInitialHash() $listItem = [ListItem]::new() $this.Columns | ForEach-Object { $column = $_ if ($column -eq $this.EditionColumn -and $this.IsEditable) { $this.AddEditionButtons($hash, $listItem, $rowIndex) } else { $this.AddCell($hash, $column.Name, $listItem, $rowIndex) } } return $listItem } hidden [HashTable] GetInitialHash() { $hash = @{} $this.Columns | ForEach-Object { $column = $_ $hash += @{ "$($column.Name)" = "" } } return $hash } hidden [void] AddEditionButtons([HashTable] $hash, [ListItem] $listItem, [int] $rowIndex) { $editionPanel = [OouiStackPanel]::new() $editionPanel.Orientation = "Horizontal" $listItem.AddChild($editionPanel) $editButton = [OouiButton]::new() Add-Member -InputObject $editButton -MemberType NoteProperty -Name CurrentRow -Value $hash Add-Member -InputObject $editButton -MemberType NoteProperty -Name Container -Value $this $editButton.Action = { $this.Container.CurrentRow = $this.Control.CurrentRow $this.Container.OnEdit() } $editionPanel.AddChild($editButton) $deleteButton = [OouiButton]::new() Add-Member -InputObject $deleteButton -MemberType NoteProperty -Name CurrentRow -Value $hash Add-Member -InputObject $deleteButton -MemberType NoteProperty -Name Container -Value $this $deleteButton.Action = { $this.Container.CurrentRow = $this.Control.CurrentRow $this.Container.OnDelete() } $editionPanel.AddChild($deleteButton) $this.StyleEditionButtons($editButton, $deleteButton, $rowIndex) } hidden [void] AddCell([HashTable] $hash, [string] $columnName, [ListItem] $listItem, [int] $rowIndex) { $itemLabel = [OouiLabel]::new() $itemLabel.Caption = $hash."$columnName" $listItem.AddChild($itemLabel) $this.StyleCell($itemLabel, $rowIndex) } hidden [void] CreateEditable() { if ($this.EditionColumn -eq $null -and $this.IsEditable) { $this.CreateEditionColumn() } $this.AddNewButton.Visible = $this.IsEditable } hidden [void] CreateEditionColumn() { $this.EditionColumn = New-Object OouiListColumn -Property @{Name = "_Edition"; Title = "_"} $this.AddColumn($this.EditionColumn) } #endregion #region Data show [void] Refresh() { # Fill Rows $rowIndex = 0 $selectedData = $this.GetSelectedData() $selectedData | ForEach-Object { $hash = $_ $columnIndex = 0 $this.Columns | Select-Object -First ($this.Columns.Count) | ForEach-Object { $column = $_ $cell = $this.List.GetCell($rowIndex, $columnIndex) if ($this.EditionColumn -ne $column) { $cell.Children.Item(0).Text = $hash."$($column.Name)" } else { $cell.IsHidden = $false #$buttons = $this.List.Children.Item($columnIndex).Children.Item($rowIndex + 1).Children #$buttons.Item(0).CurrentRow = $hash #$buttons.Item(1).CurrentRow = $hash $stack = $cell.Children.Item(0) $stack.Control.Children.Item(0).CurrentRow = $hash $stack.Control.Children.Item(1).CurrentRow = $hash } $columnIndex++ } $rowIndex++ } # EmptyRows for ($rowIndex = $selectedData.Count + 1; $rowIndex -le $this.PageRows; $rowIndex++) { $columnIndex = 0 $this.Columns | Select-Object -First ($this.Columns.Count) | ForEach-Object { $cell = $this.List.GetCell($rowIndex - 1, $columnIndex) $column = $_ if ($this.EditionColumn -ne $column) { $cell.Children.Item(0).Text = "" } else { $cell.IsHidden = $true } $columnIndex++ } } } hidden [HashTable[]] GetSelectedData() { return $this.Data | Select-Object -Skip ($this.CurrentPage * $this.PageRows) -First $this.PageRows } hidden [int] GetLastPage() { $lastPage = [Math]::Truncate($this.Data.Count / $this.PageRows) if (($this.Data.Count % $this.PageRows) -eq 0) { $lastPage-- } return $lastPage } #endregion #region Style [void] StyleComponents() { $this.List.NativeUI.ClassName = "UIList table" $this.FirstButton.Icon = [OouiIcon] @{ Kind = "first_page" } $this.PreviousButton.Icon = [OouiIcon] @{ Kind = "chevron_left" } $this.NextButton.Icon = [OouiIcon] @{ Kind = "chevron_right" } $this.LastButton.Icon = [OouiIcon] @{ Kind = "last_page" } $this.AddNewButton.Icon = [OouiIcon] @{ Kind = "add" } $this.FirstButton.NativeUI.ClassName = "btn btn-link" $this.PreviousButton.NativeUI.ClassName = "btn btn-link" $this.NextButton.NativeUI.ClassName = "btn btn-link" $this.LastButton.NativeUI.ClassName = "btn btn-link" $this.AddNewButton.NativeUI.ClassName = "btn btn-link" } [void] StyleCell($cell, [int] $rowIndex) { } [void] StyleEditionButtons([OouiButton] $editButton, [OouiButton] $deleteButton, [int] $rowIndex) { $editButton.Icon = [OouiIcon] @{ Kind = "edit" } $deleteButton.Icon = [OouiIcon] @{ Kind = "close" } $editButton.NativeUI.ClassName = "btn btn-success td-actions btn-sm" $deleteButton.NativeUI.ClassName = "btn btn-danger td-actions btn-sm" } #endregion #region Move Events hidden [void] OnMoveFirst() { $this.CurrentPage = 0 $this.Refresh() } hidden [void] OnMovePrevious() { if ($this.CurrentPage -gt 0) { $this.CurrentPage-- } $this.Refresh() } hidden [void] OnMoveNext() { if ($this.CurrentPage -lt $this.GetLastPage()) { $this.CurrentPage++ } $this.Refresh() } hidden [void] OnMoveLast() { $this.CurrentPage = $this.GetLastPage() $this.Refresh() } #endregion #region CRUD Events hidden [void] OnAddNew() { $this.InvokeTrappableCommand($this._AddNew, $this) } hidden [void] OnEdit() { $this.InvokeTrappableCommand($this._Edit, $this) } hidden [void] OnDelete() { $this.InvokeTrappableCommand($this._Delete, $this) } #endregion } class OouiMenuItem : OouiButton { [void] OnAction() { ([OouiButton]$this).OnAction() $this.Parent.ToogleMenu() } } class OouiDropDownMenu : OouiStackPanel { [OOuiButton] $DropDownToogle = [OOuiButton]::new() [List] $DropDownMenu = [List]::new() OouiDropDownMenu() { $dropDown = [Div]::new() $dropDown.SetAttribute("class", "dropdown") $this.NativeUI.AppendChild($dropDown) $this.DropDownToogle.NativeUI.SetAttribute("class", "btn btn-primary dropdown-toggle") $this.DropDownToogle.NativeUI.SetAttribute("data-toggle", "dropdown") $this.DropDownToogle.NativeUI.SetAttribute("aria-expanded", "true") $this.DropDownToogle.NativeUI.SetAttribute("aria-haspopup", "true") Add-Member -InputObject $this.DropDownToogle -MemberType NoteProperty -Name ParentControl -Value $this $this.DropDownToogle.Action = { param ($this) $this.Control.ParentControl.ToogleMenu() } $dropDown.AppendChild($this.DropDownToogle.NativeUI) $this.DropDownMenu.SetAttribute("class", "dropdown-menu") $dropDown.AppendChild($this.DropDownMenu) $this.AddNativeUIChild = { param ( [OouiElement] $element ) $menuItem = [Ooui.ListItem]::new() $element.NativeUI.SetAttribute("class", "dropdown-item") $element.NativeUI.Style.Width = "100%" $element.NativeUI.Style.BorderColor = "transparent" $menuItem.AppendChild($element.NativeUI) | Out-Null $this.DropDownMenu.AppendChild($menuItem) | Out-Null } Add-Member -InputObject $this -Name "Caption" -MemberType ScriptProperty ` -Value { $this.DropDownToogle.NativeUI.Text } ` -SecondValue { $this.DropDownToogle.NativeUI.Text = $args[0] } } [void] ToogleMenu() { if ($this.DropDownMenu.ClassName.Contains("show")) { $this.DropDownMenu.ClassName = $this.DropDownMenu.ClassName.Replace(" show", "") } else { $this.DropDownMenu.ClassName = $this.DropDownMenu.ClassName + " show" } } } class OouiAutoComplete : OouiStackPanel { [OouiTextBox] $TextBox = [OouiTextBox]::new() [List] $DropDownMenu = [List]::new() OouiAutoComplete() { $dropDown = [Div]::new() $dropDown.SetAttribute("class", "dropdown") $this.NativeUI.AppendChild($dropDown) $this.TextBox.NativeUI.SetAttribute("class", "dropdown-toggle") $this.TextBox.NativeUI.SetAttribute("data-toggle", "dropdown") $this.TextBox.NativeUI.SetAttribute("aria-expanded", "true") $this.TextBox.NativeUI.SetAttribute("aria-haspopup", "true") Add-Member -InputObject $this.TextBox -MemberType NoteProperty -Name ParentControl -Value $this $this.TextBox.Change = { param ($this) $this.Control.ParentControl.ClearDropDown() } Register-ObjectEvent -InputObject $this.TextBox.NativeUI -EventName KeyDown -MessageData $this -Action { $this = $event.MessageData #$this.Control.TextBox.Text = $event.SourceArgs[1] } | Out-Null Register-ObjectEvent -InputObject $this.TextBox.NativeUI -EventName KeyUp -MessageData $this -Action { $this = $event.MessageData $this.Control.ShowDropDown() } | Out-Null $dropDown.AppendChild($this.TextBox.NativeUI) $this.DropDownMenu.SetAttribute("class", "dropdown-menu") $dropDown.AppendChild($this.DropDownMenu) $this.AddNativeUIChild = { param ( [OouiElement] $element ) $menuItem = [Ooui.ListItem]::new() #$element.NativeUI.SetAttribute("class", "btn btn-default") $element.NativeUI.SetAttribute("class", "dropdown-item") $element.NativeUI.Style.Width = "100%" $element.NativeUI.Style.BorderColor = "transparent" $menuItem.AppendChild($element.NativeUI) | Out-Null $this.DropDownMenu.AppendChild($menuItem) | Out-Null } Add-Member -InputObject $this -Name "Text" -MemberType ScriptProperty ` -Value { $this.TextBox.Text } ` -SecondValue { $this.TextBox.Text = $args[0] } $this.AddScriptBlockProperty("ItemsRequested") } [void] ShowDropDown() { $this.ClearDropDown() $this.AddItems() if (-not $this.DropDownMenu.ClassName.Contains("show")) { $this.DropDownMenu.ClassName = $this.DropDownMenu.ClassName + " show" } } [void] ClearDropDown() { $this.DropDownMenu.Children | ForEach-Object { $this.DropDownMenu.RemoveChild($_) } if ($this.DropDownMenu.ClassName.Contains("show")) { $this.DropDownMenu.ClassName = $this.DropDownMenu.ClassName.Replace(" show", "") } } [void] AddItems() { $this.OnItemsRequested() } [void] OnItemsRequested() { [AutoCompleteItem[]] $items = Invoke-Command -ScriptBlock $this._ItemsRequested -ArgumentList $this $items | ForEach-Object { [OOuiButton] $button = [OOuiButton] @{ Caption = $_.Text } Add-Member -InputObject $button -MemberType NoteProperty -Name AutoCompleteTextBox -Value $this.TextBox Add-Member -InputObject $button -MemberType NoteProperty -Name AutoCompleteId -Value $_.Id $button.Action = { param ($this) $this.Control.AutoCompleteTextBox.Text = $this.Control.AutoCompleteId } $this.AddChild($button) } } } class OouiCard : OouiElement { hidden [div] $CardContainerDiv = [div]::new() hidden [div] $CardHeaderDiv = [div]::new() hidden [div] $CardIconDiv = [div]::new() hidden [OouiStackPanel] $CardBodyDiv = [OouiStackPanel]::new() hidden [icon] $CardIcon = [icon]::new() hidden [Heading] $Header = [Heading]::new(4) hidden [OOuiIcon] $CurrentIcon = $null OouiCard() { $this.SetNativeUI($this.CardContainerDiv) $this.CardContainerDiv.AppendChild($this.CardHeaderDiv) $this.CardContainerDiv.AppendChild($this.CardBodyDiv.NativeUI) $this.CardHeaderDiv.AppendChild($this.CardIconDiv) $this.CardHeaderDiv.AppendChild($this.Header) $this.CardIconDiv.AppendChild($this.CardIcon) $this.WrapProperty("Caption", "Text", "Header") Add-Member -InputObject $this -Name Icon -MemberType ScriptProperty -Value { $this.CurrentIcon } -SecondValue { $this.CurrentIcon = $args[0] if ($this.CurrentIcon -ne $null) { $this.CardIcon.Text = $this.CurrentIcon.NativeUI.Text } else { $this.CardIcon.Text = "" } } $this.AddNativeUIChild = { param ( [OouiElement] $element ) $listItem = [Div]::new() if ($this.CardBodyDiv.Orientation -eq [Orientation]::Horizontal) { $listItem.Style.float = "left" } else { $listItem.Style.clear = "both" } $this.CardBodyDiv.NativeUI.AppendChild($listItem) | Out-Null $listItem.AppendChild($element.NativeUI) | Out-Null } $this.StyleComponents() } [void] StyleComponents() { $this.CardContainerDiv.ClassName = "card" $this.Header.ClassName = "card-title" $this.CardHeaderDiv.ClassName = "card-header card-header-icon " $this.CardIconDiv.ClassName = "card-icon" $this.CardIcon.ClassName = "material-icons" $this.CardBodyDiv.NativeUI.ClassName = "card-body" $this.CardBodyDiv.Orientation = [Orientation]::Vertical } } class OouiImage : OouiElement { OouiImage() { $image = [Image]::new() $this.SetNativeUI($image) $this.WrapProperty("Source", "Source") Add-Member -InputObject $this -Name Width -MemberType ScriptProperty -Value { $this.NativeUI.Style.width } -SecondValue { $this.NativeUI.Style.width = $args[0] } } } |