UI/HDTProgress.xaml

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Hephaestus Deployment Toolkit"
    WindowStyle="None"
    WindowState="Maximized"
    ResizeMode="NoResize"
    Background="#FF1E1E1E">
 
    <!--
        DESIGN 11.1'S PROGRESS WINDOW, IN MDT'S SHAPE: a modest card in the
        middle of a full-screen backdrop.
 
        BOTH HALVES ARE LOAD-BEARING AND THEY COME FROM DIFFERENT PLACES.
 
        THE CARD IS MDT'S. LiteTouch shows a centred "Installation Progress"
        dialog - sequence, step, a bar - and an admin has watched that dialog a
        thousand times. A full-screen takeover of numbers reads as a kiosk
        rather than as a deployment, and the first draft of this file was one.
 
        THE BACKDROP IS WinPE'S. It is why DESIGN 11.1 asked for full-screen at
        all: behind this window is a console the payload hid, and around a small
        dialog a technician would see the black edges of a half-drawn
        X:\Windows\system32> prompt - which is the exact thing this section
        exists to stop them seeing. MDT solves it with a deployment wallpaper;
        this solves it with the window's own ground.
 
        NO X, NO TITLE BAR, NO BUTTONS. There is nothing here to answer - it is
        a status board, not a dialog - and a deployment screen with a corner
        that makes it disappear is a deployment nobody can account for.
 
        EVERY VALUE COMES FROM Get-HDTDeploymentProgress, which derives it from
        the JSONL stream the engine writes anyway (DESIGN 11.1: driven by the
        event stream, not by a parallel progress API). The screen and the log
        cannot disagree, because they are the same facts.
 
        NO x:Class AND NO MERGED DICTIONARY, for the reason every window in this
        image carries: there is no compiler in WinPE, and a second file that
        must reach the RAM disk intact is a XamlParseException waiting for the
        one machine nobody can debug.
    -->
 
    <!--
        THE SAME GROUND THE WIZARD STANDS ON. This was a navy backdrop, which
        made the two surfaces of one product look like two products - a
        technician sees the wizard and then this, minutes apart, on the same
        machine. HDTWizardShell.xaml paints #FF1E1E1E and its panels #FF252526,
        and so does this.
 
        THE ROOT PAINTS ITS OWN GROUND. Window.Background alone is not enough:
        anything rendering this tree without the Window around it gets whatever
        is behind it, and it cost exactly one screenshot to learn that on the
        wizard.
    -->
    <Grid Background="#FF1E1E1E">
 
        <!--
            THE CARD. Fixed width so the layout does not reflow on a 1024x768
            WinPE screen and a 1920x1080 one into two different-looking
            products; centred both ways so it lands where a dialog would.
        -->
        <Border Width="720" VerticalAlignment="Center" HorizontalAlignment="Center"
                Background="#FF252526" BorderBrush="#FF3A3A3C" BorderThickness="1">
            <StackPanel Margin="36,30,36,30">
 
                <!-- ============ who this machine is ============ -->
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="Auto" />
                    </Grid.ColumnDefinitions>
 
                    <StackPanel Grid.Column="0">
                        <TextBlock x:Name="HDTProgressComputerName" Text="" Foreground="White"
                                   FontSize="26" FontWeight="SemiBold" TextTrimming="CharacterEllipsis" />
                        <TextBlock x:Name="HDTProgressSequenceName" Text="" Foreground="#FFCCCCCC"
                                   FontSize="15" Margin="0,4,0,0" TextTrimming="CharacterEllipsis" />
                    </StackPanel>
 
                    <!--
                        THE PHASE ANSWERS THE FIRST QUESTION a technician has
                        about a machine that has been running twenty minutes:
                        has it rebooted yet, or is it still in WinPE?
                    -->
                    <Border Grid.Column="1" Background="#FF0E639C" Padding="14,5" VerticalAlignment="Top">
                        <TextBlock x:Name="HDTProgressPhase" Text="" Foreground="White"
                                   FontSize="14" FontWeight="SemiBold" />
                    </Border>
                </Grid>
 
                <Border Height="1" Background="#FF3A3A3C" Margin="0,22,0,22" />
 
                <!-- ============ what it is doing ============ -->
                <TextBlock x:Name="HDTProgressStepGroup" Text="" Foreground="#FF8A8A8A"
                           FontSize="13" Margin="0,0,0,6" TextTrimming="CharacterEllipsis" />
 
                <!--
                    TWO LINES OF ROOM AND NO MORE. A step name is authored on the
                    share and can be any length; without a bound, a long one
                    would push the bar off the card - and the bar is the control
                    a technician is actually looking at.
                -->
                <TextBlock x:Name="HDTProgressStepName" Text="" Foreground="White"
                           FontSize="20" TextWrapping="Wrap" MaxHeight="56"
                           TextTrimming="CharacterEllipsis" />
 
                <!--
                    THE COUNTER AND THE STEP'S OWN PERCENTAGE SHARE A LINE, and
                    the percentage is here rather than beside its bar so that
                    both bars are the same width. A bar with a caption at the
                    end of it is a bar that stops short of the one above it, and
                    the pair then reads as ragged rather than as two measures of
                    the same machine.
                -->
                <Grid Margin="0,10,0,0">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="Auto" />
                    </Grid.ColumnDefinitions>
 
                    <TextBlock Grid.Column="0" x:Name="HDTProgressStepCounter" Text=""
                               Foreground="#FFCCCCCC" FontSize="15" />
 
                    <TextBlock Grid.Column="1" x:Name="HDTProgressStepPercent" Text=""
                               Foreground="#FFCCCCCC" FontSize="15" Margin="10,0,0,0" />
                </Grid>
 
                <!--
                    A REAL BAR, NOT A MARQUEE. An indeterminate animation says
                    "not hung" and nothing else; the counter above and the fill
                    here say how far through the sequence this machine is.
                -->
                <ProgressBar x:Name="HDTProgressBar" Height="14" Minimum="0" Maximum="100" Value="0"
                             Margin="0,16,0,0" Background="#FF1E1E1E" Foreground="#FF0E639C"
                             BorderBrush="#FF3A3A3C" BorderThickness="1" />
 
                <!--
                    THE SECOND BAR IS MDT'S TOO. LiteTouch shows the sequence's
                    progress and the current operation's, one above the other,
                    and an admin has read that pair a thousand times.
 
                    IT IS THE ONLY THING ON THIS CARD THAT MOVES DURING AN
                    APPLY. Writing 18 GB of Windows is one step: the counter,
                    the sequence bar and the step name are all correct and
                    motionless for nine minutes, and a motionless screen is
                    indistinguishable from a hung machine to the person standing
                    in front of it. dism prints a percentage as it works and
                    DESIGN 11.1 carries it here through the log.
 
                    THINNER, AND A LIGHTER BLUE. It is subordinate to the bar
                    above it - one step of the sequence, not the sequence - and
                    at a glance from across a room the two must not be mistaken
                    for each other.
 
                    COLLAPSED UNTIL SOMETHING REPORTS. Most steps take a second
                    and say nothing about themselves; an empty bar sitting at
                    zero under every one of them is a control that looks broken.
                -->
                <ProgressBar x:Name="HDTProgressStepBar" Height="8" Minimum="0" Maximum="100" Value="0"
                             Margin="0,8,0,0" Visibility="Collapsed"
                             Background="#FF1E1E1E" Foreground="#FF3794FF"
                             BorderBrush="#FF3A3A3C" BorderThickness="1" />
 
                <!-- ============ how long, and how it is going ============ -->
                <Grid Margin="0,18,0,0">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="Auto" />
                    </Grid.ColumnDefinitions>
 
                    <!--
                        THE STATUS LINE IS WHERE A FAILURE LANDS, painted by a
                        trigger on the text rather than by the engine - the same
                        split the wizard's rail and message line use: the engine
                        states what a thing IS and the markup decides what that
                        looks like.
                    -->
                    <TextBlock Grid.Column="0" x:Name="HDTProgressStatus" Text=""
                               FontSize="15" VerticalAlignment="Center">
                        <TextBlock.Style>
                            <Style TargetType="TextBlock">
                                <Setter Property="Foreground" Value="#FFCCCCCC" />
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding Tag, RelativeSource={RelativeSource Self}}" Value="Failed">
                                        <Setter Property="Foreground" Value="#FFF48771" />
                                        <Setter Property="FontWeight" Value="SemiBold" />
                                    </DataTrigger>
                                    <DataTrigger Binding="{Binding Tag, RelativeSource={RelativeSource Self}}" Value="Succeeded">
                                        <Setter Property="Foreground" Value="#FF89D185" />
                                        <Setter Property="FontWeight" Value="SemiBold" />
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </TextBlock.Style>
                    </TextBlock>
 
                    <TextBlock Grid.Column="1" x:Name="HDTProgressElapsed" Text="" Foreground="#FF8A8A8A"
                               FontSize="15" VerticalAlignment="Center" />
                </Grid>
            </StackPanel>
        </Border>
    </Grid>
</Window>