f311429bc2
Adds Services/SelfUpdateService.cs implementing the Chrome-style pattern:
1. Download new exe to "<current>.new"
2. Rename running exe to "<current>.old" (NTFS allows MoveFile on a
running exe -- it resolves processes by handle, not by path)
3. Rename ".new" to canonical path
4. Spawn the new exe with our argv
5. Environment.Exit(0)
6. Next start of the new exe runs CleanupAfterUpdate() in App.OFIC()
which deletes the leftover ".old"
UI: the existing "Download" banner button is now "Install update". Click
runs the self-update flow with a percent/MB progress label; any failure
(network, AV write-block, dir not writable) falls back to opening the
URL in the browser so users always have a path forward.
Bumps to 0.4.7. Also fixes a stale fallback URL that pointed at
sijbers.uk/pack/... -- now correctly points at bns.sijbers.uk/launcher/.
396 lines
24 KiB
XML
396 lines
24 KiB
XML
<Window xmlns="https://github.com/avaloniaui"
|
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
mc:Ignorable="d" d:DesignWidth="900" d:DesignHeight="600"
|
|
x:Class="ModpackLauncher.MainWindow"
|
|
Title="Modpack Launcher"
|
|
Width="900" Height="640"
|
|
MinWidth="720" MinHeight="540"
|
|
Background="Transparent"
|
|
TransparencyLevelHint="Transparent"
|
|
WindowDecorations="None"
|
|
Icon="/Assets/icon.png"
|
|
WindowStartupLocation="CenterScreen">
|
|
|
|
<Window.Resources>
|
|
<!-- Palette: dark navy base + brass trim + cyan magic accent -->
|
|
|
|
<!-- Brass gradient (lit from top, polished) -->
|
|
<LinearGradientBrush x:Key="BrassTrim" StartPoint="0%,0%" EndPoint="0%,100%">
|
|
<GradientStop Offset="0" Color="#F5D88A" />
|
|
<GradientStop Offset="0.35" Color="#E8B95C" />
|
|
<GradientStop Offset="0.65" Color="#A37A2E" />
|
|
<GradientStop Offset="1" Color="#5C4519" />
|
|
</LinearGradientBrush>
|
|
<LinearGradientBrush x:Key="BrassFill" StartPoint="0%,0%" EndPoint="0%,100%">
|
|
<GradientStop Offset="0" Color="#F5D88A" />
|
|
<GradientStop Offset="0.5" Color="#D4A24C" />
|
|
<GradientStop Offset="1" Color="#8C6829" />
|
|
</LinearGradientBrush>
|
|
<LinearGradientBrush x:Key="BrassFillHover" StartPoint="0%,0%" EndPoint="0%,100%">
|
|
<GradientStop Offset="0" Color="#FBE3A0" />
|
|
<GradientStop Offset="0.5" Color="#E8B95C" />
|
|
<GradientStop Offset="1" Color="#A37A2E" />
|
|
</LinearGradientBrush>
|
|
|
|
<!-- Rivet (radial gradient, lit from upper-left) -->
|
|
<RadialGradientBrush x:Key="RivetFill" Center="35%,35%" GradientOrigin="35%,35%" RadiusX="0.55" RadiusY="0.55">
|
|
<GradientStop Offset="0" Color="#F8DC95" />
|
|
<GradientStop Offset="0.5" Color="#C99843" />
|
|
<GradientStop Offset="1" Color="#3F2E10" />
|
|
</RadialGradientBrush>
|
|
|
|
<!-- Card fill (deep navy gradient) -->
|
|
<LinearGradientBrush x:Key="CardFill" StartPoint="0%,0%" EndPoint="0%,100%">
|
|
<GradientStop Offset="0" Color="#13192A" />
|
|
<GradientStop Offset="1" Color="#0A0F1A" />
|
|
</LinearGradientBrush>
|
|
|
|
<!-- Title bar metallic -->
|
|
<LinearGradientBrush x:Key="TitleBarFill" StartPoint="0%,0%" EndPoint="0%,100%">
|
|
<GradientStop Offset="0" Color="#0F1626" />
|
|
<GradientStop Offset="1" Color="#070B16" />
|
|
</LinearGradientBrush>
|
|
|
|
<!-- Magic cyan glow (radial) -->
|
|
<RadialGradientBrush x:Key="MagicGlow" Center="50%,50%" GradientOrigin="50%,50%" RadiusX="0.8" RadiusY="0.8">
|
|
<GradientStop Offset="0" Color="#605DD4E8" />
|
|
<GradientStop Offset="0.5" Color="#205DD4E8" />
|
|
<GradientStop Offset="1" Color="#005DD4E8" />
|
|
</RadialGradientBrush>
|
|
|
|
<!-- Tileable noise overlay -->
|
|
<ImageBrush x:Key="NoiseBrush" Source="/Assets/noise.png"
|
|
TileMode="Tile" Stretch="None"
|
|
DestinationRect="0,0,128,128" />
|
|
</Window.Resources>
|
|
|
|
<Window.Styles>
|
|
<!-- Reusable "brass panel" with metal trim + corner rivets -->
|
|
<Style Selector="ContentControl.brass-panel">
|
|
<Setter Property="Padding" Value="20" />
|
|
<Setter Property="Template">
|
|
<ControlTemplate>
|
|
<Grid>
|
|
<!-- Outer brass trim -->
|
|
<Border BorderBrush="{StaticResource BrassTrim}" BorderThickness="2" CornerRadius="6"
|
|
Background="{StaticResource CardFill}">
|
|
<ContentPresenter Content="{TemplateBinding Content}"
|
|
Margin="{TemplateBinding Padding}" />
|
|
</Border>
|
|
<!-- Corner rivets -->
|
|
<Ellipse Width="6" Height="6" HorizontalAlignment="Left" VerticalAlignment="Top"
|
|
Margin="6" Fill="{StaticResource RivetFill}" />
|
|
<Ellipse Width="6" Height="6" HorizontalAlignment="Right" VerticalAlignment="Top"
|
|
Margin="6" Fill="{StaticResource RivetFill}" />
|
|
<Ellipse Width="6" Height="6" HorizontalAlignment="Left" VerticalAlignment="Bottom"
|
|
Margin="6" Fill="{StaticResource RivetFill}" />
|
|
<Ellipse Width="6" Height="6" HorizontalAlignment="Right" VerticalAlignment="Bottom"
|
|
Margin="6" Fill="{StaticResource RivetFill}" />
|
|
</Grid>
|
|
</ControlTemplate>
|
|
</Setter>
|
|
</Style>
|
|
|
|
<!-- Primary button: brass gradient + cyan magic hover glow -->
|
|
<Style Selector="Button.primary">
|
|
<Setter Property="Background" Value="{StaticResource BrassFill}" />
|
|
<Setter Property="Foreground" Value="#1A140F" />
|
|
<Setter Property="Padding" Value="26 12" />
|
|
<Setter Property="FontSize" Value="16" />
|
|
<Setter Property="FontWeight" Value="Bold" />
|
|
<Setter Property="CornerRadius" Value="6" />
|
|
<Setter Property="BorderBrush" Value="#5C4519" />
|
|
<Setter Property="BorderThickness" Value="1" />
|
|
</Style>
|
|
<Style Selector="Button.primary:pointerover /template/ ContentPresenter">
|
|
<Setter Property="Background" Value="{StaticResource BrassFillHover}" />
|
|
</Style>
|
|
<Style Selector="Button.primary:disabled /template/ ContentPresenter">
|
|
<Setter Property="Background" Value="#3A2D1E" />
|
|
<Setter Property="Foreground" Value="#6B5F4A" />
|
|
</Style>
|
|
|
|
<!-- Secondary button -->
|
|
<Style Selector="Button.secondary">
|
|
<Setter Property="Background" Value="#1B233A" />
|
|
<Setter Property="Foreground" Value="#E8DFC8" />
|
|
<Setter Property="Padding" Value="14 8" />
|
|
<Setter Property="CornerRadius" Value="4" />
|
|
<Setter Property="BorderBrush" Value="#A37A2E" />
|
|
<Setter Property="BorderThickness" Value="1" />
|
|
</Style>
|
|
<Style Selector="Button.secondary:pointerover /template/ ContentPresenter">
|
|
<Setter Property="Background" Value="#26314D" />
|
|
<Setter Property="BorderBrush" Value="#E8B95C" />
|
|
</Style>
|
|
|
|
<Style Selector="TextBlock.h1">
|
|
<Setter Property="FontSize" Value="22" />
|
|
<Setter Property="FontWeight" Value="SemiBold" />
|
|
<Setter Property="Foreground" Value="#E8DFC8" />
|
|
</Style>
|
|
<Style Selector="TextBlock.muted">
|
|
<Setter Property="Foreground" Value="#7A8497" />
|
|
<Setter Property="FontSize" Value="13" />
|
|
</Style>
|
|
|
|
<!-- Brass progress bar -->
|
|
<Style Selector="ProgressBar.brass">
|
|
<Setter Property="Foreground" Value="{StaticResource BrassFill}" />
|
|
<Setter Property="Background" Value="#0A0F1A" />
|
|
<Setter Property="BorderBrush" Value="{StaticResource BrassTrim}" />
|
|
<Setter Property="BorderThickness" Value="1" />
|
|
</Style>
|
|
|
|
<!-- Custom title bar caption buttons -->
|
|
<Style Selector="Button.caption">
|
|
<Setter Property="Background" Value="Transparent" />
|
|
<Setter Property="Width" Value="46" />
|
|
<Setter Property="Height" Value="36" />
|
|
<Setter Property="CornerRadius" Value="0" />
|
|
<Setter Property="Padding" Value="0" />
|
|
<Setter Property="HorizontalContentAlignment" Value="Center" />
|
|
<Setter Property="VerticalContentAlignment" Value="Center" />
|
|
</Style>
|
|
<Style Selector="Button.caption:pointerover /template/ ContentPresenter">
|
|
<Setter Property="Background" Value="#1B233A" />
|
|
</Style>
|
|
<Style Selector="Button.caption Path">
|
|
<Setter Property="Stroke" Value="#A37A2E" />
|
|
<Setter Property="StrokeThickness" Value="1" />
|
|
<Setter Property="HorizontalAlignment" Value="Center" />
|
|
<Setter Property="VerticalAlignment" Value="Center" />
|
|
</Style>
|
|
<Style Selector="Button.caption:pointerover Path">
|
|
<Setter Property="Stroke" Value="#F5D88A" />
|
|
</Style>
|
|
<Style Selector="Button.caption-close">
|
|
<Setter Property="Background" Value="Transparent" />
|
|
<Setter Property="Width" Value="46" />
|
|
<Setter Property="Height" Value="36" />
|
|
<Setter Property="CornerRadius" Value="0" />
|
|
<Setter Property="Padding" Value="0" />
|
|
<Setter Property="HorizontalContentAlignment" Value="Center" />
|
|
<Setter Property="VerticalContentAlignment" Value="Center" />
|
|
</Style>
|
|
<Style Selector="Button.caption-close:pointerover /template/ ContentPresenter">
|
|
<Setter Property="Background" Value="#B94228" />
|
|
</Style>
|
|
<Style Selector="Button.caption-close Path">
|
|
<Setter Property="Stroke" Value="#A37A2E" />
|
|
<Setter Property="StrokeThickness" Value="1" />
|
|
<Setter Property="HorizontalAlignment" Value="Center" />
|
|
<Setter Property="VerticalAlignment" Value="Center" />
|
|
</Style>
|
|
<Style Selector="Button.caption-close:pointerover Path">
|
|
<Setter Property="Stroke" Value="#F5D88A" />
|
|
</Style>
|
|
</Window.Styles>
|
|
|
|
<!-- Outermost: main brass-bordered window + slide-out info panel (separate column, OUTSIDE the window) -->
|
|
<Grid>
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="*" />
|
|
<ColumnDefinition Width="Auto" />
|
|
</Grid.ColumnDefinitions>
|
|
|
|
<Border Grid.Column="0" Name="RootBorder" CornerRadius="10"
|
|
Background="{StaticResource BrassTrim}"
|
|
ClipToBounds="True">
|
|
<Border CornerRadius="8" Background="#0B1220" Margin="2" ClipToBounds="True">
|
|
<Panel Background="{StaticResource NoiseBrush}">
|
|
<Grid RowDefinitions="36,1,*">
|
|
|
|
<!-- Title bar -->
|
|
<Grid Grid.Row="0" Name="TitleBar" Background="{StaticResource TitleBarFill}"
|
|
PointerPressed="OnTitleBarPressed">
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="*" />
|
|
<ColumnDefinition Width="Auto" />
|
|
</Grid.ColumnDefinitions>
|
|
|
|
<!-- Magic glow halo behind icon + title text -->
|
|
<Grid Grid.Column="0" Margin="10 0 0 0" VerticalAlignment="Center" IsHitTestVisible="False">
|
|
<Ellipse Width="36" Height="36" HorizontalAlignment="Left"
|
|
Margin="-8 0 0 0" Fill="{StaticResource MagicGlow}" />
|
|
<StackPanel Orientation="Horizontal" Spacing="10" VerticalAlignment="Center">
|
|
<Image Source="/Assets/icon.png" Width="22" Height="22"
|
|
RenderOptions.BitmapInterpolationMode="HighQuality" />
|
|
<TextBlock Name="TitleText" Text="Brass & Sigil Launcher"
|
|
Foreground="#F5D88A" FontSize="12" FontWeight="SemiBold"
|
|
VerticalAlignment="Center" />
|
|
</StackPanel>
|
|
</Grid>
|
|
|
|
<StackPanel Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Stretch">
|
|
<Button Classes="caption" Click="OnRefreshClick" ToolTip.Tip="Check for updates">
|
|
<Path Width="11" Height="11"
|
|
Data="M 9,1.5 A 4,4 0 1 0 10.5,5 M 9,1.5 V 4 H 6.5" />
|
|
</Button>
|
|
<Button Classes="caption" Click="OnInfoClick" ToolTip.Tip="Pack info">
|
|
<Path Width="11" Height="11"
|
|
Data="M 5.5,0.5 A 5,5 0 1 1 5.499,0.5 Z M 5.5,4 V 9 M 5.5,2 V 2.5" />
|
|
</Button>
|
|
<Button Classes="caption" Click="OnMinimizeClick" ToolTip.Tip="Minimize">
|
|
<Path Width="10" Height="10" Data="M 0,5 H 10" />
|
|
</Button>
|
|
<Button Classes="caption-close" Click="OnCloseClick" ToolTip.Tip="Close">
|
|
<Path Width="10" Height="10" Data="M 0,0 L 10,10 M 10,0 L 0,10" />
|
|
</Button>
|
|
</StackPanel>
|
|
</Grid>
|
|
|
|
<!-- Brass divider hairline (own row so hover backgrounds can't paint over it) -->
|
|
<Border Grid.Row="1" Background="{StaticResource BrassTrim}" IsHitTestVisible="False" />
|
|
|
|
<!-- Main content -->
|
|
<Grid Grid.Row="2" RowDefinitions="Auto,Auto,*,Auto" Margin="14">
|
|
|
|
<!-- Update-available banner (hidden until manifest reports a newer launcherVersion) -->
|
|
<Border Name="UpdateBanner" Grid.Row="0" IsVisible="False"
|
|
Background="#13192A" BorderBrush="#D4A24C" BorderThickness="1"
|
|
CornerRadius="6" Padding="12 10" Margin="0 0 0 12">
|
|
<Grid ColumnDefinitions="Auto,*,Auto" VerticalAlignment="Center">
|
|
<TextBlock Grid.Column="0" Text="ⓘ" FontSize="16"
|
|
Foreground="#E8B95C" VerticalAlignment="Center" Margin="0 0 10 0" />
|
|
<TextBlock Grid.Column="1" Name="UpdateBannerText" VerticalAlignment="Center"
|
|
Foreground="#E8DFC8" FontSize="13" TextWrapping="Wrap"
|
|
Text="A newer launcher is available." />
|
|
<Button Grid.Column="2" Name="UpdateBannerDownloadButton"
|
|
Classes="secondary" Content="Install update"
|
|
Click="OnUpdateBannerDownloadClick" />
|
|
</Grid>
|
|
</Border>
|
|
|
|
<!-- Header card -->
|
|
<ContentControl Grid.Row="1" Classes="brass-panel" Margin="0 0 0 14">
|
|
<Grid ColumnDefinitions="*,Auto">
|
|
<StackPanel Grid.Column="0" Orientation="Vertical" Spacing="4">
|
|
<TextBlock Name="PackNameText" Classes="h1" Text="Modpack" />
|
|
<TextBlock Name="PackVersionText" Classes="muted" Text="No pack synced yet" />
|
|
</StackPanel>
|
|
<StackPanel Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Center" Spacing="10">
|
|
<TextBlock Name="UserText" Classes="muted" Text="Not signed in" VerticalAlignment="Center" />
|
|
<TextBlock Name="WhitelistStatusText" Classes="muted" Text="" IsVisible="False"
|
|
VerticalAlignment="Center" FontStyle="Italic" />
|
|
<Button Name="RequestAccessButton" Classes="secondary" Content="Request access"
|
|
Click="OnRequestAccessClick" IsVisible="False"
|
|
ToolTip.Tip="Send the server admin a request to whitelist your account." />
|
|
<Button Name="LoginButton" Classes="secondary" Content="Sign in" Click="OnLoginClick" />
|
|
<Button Name="LogoutButton" Classes="secondary" Content="Sign out"
|
|
Click="OnLogoutClick" IsVisible="False" />
|
|
</StackPanel>
|
|
</Grid>
|
|
</ContentControl>
|
|
|
|
<!-- Action + log -->
|
|
<Grid Grid.Row="2" RowDefinitions="Auto,*">
|
|
<ContentControl Grid.Row="0" Classes="brass-panel" Margin="0 0 0 14">
|
|
<StackPanel Spacing="14">
|
|
<Grid ColumnDefinitions="*,Auto">
|
|
<StackPanel Grid.Column="0" VerticalAlignment="Center" Spacing="2">
|
|
<TextBlock Name="StatusText" Classes="h1" Text="Ready" />
|
|
<TextBlock Name="StatusSubtext" Classes="muted"
|
|
Text="Click Play to sync the pack and launch Minecraft." />
|
|
</StackPanel>
|
|
<!-- Play button with subtle cyan glow halo behind -->
|
|
<Grid Grid.Column="1" Width="180" Height="48">
|
|
<Ellipse HorizontalAlignment="Center" VerticalAlignment="Center"
|
|
Width="200" Height="80" Fill="{StaticResource MagicGlow}"
|
|
Opacity="0.45" IsHitTestVisible="False" />
|
|
<Button Name="PlayButton" Classes="primary" Content="Play"
|
|
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
|
|
Click="OnPlayClick" />
|
|
</Grid>
|
|
</Grid>
|
|
<ProgressBar Name="ProgressBar" Classes="brass" Height="8"
|
|
Minimum="0" Maximum="100" Value="0" CornerRadius="4" />
|
|
</StackPanel>
|
|
</ContentControl>
|
|
|
|
<ContentControl Grid.Row="1" Classes="brass-panel">
|
|
<Grid RowDefinitions="Auto,*">
|
|
<Grid Grid.Row="0" ColumnDefinitions="*,Auto" Margin="0 0 0 8">
|
|
<TextBlock Grid.Column="0" Classes="h1" Text="Log" FontSize="14" />
|
|
<Button Grid.Column="1" Classes="secondary" Content="Open install folder"
|
|
Click="OnOpenFolderClick" />
|
|
</Grid>
|
|
<Border Grid.Row="1" Background="#070B16" CornerRadius="4" Padding="10"
|
|
BorderBrush="#1B233A" BorderThickness="1">
|
|
<ScrollViewer Name="LogScroll" VerticalScrollBarVisibility="Auto">
|
|
<TextBlock Name="LogText" FontFamily="Cascadia Mono, Consolas, monospace"
|
|
FontSize="12" Foreground="#B7C0D6" TextWrapping="Wrap" />
|
|
</ScrollViewer>
|
|
</Border>
|
|
</Grid>
|
|
</ContentControl>
|
|
</Grid>
|
|
|
|
<!-- Footer / settings -->
|
|
<ContentControl Grid.Row="3" Classes="brass-panel" Margin="0 14 0 0">
|
|
<StackPanel Spacing="10">
|
|
<!-- RAM allocation -->
|
|
<Grid ColumnDefinitions="Auto,Auto,*,Auto">
|
|
<TextBlock Grid.Column="0" Text="RAM" VerticalAlignment="Center" Classes="muted" />
|
|
<NumericUpDown Grid.Column="1" Name="RamBox" Margin="10 0 10 0" Width="140"
|
|
Minimum="2048" Maximum="65536" Increment="1024" FormatString="0" />
|
|
<TextBlock Grid.Column="2" Text="MB" VerticalAlignment="Center" Classes="muted" Margin="0 0 10 0" />
|
|
<TextBlock Grid.Column="3" Name="RamWarningText" VerticalAlignment="Center"
|
|
FontSize="11" TextWrapping="Wrap" />
|
|
</Grid>
|
|
<!-- Install location -->
|
|
<Grid ColumnDefinitions="Auto,*,Auto">
|
|
<TextBlock Grid.Column="0" Text="Install location" VerticalAlignment="Center" Classes="muted" />
|
|
<TextBlock Grid.Column="1" Name="InstallDirText" VerticalAlignment="Center" Margin="10 0 10 0"
|
|
TextTrimming="CharacterEllipsis" Foreground="#B7C0D6" FontSize="12" />
|
|
<Button Grid.Column="2" Classes="secondary" Content="Change..." Click="OnChangeInstallDirClick" />
|
|
</Grid>
|
|
<TextBlock Foreground="#5C6478" FontSize="10" TextWrapping="Wrap" HorizontalAlignment="Center"
|
|
Text="NOT AN OFFICIAL MINECRAFT PRODUCT. NOT APPROVED BY OR ASSOCIATED WITH MOJANG OR MICROSOFT." />
|
|
</StackPanel>
|
|
</ContentControl>
|
|
</Grid>
|
|
|
|
</Grid>
|
|
</Panel>
|
|
</Border>
|
|
</Border>
|
|
|
|
<!-- Slide-out container: starts at Width=0 so the Auto column contributes nothing.
|
|
InfoPanel inside has fixed Width=320; HorizontalAlignment=Right + ClipToBounds=True
|
|
on the container makes the panel "slide in" from the right as the container grows.
|
|
Window.Width is animated in lock-step with InfoPanelContainer.Width so the main
|
|
content (RootBorder, in the Star column) keeps its current width throughout.
|
|
Vertically: outer Grid is single-row (full window height) so this Border
|
|
stretches naturally; the inner ScrollViewer inherits it via its Auto,*
|
|
Grid row. No code-behind height management needed. -->
|
|
<Border Grid.Column="1" Name="InfoPanelContainer" Width="0"
|
|
ClipToBounds="True">
|
|
<Border Name="InfoPanel" HorizontalAlignment="Right" Width="320" Margin="14 0 0 0"
|
|
CornerRadius="10" Background="{StaticResource BrassTrim}"
|
|
ClipToBounds="True">
|
|
<Border CornerRadius="8" Background="#0F1622" Margin="2" ClipToBounds="True">
|
|
<Grid RowDefinitions="Auto,*">
|
|
<Grid Grid.Row="0" ColumnDefinitions="*,Auto" Margin="14 12 8 8">
|
|
<TextBlock Grid.Column="0" Classes="h1" Text="Pack info" FontSize="14"
|
|
VerticalAlignment="Center" />
|
|
<Button Grid.Column="1" Classes="caption" Click="OnInfoClick" ToolTip.Tip="Close"
|
|
Width="32" Height="28">
|
|
<Path Width="9" Height="9" Data="M 0,0 L 9,9 M 9,0 L 0,9" />
|
|
</Button>
|
|
</Grid>
|
|
<ScrollViewer Grid.Row="1" Name="InfoScrollViewer"
|
|
Padding="14 0 14 40"
|
|
VerticalScrollBarVisibility="Auto"
|
|
HorizontalScrollBarVisibility="Disabled">
|
|
<StackPanel Name="InfoPanelContent" Spacing="14" Margin="0 0 0 8" />
|
|
</ScrollViewer>
|
|
</Grid>
|
|
</Border>
|
|
</Border>
|
|
</Border>
|
|
</Grid>
|
|
</Window>
|