UI/HDTWelcome.xaml

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Hephaestus Deployment Toolkit"
    Height="740" Width="760"
    WindowStartupLocation="CenterScreen"
    ResizeMode="NoResize"
    WindowStyle="None"
    Background="#FF1E1E1E">
 
    <!--
        NO STYLES OF ITS OWN, AND THAT IS THE CHANGE. This window used to carry
        an inline copy of the Button, ToggleButton, TextBox, PasswordBox and
        HDTAddressBox styles - about 120 lines HDTTheme.xaml already had, in
        literal colours rather than the theme's tokens. It was the ONE screen a
        palette change could not reach, because Show-HDTWizard had no theme to
        merge while Show-HDTWizardShell did, and it had already drifted once:
        the address boxes stayed 32 high after the theme moved to 34.
 
        THE THEME IS MERGED AT RUNTIME, NOT WITH ResourceDictionary Source=.
        A Source= reference is a second file that has to reach the RAM disk
        intact, and a half-copied one is a XamlParseException where the first
        screen of a deployment should be; WinPeUiStack.Contract.Tests.ps1
        refuses one. New-HDTWizardHost adds the dictionary to this window's
        Resources after XamlReader::Load returns - which is why every reference
        below is a DynamicResource: a StaticResource is resolved during the
        parse, when the theme is not there yet.
 
        WHY THE STYLES EXIST AT ALL is in HDTTheme.xaml beside each one: WPF's
        default Button template paints its own light hover chrome underneath the
        content, so white-on-dark becomes unreadable the moment the mouse
        touches it, and the eye's glyph is drawn from geometry because Segoe
        MDL2 Assets is not guaranteed to be in a WinPE image.
    -->
 
 
    <!--
        NO TITLE BAR, AND THEREFORE NO X. In WinPE there is no desktop, no
        taskbar and nothing to switch to, so the chrome is vestigial - but the
        close button is worse than vestigial: it is a third way out of the
        wizard that goes round the buttons. Show-HDTWizard maps a dismissed
        window to Cancel precisely so that cannot mean "yes", but a technician
        who closes the deployment wizard lands at a bare X:\Windows\System32>
        prompt with no idea what happened. Cancel and Open CMD are the two ways
        out, and both of them say what they do.
 
        MDT's LiteTouch fills the screen for the same reason.
    -->
 
    <!--
        THE WELCOME SCREEN - MDT's LiteTouch Welcome, rebuilt.
 
        THIS IS THE ONE PANE THAT MUST LIVE IN THE BOOT IMAGE, and not by
        preference: it runs BEFORE any share is reachable, so it cannot be read
        from one. Every pane after it - task sequence, computer name, summary,
        progress - lives on the share under Scripts\UI\ and is read after
        connecting, exactly as MDT reads DeployWiz_*.xml, so those can be
        redesigned without rebuilding anything.
 
        THREE PANES, EACH INDEPENDENTLY HIDEABLE (MDT's Skip* properties, under
        the HDT prefix, resolved by the ordinary rules engine):
 
            HDTSkipStaticIp hides the network group; DHCP is used
            HDTSkipDeployRoot hides the share box; bootstrap.json's value wins
            HDTSkipCredential hides the account group; the embedded one wins
            HDTSkipWelcome skips this window entirely
 
        A pane appears only when it has something to ask or a rule asks for it,
        because the UNATTENDED PATH IS THE DEFAULT: an image carrying an
        embedded credential and a resolved task sequence still deploys with
        nobody present, and the zero-keystroke E2E proves it.
 
        STATIC IP IS APPLIED THROUGH WMI, not NetTCPIP. SPIKES S14: Get-NetIPAddress
        does not exist in a WinPE image built from the ADK - it is what killed
        the first SMB probe. Win32_NetworkAdapterConfiguration is guaranteed by
        WinPE-WMI.
 
        No x:Class, no code-behind, no external resource dictionary - there is
        no compiler in WinPE and every extra file is another thing that has to
        reach the RAM disk intact. tests/contract/WinPeUiStack.Contract.Tests.ps1
        asserts all three, over every window.
    -->
 
    <Grid Background="#FF1E1E1E">
        <Grid.RowDefinitions>
            <RowDefinition Height="104" />
            <RowDefinition Height="*" />
            <RowDefinition Height="72" />
        </Grid.RowDefinitions>
 
        <Border Grid.Row="0" Background="#FF0E639C" x:Name="HDTDragBanner">
            <StackPanel VerticalAlignment="Center" Margin="28,0,28,0">
                <TextBlock x:Name="HDTWelcomeTitleText"
                           Foreground="White" FontSize="30" FontWeight="SemiBold" />
                <TextBlock x:Name="HDTWelcomeSubtitleText"
                           Foreground="#FFD6E9F5" FontSize="16" Margin="0,4,0,0" />
            </StackPanel>
        </Border>
 
        <!--
            NO ScrollViewer. A deployment wizard that scrolls hides a field
            from a technician who does not know it is there, and this screen is
            fixed - three panes, known size - so it is laid out to fit instead.
            The window is sized to the content rather than the content squeezed
            into the window.
        -->
        <StackPanel Grid.Row="1" Margin="28,18,28,0">
 
                <!-- ============ network ============ -->
                <StackPanel x:Name="HDTNetworkPane">
                    <TextBlock x:Name="HDTWelcomeNetworkHeading" Foreground="White" FontSize="19" FontWeight="SemiBold" />
 
                    <RadioButton x:Name="HDTUseDhcpRadio"
                                 GroupName="HDTAddressMode" IsChecked="True"
                                 Foreground="#FFCCCCCC" FontSize="16" Margin="0,10,0,0" />
                    <RadioButton x:Name="HDTUseStaticRadio"
                                 GroupName="HDTAddressMode"
                                 Foreground="#FFCCCCCC" FontSize="16" Margin="0,6,0,0" />
 
                    <Grid x:Name="HDTStaticGrid" Margin="22,8,0,0">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="155" />
                            <ColumnDefinition Width="220" />
                            <ColumnDefinition Width="130" />
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="36" />
                            <RowDefinition Height="36" />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>
 
                        <TextBlock Grid.Row="0" Grid.Column="0" x:Name="HDTWelcomeIpAddressLabel"
                                   Foreground="#FFCCCCCC" FontSize="15" VerticalAlignment="Center" />
                        <TextBox Grid.Row="0" Grid.Column="1" x:Name="HDTIpAddressBox" Style="{DynamicResource HDTAddressBox}" />
 
                        <TextBlock Grid.Row="0" Grid.Column="2" x:Name="HDTWelcomeSubnetMaskLabel"
                                   Foreground="#FFCCCCCC" FontSize="15" VerticalAlignment="Center" Margin="12,0,0,0" />
                        <TextBox Grid.Row="0" Grid.Column="3" x:Name="HDTSubnetMaskBox" Style="{DynamicResource HDTAddressBox}" />
 
                        <TextBlock Grid.Row="1" Grid.Column="0" x:Name="HDTWelcomeGatewayLabel"
                                   Foreground="#FFCCCCCC" FontSize="15" VerticalAlignment="Center" />
                        <TextBox Grid.Row="1" Grid.Column="1" x:Name="HDTGatewayBox" Style="{DynamicResource HDTAddressBox}" />
 
                        <TextBlock Grid.Row="1" Grid.Column="2" x:Name="HDTWelcomeDnsLabel"
                                   Foreground="#FFCCCCCC" FontSize="15" VerticalAlignment="Center" Margin="12,0,0,0" />
                        <TextBox Grid.Row="1" Grid.Column="3" x:Name="HDTDnsBox" Style="{DynamicResource HDTAddressBox}" />
 
                        <!--
                            UNDER THE BOX IT DESCRIBES, NOT A TOOLTIP. It sat
                            under the IP address column while describing a box
                            two columns to its right, which is worse than not
                            being there. A tooltip was the alternative and is
                            wrong here for two reasons: the credential pane
                            already puts its hint directly under the Domain box,
                            so a tooltip would be the one inconsistent
                            affordance on the screen; and hover is invisible - a
                            technician on a bench in WinPE has no reason to
                            discover it, and Set-HDTStaticAddress genuinely
                            needs the comma to split the list.
                        -->
                        <TextBlock Grid.Row="2" Grid.Column="3" x:Name="HDTDnsHint"
                                   Foreground="#FF8A8A8A" FontSize="14"
                                   Margin="2,2,0,0" TextWrapping="Wrap" />
                    </Grid>
                </StackPanel>
 
                <!-- ============ share ============ -->
                <StackPanel x:Name="HDTDeployRootPane" Margin="0,22,0,0">
                    <TextBlock x:Name="HDTWelcomeShareHeading" Foreground="White" FontSize="19" FontWeight="SemiBold" />
 
                    <Grid Margin="0,10,0,0">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="155" />
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>
 
                        <TextBlock Grid.Row="0" Grid.Column="0" x:Name="HDTWelcomeShareLabel"
                                   Foreground="#FFCCCCCC" FontSize="15" VerticalAlignment="Center" />
                        <TextBox Grid.Row="0" Grid.Column="1" x:Name="HDTDeployRootBox"
                                   VerticalContentAlignment="Center"
                                   Background="#FF2D2D30" Foreground="White" BorderBrush="#FF3F3F46" />
 
                        <!--
                            THE BOX IS EMPTY AND NOBODY IS COMING TO FILL IT.
                            An image built with no deployRoot reaches this screen
                            with nothing to connect to, and an empty box on its
                            own reads as "optional". This says otherwise, and it
                            is amber rather than red because nothing has failed
                            yet - the technician simply has to type it.
 
                            Collapsed by default: the host shows it only when the
                            boot image carried no share.
                        -->
                        <TextBlock Grid.Row="1" Grid.Column="1" x:Name="HDTDeployRootHint"
                                   Visibility="Collapsed"
                                   Foreground="#FFD9A441" FontSize="14" TextWrapping="Wrap"
                                   Margin="2,6,0,0" />
                    </Grid>
                </StackPanel>
 
                <!-- ============ account ============ -->
                <StackPanel x:Name="HDTCredentialPane" Margin="0,22,0,0">
                    <TextBlock x:Name="HDTWelcomeAccountHeading" Foreground="White" FontSize="19" FontWeight="SemiBold" />
 
                    <Grid Margin="0,10,0,0">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="155" />
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="36" />
                            <RowDefinition Height="36" />
                            <RowDefinition Height="20" />
                            <RowDefinition Height="36" />
                        </Grid.RowDefinitions>
 
                        <TextBlock Grid.Row="0" Grid.Column="0" x:Name="HDTWelcomeUserIdLabel"
                                   Foreground="#FFCCCCCC" FontSize="15" VerticalAlignment="Center" />
                        <TextBox Grid.Row="0" Grid.Column="1" x:Name="HDTUserIdBox"
                                   VerticalContentAlignment="Center"
                                   Background="#FF2D2D30" Foreground="White" BorderBrush="#FF3F3F46" />
 
                        <TextBlock Grid.Row="1" Grid.Column="0" x:Name="HDTWelcomeUserDomainLabel"
                                   Foreground="#FFCCCCCC" FontSize="15" VerticalAlignment="Center" />
                        <TextBox Grid.Row="1" Grid.Column="1" x:Name="HDTUserDomainBox"
                                   VerticalContentAlignment="Center"
                                   Background="#FF2D2D30" Foreground="White" BorderBrush="#FF3F3F46" />
 
                        <TextBlock Grid.Row="2" Grid.Column="1" x:Name="HDTUserDomainHint"
                                   Foreground="#FF8A8A8A" FontSize="14" Margin="2,0,0,0" />
 
                        <TextBlock Grid.Row="3" Grid.Column="0" x:Name="HDTWelcomePasswordLabel"
                                   Foreground="#FFCCCCCC" FontSize="15" VerticalAlignment="Center" />
                        <!--
                            TWO BOXES IN ONE CELL, and only one of them visible
                            at a time. PasswordBox.Password is not a
                            DependencyProperty, so it cannot be bound and the
                            reveal cannot be done declaratively: the host swaps
                            the text and the visibility (New-HDTWizardHost),
                            which is why both carry x:Name.
                        -->
                        <Grid Grid.Row="3" Grid.Column="1">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*" />
                                <ColumnDefinition Width="Auto" />
                            </Grid.ColumnDefinitions>
 
                            <PasswordBox Grid.Column="0" x:Name="HDTPasswordBox"
                                         VerticalContentAlignment="Center"
                                         Background="#FF2D2D30" Foreground="White" BorderBrush="#FF3F3F46" />
 
                            <TextBox Grid.Column="0" x:Name="HDTPasswordRevealBox"
                                     Visibility="Collapsed" VerticalContentAlignment="Center"
                                     Background="#FF2D2D30" Foreground="White" BorderBrush="#FF3F3F46" />
 
                            <ToggleButton Grid.Column="1" x:Name="HDTPasswordRevealToggle"
                                          Width="38" Height="34" Margin="6,0,0,0">
                                <Grid Width="22" Height="16">
                                    <Path Data="M 1,8 C 5,2.5 17,2.5 21,8 C 17,13.5 5,13.5 1,8 Z"
                                          Stroke="{Binding Foreground, RelativeSource={RelativeSource AncestorType=ToggleButton}}"
                                          StrokeThickness="1.3" />
                                    <Ellipse Width="6" Height="6"
                                             HorizontalAlignment="Center" VerticalAlignment="Center"
                                             Fill="{Binding Foreground, RelativeSource={RelativeSource AncestorType=ToggleButton}}" />
                                </Grid>
                            </ToggleButton>
                        </Grid>
                    </Grid>
                </StackPanel>
 
                <TextBlock x:Name="HDTMessageText" Text=""
                           Foreground="#FFF48771" FontSize="15"
                           Margin="0,18,0,12" TextWrapping="Wrap" />
        </StackPanel>
 
        <!--
            A GRID, NOT A StackPanel, because the footer now has two ends: the
            command prompt on the left and the wizard's own buttons on the right.
 
            HDTOpenCmdButton is MDT's "Exit to Command Prompt" - the escape
            hatch a technician reaches for when the network is wrong, a driver
            is missing, or they simply need diskpart. WinPE gives it on F8, but
            F8 is folklore; a button is discoverable.
        -->
        <Border Grid.Row="2" Background="#FF252526">
            <Grid Margin="28,0,28,0">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
 
                <Button Grid.Column="0" x:Name="HDTOpenCmdButton"
                        Width="120" Height="34" HorizontalAlignment="Left" VerticalAlignment="Center"
                        Background="#FF3C3C3C" BorderThickness="0" />
 
                <StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right"
                            VerticalAlignment="Center">
                    <Button x:Name="HDTCancelButton"
                            Width="112" Height="34" Margin="0,0,12,0"
                            Background="#FF3C3C3C" BorderThickness="0" />
                    <Button x:Name="HDTNextButton"
                            Width="112" Height="34"
                            Background="#FF0E639C" BorderThickness="0"
                            IsDefault="True" />
                </StackPanel>
            </Grid>
        </Border>
    </Grid>
</Window>