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"
    ResizeMode="NoResize"
    SizeToContent="WidthAndHeight"
    WindowStartupLocation="CenterScreen"
    Topmost="True"
    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 GONE, AND THE REASON IT EXISTED EXPIRED. DESIGN 11.1
        asked for full-screen because behind this window was a console the
        payload hid only for the wizard, and around a small dialog a technician
        would have seen the black edges of a half-drawn X:\Windows\system32>
        prompt. Start-HDTDeployment now hides that console at step 4a, for the
        whole run, and a boot image's BGInfo paints the machine's serial, model
        and address onto the wallpaper - so a full-screen ground had become a
        sheet covering the very thing it was invented to protect anybody from
        seeing. MDT solves this with a deployment wallpaper, and now so does
        this: the card, on the wallpaper, and nothing else.
 
        SizeToContent, NOT A HEIGHT SOMEBODY MAINTAINS. Every part of this card
        that can grow is already bounded - the step name wraps to MaxHeight 56,
        the step bar collapses when nothing is reporting - so the window is
        exactly as tall as what is in it, on a 1024x768 WinPE screen and a
        1920x1080 bench machine alike.
 
        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.
 
        Topmost, AND ONLY BECAUSE THIS WINDOW OUTLIVES WinPE. In WinPE there
        is no shell to compete with - cmd.exe is it - but the full-OS leg draws
        this board on a DESKTOP, and a deployed machine showed the taskbar and
        the Start menu opening straight over it. It is opaque, so unlike the boot
        status panel it obeys z-order properly and Topmost does what it says.
 
        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>