mirror of
https://github.com/ChrisTitusTech/winutil.git
synced 2026-08-09 17:41:14 +10:00
Add maximaze button (#4841)
* Add maximize button logic and update assets * Add maximize button with theming * delelte logo * Center and restyle the window control buttons * Fix window state test setup --------- Co-authored-by: aran628 <aran2014+@gmail.com> Co-authored-by: Chris Titus <contact@christitus.com>
This commit is contained in:
co-authored by
aran628
Chris Titus
parent
822003d87f
commit
13a18eeeb2
+1
-1
@@ -25,7 +25,7 @@
|
|||||||
"IconFontSize": "14",
|
"IconFontSize": "14",
|
||||||
"IconButtonSize": "35",
|
"IconButtonSize": "35",
|
||||||
"SettingsIconFontSize": "18",
|
"SettingsIconFontSize": "18",
|
||||||
"CloseIconFontSize": "18",
|
"CloseIconFontSize": "12",
|
||||||
"GroupBorderBackgroundColor": "#232629",
|
"GroupBorderBackgroundColor": "#232629",
|
||||||
"ButtonFontSize": "12",
|
"ButtonFontSize": "12",
|
||||||
"ButtonFontFamily": "Arial",
|
"ButtonFontFamily": "Arial",
|
||||||
|
|||||||
@@ -87,6 +87,13 @@ function Invoke-WPFButton {
|
|||||||
}
|
}
|
||||||
"WPFCloseButton" {$sync.Form.Close(); Write-Host "Bye bye!"}
|
"WPFCloseButton" {$sync.Form.Close(); Write-Host "Bye bye!"}
|
||||||
"WPFMinimizeButton" {$sync.Form.WindowState = [Windows.WindowState]::Minimized}
|
"WPFMinimizeButton" {$sync.Form.WindowState = [Windows.WindowState]::Minimized}
|
||||||
|
"WPFMaximizeButton" {
|
||||||
|
if ($sync.Form.WindowState -eq [Windows.WindowState]::Normal) {
|
||||||
|
$sync.Form.WindowState = [Windows.WindowState]::Maximized
|
||||||
|
} else {
|
||||||
|
$sync.Form.WindowState = [Windows.WindowState]::Normal
|
||||||
|
}
|
||||||
|
}
|
||||||
"WPFselectedAppsButton" {$sync.selectedAppsPopup.IsOpen = -not $sync.selectedAppsPopup.IsOpen}
|
"WPFselectedAppsButton" {$sync.selectedAppsPopup.IsOpen = -not $sync.selectedAppsPopup.IsOpen}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
BeforeAll {
|
BeforeAll {
|
||||||
$script:repoRoot = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path
|
$script:repoRoot = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path
|
||||||
|
|
||||||
if (-not ("System.Windows.Controls.CheckBox" -as [type])) {
|
if (-not ("Windows.Visibility" -as [type])) {
|
||||||
Add-Type @"
|
Add-Type @"
|
||||||
namespace Windows
|
namespace Windows
|
||||||
{
|
{
|
||||||
@@ -15,7 +15,25 @@ namespace Windows
|
|||||||
Collapsed
|
Collapsed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
"@
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not ("Windows.WindowState" -as [type])) {
|
||||||
|
Add-Type @"
|
||||||
|
namespace Windows
|
||||||
|
{
|
||||||
|
public enum WindowState
|
||||||
|
{
|
||||||
|
Normal,
|
||||||
|
Minimized,
|
||||||
|
Maximized
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"@
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not ("System.Windows.Controls.CheckBox" -as [type])) {
|
||||||
|
Add-Type @"
|
||||||
namespace System.Windows.Controls
|
namespace System.Windows.Controls
|
||||||
{
|
{
|
||||||
public class CheckBox
|
public class CheckBox
|
||||||
@@ -316,3 +334,32 @@ Describe "Invoke-WPFButton progress cleanup" {
|
|||||||
Should -Not -Invoke Set-WinUtilTweaksProgressIndicator
|
Should -Not -Invoke Set-WinUtilTweaksProgressIndicator
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Describe "Invoke-WPFButton window state" {
|
||||||
|
BeforeEach {
|
||||||
|
New-WinUtilUiStateTestContext
|
||||||
|
$script:sync.ProcessRunning = $true
|
||||||
|
$script:sync.Form = [pscustomobject]@{
|
||||||
|
WindowState = [Windows.WindowState]::Normal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AfterEach {
|
||||||
|
Remove-Variable -Name sync -Scope Script -ErrorAction SilentlyContinue
|
||||||
|
Remove-Variable -Name sync -Scope Global -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
|
||||||
|
It "maximizes a normal window" {
|
||||||
|
Invoke-WPFButton -Button "WPFMaximizeButton"
|
||||||
|
|
||||||
|
$script:sync.Form.WindowState | Should -Be ([Windows.WindowState]::Maximized)
|
||||||
|
}
|
||||||
|
|
||||||
|
It "restores a maximized window" {
|
||||||
|
$script:sync.Form.WindowState = [Windows.WindowState]::Maximized
|
||||||
|
|
||||||
|
Invoke-WPFButton -Button "WPFMaximizeButton"
|
||||||
|
|
||||||
|
$script:sync.Form.WindowState | Should -Be ([Windows.WindowState]::Normal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -248,6 +248,52 @@ Describe "XAML document" {
|
|||||||
$buttonSource | Should -Match '"WPFInstallSelectedAppx"\s*\{Invoke-WPFAppxInstall\}'
|
$buttonSource | Should -Match '"WPFInstallSelectedAppx"\s*\{Invoke-WPFAppxInstall\}'
|
||||||
$tabSource | Should -Match '\$sync\.\$tabNav\.Items\[\$tabNumber\]\.IsSelected = \$true'
|
$tabSource | Should -Match '\$sync\.\$tabNav\.Items\[\$tabNumber\]\.IsSelected = \$true'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
It "centers top bar controls vertically" {
|
||||||
|
$navPanel = $script:xaml.SelectSingleNode('//*[local-name()="StackPanel"][@Name="NavDockPanel"]')
|
||||||
|
$minimizeButton = $script:xaml.SelectSingleNode('//*[local-name()="Button"][@Name="WPFMinimizeButton"]')
|
||||||
|
$actionPanel = $minimizeButton.ParentNode
|
||||||
|
$topBarButtonNames = @(
|
||||||
|
"ThemeButton",
|
||||||
|
"FontScalingButton",
|
||||||
|
"SettingsButton",
|
||||||
|
"WPFMinimizeButton",
|
||||||
|
"WPFMaximizeButton",
|
||||||
|
"WPFCloseButton"
|
||||||
|
)
|
||||||
|
|
||||||
|
$navPanel.GetAttribute("VerticalAlignment") | Should -Be "Center"
|
||||||
|
$actionPanel.GetAttribute("VerticalAlignment") | Should -Be "Center"
|
||||||
|
|
||||||
|
foreach ($buttonName in $topBarButtonNames) {
|
||||||
|
$button = $script:xaml.SelectSingleNode("//*[local-name()='Button'][@Name='$buttonName']")
|
||||||
|
$button.GetAttribute("VerticalAlignment") | Should -Be "Center"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
It "uses state-aware maximize and restore icons" {
|
||||||
|
$themes = Get-WinUtilConfigObject -Name "themes"
|
||||||
|
$minimizeButton = $script:xaml.SelectSingleNode('//*[local-name()="Button"][@Name="WPFMinimizeButton"]')
|
||||||
|
$maximizeButton = $script:xaml.SelectSingleNode('//*[local-name()="Button"][@Name="WPFMaximizeButton"]')
|
||||||
|
$closeButton = $script:xaml.SelectSingleNode('//*[local-name()="Button"][@Name="WPFCloseButton"]')
|
||||||
|
$maximizeStyle = $maximizeButton.SelectSingleNode('./*[local-name()="Button.Style"]/*[local-name()="Style"]')
|
||||||
|
$maximizeIcon = $maximizeStyle.SelectSingleNode('./*[local-name()="Setter"][@Property="Content"]')
|
||||||
|
$maximizedTrigger = $maximizeStyle.SelectSingleNode('./*[local-name()="Style.Triggers"]/*[local-name()="DataTrigger"][@Value="Maximized"]')
|
||||||
|
$restoreIcon = $maximizedTrigger.SelectSingleNode('./*[local-name()="Setter"][@Property="Content"]')
|
||||||
|
|
||||||
|
foreach ($button in @($minimizeButton, $maximizeButton, $closeButton)) {
|
||||||
|
$button.GetAttribute("FontFamily") | Should -Be "Segoe MDL2 Assets"
|
||||||
|
$button.GetAttribute("FontSize") | Should -Be "{DynamicResource CloseIconFontSize}"
|
||||||
|
$button.GetAttribute("Margin") | Should -BeIn @("0", "0,0,0,0")
|
||||||
|
}
|
||||||
|
|
||||||
|
$minimizeButton.GetAttribute("Content") | Should -Be ([string][char]0xE921)
|
||||||
|
$maximizeIcon.GetAttribute("Value") | Should -Be ([string][char]0xE922)
|
||||||
|
$restoreIcon.GetAttribute("Value") | Should -Be ([string][char]0xE923)
|
||||||
|
$closeButton.GetAttribute("Content") | Should -Be ([string][char]0xE8BB)
|
||||||
|
$maximizeStyle.GetAttribute("BasedOn") | Should -Be "{StaticResource HoverButtonStyle}"
|
||||||
|
[int]$themes.shared.CloseIconFontSize | Should -BeLessThan ([int]$themes.shared.SettingsIconFontSize)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Describe "XAML and sync wiring" {
|
Describe "XAML and sync wiring" {
|
||||||
|
|||||||
+59
-21
@@ -955,7 +955,7 @@
|
|||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<!-- Navigation Buttons Panel -->
|
<!-- Navigation Buttons Panel -->
|
||||||
<StackPanel Name="NavDockPanel" Orientation="Horizontal" Grid.Column="0" Margin="5,5,10,5">
|
<StackPanel Name="NavDockPanel" Orientation="Horizontal" Grid.Column="0" VerticalAlignment="Center" Margin="5,5,10,5">
|
||||||
<StackPanel Name="NavLogoPanel" Orientation="Horizontal" HorizontalAlignment="Left" Background="{DynamicResource MainBackgroundColor}" SnapsToDevicePixels="True" Margin="10,0,20,0">
|
<StackPanel Name="NavLogoPanel" Orientation="Horizontal" HorizontalAlignment="Left" Background="{DynamicResource MainBackgroundColor}" SnapsToDevicePixels="True" Margin="10,0,20,0">
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<ToggleButton Margin="0,0,5,0" Height="{DynamicResource TabButtonHeight}" Width="{DynamicResource TabButtonWidth}"
|
<ToggleButton Margin="0,0,5,0" Height="{DynamicResource TabButtonHeight}" Width="{DynamicResource TabButtonWidth}"
|
||||||
@@ -1037,7 +1037,7 @@
|
|||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<!-- Buttons Container -->
|
<!-- Buttons Container -->
|
||||||
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="5,5,5,5">
|
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="5,5,5,5">
|
||||||
<Button Name="ThemeButton"
|
<Button Name="ThemeButton"
|
||||||
Style="{StaticResource HoverButtonStyle}"
|
Style="{StaticResource HoverButtonStyle}"
|
||||||
BorderBrush="Transparent"
|
BorderBrush="Transparent"
|
||||||
@@ -1045,7 +1045,7 @@
|
|||||||
Foreground="{DynamicResource MainForegroundColor}"
|
Foreground="{DynamicResource MainForegroundColor}"
|
||||||
FontSize="{DynamicResource SettingsIconFontSize}"
|
FontSize="{DynamicResource SettingsIconFontSize}"
|
||||||
Width="{DynamicResource IconButtonSize}" Height="{DynamicResource IconButtonSize}"
|
Width="{DynamicResource IconButtonSize}" Height="{DynamicResource IconButtonSize}"
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Top"
|
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||||
Margin="0,0,2,0"
|
Margin="0,0,2,0"
|
||||||
FontFamily="Segoe MDL2 Assets"
|
FontFamily="Segoe MDL2 Assets"
|
||||||
Content="N/A"
|
Content="N/A"
|
||||||
@@ -1083,7 +1083,7 @@
|
|||||||
Foreground="{DynamicResource MainForegroundColor}"
|
Foreground="{DynamicResource MainForegroundColor}"
|
||||||
FontSize="{DynamicResource SettingsIconFontSize}"
|
FontSize="{DynamicResource SettingsIconFontSize}"
|
||||||
Width="{DynamicResource IconButtonSize}" Height="{DynamicResource IconButtonSize}"
|
Width="{DynamicResource IconButtonSize}" Height="{DynamicResource IconButtonSize}"
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Top"
|
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||||
Margin="0,0,2,0"
|
Margin="0,0,2,0"
|
||||||
FontFamily="Segoe MDL2 Assets"
|
FontFamily="Segoe MDL2 Assets"
|
||||||
Content=""
|
Content=""
|
||||||
@@ -1151,7 +1151,7 @@
|
|||||||
Foreground="{DynamicResource MainForegroundColor}"
|
Foreground="{DynamicResource MainForegroundColor}"
|
||||||
FontSize="{DynamicResource SettingsIconFontSize}"
|
FontSize="{DynamicResource SettingsIconFontSize}"
|
||||||
Width="{DynamicResource IconButtonSize}" Height="{DynamicResource IconButtonSize}"
|
Width="{DynamicResource IconButtonSize}" Height="{DynamicResource IconButtonSize}"
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Top"
|
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||||
Margin="0,0,2,0"
|
Margin="0,0,2,0"
|
||||||
FontFamily="Segoe MDL2 Assets"
|
FontFamily="Segoe MDL2 Assets"
|
||||||
Content=""/>
|
Content=""/>
|
||||||
@@ -1180,24 +1180,62 @@
|
|||||||
</Popup>
|
</Popup>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
Content="−" BorderThickness="0"
|
Content=""
|
||||||
BorderBrush="Transparent"
|
Style="{StaticResource HoverButtonStyle}"
|
||||||
Background="{DynamicResource MainBackgroundColor}"
|
BorderThickness="0"
|
||||||
Width="{DynamicResource IconButtonSize}" Height="{DynamicResource IconButtonSize}"
|
BorderBrush="Transparent"
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Top"
|
Background="{DynamicResource MainBackgroundColor}"
|
||||||
Margin="0,0,0,0"
|
Width="{DynamicResource IconButtonSize}" Height="{DynamicResource IconButtonSize}"
|
||||||
FontFamily="{DynamicResource FontFamily}"
|
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||||
Foreground="{DynamicResource MainForegroundColor}" FontSize="{DynamicResource CloseIconFontSize}" Name="WPFMinimizeButton" />
|
Margin="0"
|
||||||
|
FontFamily="Segoe MDL2 Assets"
|
||||||
|
Foreground="{DynamicResource MainForegroundColor}"
|
||||||
|
FontSize="{DynamicResource CloseIconFontSize}"
|
||||||
|
ToolTip="Minimize"
|
||||||
|
AutomationProperties.Name="Minimize"
|
||||||
|
Name="WPFMinimizeButton" />
|
||||||
|
<Button
|
||||||
|
BorderThickness="0"
|
||||||
|
BorderBrush="Transparent"
|
||||||
|
Background="{DynamicResource MainBackgroundColor}"
|
||||||
|
Width="{DynamicResource IconButtonSize}" Height="{DynamicResource IconButtonSize}"
|
||||||
|
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||||
|
Margin="0,0,0,0"
|
||||||
|
FontFamily="Segoe MDL2 Assets"
|
||||||
|
Foreground="{DynamicResource MainForegroundColor}"
|
||||||
|
FontSize="{DynamicResource CloseIconFontSize}"
|
||||||
|
Name="WPFMaximizeButton">
|
||||||
|
<Button.Style>
|
||||||
|
<Style TargetType="Button" BasedOn="{StaticResource HoverButtonStyle}">
|
||||||
|
<Setter Property="Content" Value=""/>
|
||||||
|
<Setter Property="ToolTip" Value="Maximize"/>
|
||||||
|
<Setter Property="AutomationProperties.Name" Value="Maximize"/>
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding WindowState, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" Value="Maximized">
|
||||||
|
<Setter Property="Content" Value=""/>
|
||||||
|
<Setter Property="ToolTip" Value="Restore"/>
|
||||||
|
<Setter Property="AutomationProperties.Name" Value="Restore"/>
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</Button.Style>
|
||||||
|
</Button>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
Content="×" BorderThickness="0"
|
Content=""
|
||||||
BorderBrush="Transparent"
|
Style="{StaticResource HoverButtonStyle}"
|
||||||
Background="{DynamicResource MainBackgroundColor}"
|
BorderThickness="0"
|
||||||
Width="{DynamicResource IconButtonSize}" Height="{DynamicResource IconButtonSize}"
|
BorderBrush="Transparent"
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Top"
|
Background="{DynamicResource MainBackgroundColor}"
|
||||||
Margin="0,0,0,0"
|
Width="{DynamicResource IconButtonSize}" Height="{DynamicResource IconButtonSize}"
|
||||||
FontFamily="{DynamicResource FontFamily}"
|
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||||
Foreground="{DynamicResource MainForegroundColor}" FontSize="{DynamicResource CloseIconFontSize}" Name="WPFCloseButton" />
|
Margin="0"
|
||||||
|
FontFamily="Segoe MDL2 Assets"
|
||||||
|
Foreground="{DynamicResource MainForegroundColor}"
|
||||||
|
FontSize="{DynamicResource CloseIconFontSize}"
|
||||||
|
ToolTip="Close"
|
||||||
|
AutomationProperties.Name="Close"
|
||||||
|
Name="WPFCloseButton" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
Reference in New Issue
Block a user