UI/Console/HDTSelectionProfile.xaml

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Selection profiles"
    Height="720" Width="1120"
    MinHeight="480" MinWidth="860"
    WindowStartupLocation="Manual"
    Background="{DynamicResource HDTWindowBrush}">
 
    <!--
        THE SELECTION PROFILES WINDOW - Deployment Workbench's Advanced
        Configuration \ Selection Profiles, which is where an MDT admin has
        defined "which folders does this thing use" for fifteen years.
 
        IT IS A WINDOW AND NOT A TAB ON THE BOOT IMAGE, and that is deliberate.
        A profile is SHARE-WIDE: DESIGN 13 calls standalone media a content
        projection of the share, and a selection profile is that projection's
        filter, so the same document that picks two vendor WinPE packs for a boot
        image picks which applications go on a USB stick. Hanging it off the boot
        image would say it was about drivers, and then the media code would need
        a second one.
 
        THE TREE IS TICK BOXES BECAUSE AN ADMINISTRATOR KNOWS THE FOLDER BY
        SEEING IT. That is MDT's control here, and the reason a profile's include
        list is a set of paths rather than a pattern: the thing being chosen is
        on the screen.
 
        THE SQUARE IS THE CONTROL THAT MATTERS. Drivers ticked is the whole store
        - six hundred .inf files in a boot image that is transferred to every
        machine that PXE boots. Drivers SQUARE, with two vendor packs ticked
        below it, is a hundred. A two-state box cannot tell those apart without
        opening every branch.
 
        NOTHING ON THIS WINDOW EXISTS WITHOUT A COMMAND BEHIND IT:
 
          Profiles list Get-HDTSelectionProfile
          New New-HDTSelectionProfile
          Rename Set-HDTSelectionProfile -Name
          Delete Remove-HDTSelectionProfile
          The tree Get-HDTShareContentFolder
          Save Set-HDTSelectionProfile -Include,
                           Save-HDTSelectionProfileDocument
 
        NO x:Class AND NO CODE-BEHIND, as HDTConsole.xaml and HDTBootImage.xaml.
        Handlers attach in PowerShell, by name.
 
        NAMED CONTROLS ARE THE CONTRACT with New-HDTConsoleHost:
        HDTSelectionProfileTitleText, HDTSelectionProfilePathText,
        HDTSelectionProfileListLabel, HDTSelectionProfileList,
        HDTSelectionProfileNewButton, HDTSelectionProfileRenameButton,
        HDTSelectionProfileDeleteButton, HDTSelectionProfileIncludeLabel,
        HDTSelectionProfileIncludeHint, HDTSelectionProfileTree,
        HDTSelectionProfileSummaryText, HDTSelectionProfileCommandText,
        HDTSelectionProfileSaveButton and HDTSelectionProfileCloseButton.
 
        THE PALETTE IS THE CONSOLE'S - every colour a DynamicResource under the
        keys HDTConsole.xaml declares, so Get-HDTConsoleTheme repaints this
        window with the others.
    -->
    <Window.Resources>
        <SolidColorBrush x:Key="HDTWindowBrush" Color="#FFF3F3F3" />
        <SolidColorBrush x:Key="HDTBannerBrush" Color="#FF0E639C" />
        <SolidColorBrush x:Key="HDTBannerTextBrush" Color="#FFFFFFFF" />
        <SolidColorBrush x:Key="HDTBannerLabelBrush" Color="#FFD6E9F5" />
        <SolidColorBrush x:Key="HDTPanelBrush" Color="#FFFFFFFF" />
        <SolidColorBrush x:Key="HDTPanelTextBrush" Color="#FF1B1B1B" />
        <SolidColorBrush x:Key="HDTBorderBrush" Color="#FFC8C8C8" />
        <SolidColorBrush x:Key="HDTLabelBrush" Color="#FF0E639C" />
        <SolidColorBrush x:Key="HDTHintBrush" Color="#FF6A6A6A" />
        <SolidColorBrush x:Key="HDTCommandBrush" Color="#FFF7F7F7" />
        <SolidColorBrush x:Key="HDTCommandTextBrush" Color="#FF0A3069" />
        <SolidColorBrush x:Key="HDTFieldBrush" Color="#FFEDEDED" />
        <SolidColorBrush x:Key="HDTFooterBrush" Color="#FFE8E8E8" />
        <SolidColorBrush x:Key="HDTButtonBrush" Color="#FF0E639C" />
        <SolidColorBrush x:Key="HDTButtonTextBrush" Color="#FFFFFFFF" />
        <SolidColorBrush x:Key="HDTButtonHoverBrush" Color="#FFCCE4F7" />
        <SolidColorBrush x:Key="HDTButtonHoverTextBrush" Color="#FF000000" />
        <SolidColorBrush x:Key="HDTButtonPressedBrush" Color="#FFA9CFEC" />
 
        <!-- The console's button, template and all. See HDTConsole.xaml for why
             the colours are Setters inside a ControlTemplate rather than local
             values on the element. -->
        <!--
            THE ? THIS PRODUCT ALREADY HAS, copied verbatim from
            HDTNewWorkspace.xaml, which shares it with HDTNewSequence,
            HDTImportApplication, HDTApplicationDetection, HDTConsole and
            HDTSequenceEditor. A 22px outlined dot with a bold glyph and a help
            cursor - not a solid button, which is what this tab first got and
            what made it read as a different kind of control.
        -->
<Style TargetType="Border" x:Key="HDTHelpDot">
            <Setter Property="Background" Value="Transparent" />
            <Setter Property="Width" Value="22" />
            <Setter Property="Height" Value="22" />
            <Setter Property="CornerRadius" Value="11" />
            <Setter Property="BorderBrush" Value="{DynamicResource HDTBorderBrush}" />
            <Setter Property="BorderThickness" Value="1" />
            <Setter Property="HorizontalAlignment" Value="Right" />
            <Setter Property="VerticalAlignment" Value="Center" />
            <Setter Property="Cursor" Value="Help" />
            <Setter Property="Margin" Value="8,0,0,10" />
            <Setter Property="ToolTipService.ShowDuration" Value="60000" />
            <Setter Property="ToolTipService.InitialShowDelay" Value="200" />
        </Style>
 
        <Style TargetType="TextBlock" x:Key="HDTHelpGlyph">
            <Setter Property="Text" Value="?" />
            <Setter Property="Foreground" Value="{DynamicResource HDTHintTextBrush}" />
            <Setter Property="FontSize" Value="12" />
            <Setter Property="FontWeight" Value="Bold" />
            <Setter Property="HorizontalAlignment" Value="Center" />
            <Setter Property="VerticalAlignment" Value="Center" />
        </Style>
 
        <Style TargetType="Button">
            <Setter Property="Background" Value="{DynamicResource HDTButtonBrush}" />
            <Setter Property="Foreground" Value="{DynamicResource HDTButtonTextBrush}" />
            <Setter Property="BorderThickness" Value="0" />
            <Setter Property="FontSize" Value="13" />
            <Setter Property="Padding" Value="14,6,14,6" />
            <Setter Property="Margin" Value="0,0,8,0" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button">
                        <Border x:Name="HDTButtonSurface"
                                Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}">
                            <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"
                                              Margin="{TemplateBinding Padding}" />
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter TargetName="HDTButtonSurface" Property="Background"
                                        Value="{DynamicResource HDTButtonHoverBrush}" />
                                <Setter Property="Foreground"
                                        Value="{DynamicResource HDTButtonHoverTextBrush}" />
                            </Trigger>
                            <Trigger Property="IsPressed" Value="True">
                                <Setter TargetName="HDTButtonSurface" Property="Background"
                                        Value="{DynamicResource HDTButtonPressedBrush}" />
                                <Setter Property="Foreground"
                                        Value="{DynamicResource HDTButtonHoverTextBrush}" />
                            </Trigger>
                            <!-- A disabled action must LOOK disabled. Remove
                                 means nothing until a row is selected, and a
                                 bright button that does nothing when pressed is
                                 how an administrator concludes the window is
                                 broken. -->
                            <Trigger Property="IsEnabled" Value="False">
                                <Setter TargetName="HDTButtonSurface" Property="Background"
                                        Value="{DynamicResource HDTFooterBrush}" />
                                <Setter Property="Foreground"
                                        Value="{DynamicResource HDTBorderBrush}" />
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
 
        <Style TargetType="TextBlock">
            <Setter Property="Foreground" Value="{DynamicResource HDTPanelTextBrush}" />
            <Setter Property="FontFamily" Value="Segoe UI" />
            <Setter Property="FontSize" Value="13" />
        </Style>
 
        <!-- The hint under a field: the same size, deliberately quieter. It
             says what an EMPTY box means, which is the question every one of
             these fields raises and none of them can answer by itself. -->
        <Style x:Key="HDTHintText" TargetType="TextBlock">
            <Setter Property="Foreground" Value="{DynamicResource HDTHintBrush}" />
            <Setter Property="FontFamily" Value="Segoe UI" />
            <Setter Property="FontSize" Value="12" />
            <Setter Property="TextWrapping" Value="Wrap" />
        </Style>
 
        <!-- WHITE, BECAUSE THESE ARE TYPED INTO. HDTFieldBrush is the read-only
             wash the console's detail pane puts on rows that are a reading
             rather than a setting; every box on this window is a setting. It
             wore the wash for months and nobody could tell, because the wash
             was #FAFAFA and invisible against white - the moment it became a
             grey somebody could see, this window started claiming its image
             name could not be changed. -->
        <Style TargetType="TextBox">
            <Setter Property="Background" Value="{DynamicResource HDTPanelBrush}" />
            <Setter Property="Foreground" Value="{DynamicResource HDTPanelTextBrush}" />
            <Setter Property="BorderBrush" Value="{DynamicResource HDTBorderBrush}" />
            <Setter Property="BorderThickness" Value="1" />
            <Setter Property="FontFamily" Value="Segoe UI" />
            <Setter Property="FontSize" Value="13" />
            <Setter Property="Padding" Value="6,4,6,4" />
        </Style>
 
        <Style TargetType="ComboBox">
            <Setter Property="FontFamily" Value="Segoe UI" />
            <!-- AND IT MUST NOT LOOK READ-ONLY. WPF's default ComboBox
                 template paints its own grey chrome and ignores Background, so
                 a dropdown beside white boxes reads as a disabled one.
                 IsEditable puts a real text box in the closed control, which
                 takes the Background; IsReadOnly keeps it from being typed
                 into. No ComboBox here uses an ItemTemplate, so what it shows
                 is what it showed before. -->
            <Setter Property="IsEditable" Value="True" />
            <Setter Property="IsReadOnly" Value="True" />
            <Setter Property="Background" Value="{DynamicResource HDTPanelBrush}" />
            <Setter Property="Foreground" Value="{DynamicResource HDTPanelTextBrush}" />
            <Setter Property="BorderBrush" Value="{DynamicResource HDTBorderBrush}" />
            <Setter Property="BorderThickness" Value="1" />
            <Setter Property="FontSize" Value="13" />
            <Setter Property="Padding" Value="6,4,6,4" />
        </Style>
 
        <Style TargetType="CheckBox">
            <Setter Property="Foreground" Value="{DynamicResource HDTPanelTextBrush}" />
            <Setter Property="FontFamily" Value="Segoe UI" />
            <Setter Property="FontSize" Value="13" />
        </Style>
 
        <Style TargetType="TabItem">
            <Setter Property="Foreground" Value="{DynamicResource HDTPanelTextBrush}" />
            <Setter Property="FontFamily" Value="Segoe UI" />
            <Setter Property="FontSize" Value="12" />
            <Setter Property="Padding" Value="14,5,14,5" />
        </Style>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
 
        <!-- the banner: which share these profiles belong to -->
        <Border Grid.Row="0" Background="{DynamicResource HDTBannerBrush}" Padding="24,14,24,14">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
 
                <TextBlock Grid.Row="0" x:Name="HDTSelectionProfileTitleText"
                           Foreground="{DynamicResource HDTBannerTextBrush}"
                           FontFamily="Segoe UI" FontSize="19" />
 
                <TextBlock Grid.Row="1" x:Name="HDTSelectionProfilePathText"
                           Text=""
                           Foreground="{DynamicResource HDTBannerLabelBrush}"
                           FontFamily="Consolas, Courier New" FontSize="12"
                           Margin="0,4,0,0" />
            </Grid>
        </Border>
 
        <Grid Grid.Row="1" Margin="24,18,24,0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="300" />
                <ColumnDefinition Width="18" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
 
            <!-- ================= the profiles themselves ================= -->
            <Grid Grid.Column="0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="*" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
 
                <TextBlock Grid.Row="0" x:Name="HDTSelectionProfileListLabel" Margin="0,0,0,6"
                           Foreground="{DynamicResource HDTLabelBrush}" FontWeight="SemiBold" />
 
                <Border Grid.Row="1" Background="{DynamicResource HDTPanelBrush}"
                        BorderBrush="{DynamicResource HDTBorderBrush}" BorderThickness="1">
                    <ListBox x:Name="HDTSelectionProfileList" BorderThickness="0" Padding="4"
                             Background="Transparent">
                        <ListBox.ItemTemplate>
                            <DataTemplate>
                                <!--
                                    THE NAME, THEN WHAT IT CARRIES. A list of
                                    names alone makes an administrator click each
                                    one to find out which is the empty profile
                                    they started on Tuesday.
                                -->
                                <StackPanel Margin="4,4,4,4">
                                    <TextBlock Text="{Binding Name}" />
                                    <TextBlock Text="{Binding Detail}" FontSize="11"
                                               Foreground="{DynamicResource HDTHintBrush}" />
                                </StackPanel>
                            </DataTemplate>
                        </ListBox.ItemTemplate>
                    </ListBox>
                </Border>
 
                <!--
                    THE BUILT-INS ARE IN THE LIST AND CANNOT BE DELETED. MDT
                    ships Everything, All Drivers and Nothing and so does this;
                    they resolve by name with no document behind them, so a
                    hand-made share with no selection-profiles.yaml still has
                    something the boot image can point at. Rename and Delete go
                    grey on one rather than refusing after the click.
                -->
                <StackPanel Grid.Row="2" Margin="0,10,0,0">
                    <!--
                        THE NAME IS TYPED HERE, NOT IN A SECOND WINDOW. New and
                        Rename both need one, and a modal that asks for a single
                        string is a window an administrator has to dismiss before
                        they can see the tree they are naming.
 
                        THE ID IS DERIVED FROM IT AND SHOWN. workspace.yaml
                        references the id, so an administrator who has to write
                        one into a document by hand needs to be able to read it
                        off the screen - and a derived id nobody could see would
                        be a value that appears in a file from nowhere.
                    -->
                    <TextBlock x:Name="HDTSelectionProfileNameLabel" Margin="0,0,0,4" />
                    <TextBox x:Name="HDTSelectionProfileNameBox" />
                    <TextBlock x:Name="HDTSelectionProfileIdText" Style="{StaticResource HDTHintText}"
                               Margin="0,4,0,0" />
 
                    <StackPanel Orientation="Horizontal" Margin="0,10,0,0">
                        <Button x:Name="HDTSelectionProfileNewButton" MinWidth="76" />
                        <Button x:Name="HDTSelectionProfileRenameButton" MinWidth="76" />
                        <Button x:Name="HDTSelectionProfileDeleteButton" MinWidth="76" Margin="0" />
                    </StackPanel>
                </StackPanel>
            </Grid>
 
            <!-- ================= what the profile includes ================= -->
            <Grid Grid.Column="2">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="*" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
 
                <TextBlock Grid.Row="0" x:Name="HDTSelectionProfileIncludeLabel" Margin="0,0,0,6"
                           Foreground="{DynamicResource HDTLabelBrush}" FontWeight="SemiBold" />
 
                <TextBlock Grid.Row="1" x:Name="HDTSelectionProfileIncludeHint"
                           Style="{StaticResource HDTHintText}" Margin="0,0,0,8" MaxWidth="700"
                           HorizontalAlignment="Left" />
 
                <Border Grid.Row="2" Background="{DynamicResource HDTPanelBrush}"
                        BorderBrush="{DynamicResource HDTBorderBrush}" BorderThickness="1">
                    <TreeView x:Name="HDTSelectionProfileTree" BorderThickness="0" Padding="8"
                              Background="Transparent">
                        <!--
                            THE BRANCH THAT LEADS TO A TICK OPENS ITSELF, which
                            is what IsExpanded on the row is for. A window that
                            came up with everything shut would hide the ticks
                            that are the reason it was opened.
                        -->
                        <TreeView.ItemContainerStyle>
                            <Style TargetType="TreeViewItem">
                                <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
                            </Style>
                        </TreeView.ItemContainerStyle>
 
                        <TreeView.ItemTemplate>
                            <HierarchicalDataTemplate ItemsSource="{Binding Children}">
                                <StackPanel Orientation="Horizontal" Margin="0,2,0,2">
                                    <!--
                                        IsThreeState, AND THE THIRD STATE IS THE
                                        POINT. Drivers ticked is the whole store;
                                        Drivers SQUARE with two vendor packs
                                        below it is a hundred .inf files. A
                                        two-state box cannot tell those apart
                                        without opening every branch.
                                    -->
                                    <!--
                                        IsThreeState is FALSE and the square
                                        still appears. A null IsChecked draws
                                        the square whatever this says; what
                                        IsThreeState="True" adds is the USER
                                        cycling into it - ticked, square,
                                        clear - and "some of Drivers" is not
                                        something anybody can mean by clicking.
                                        It is computed, from what is ticked
                                        below.
                                    -->
                                    <CheckBox IsThreeState="False"
                                              IsChecked="{Binding State, Mode=TwoWay}"
                                              VerticalAlignment="Center" />
 
                                    <TextBlock Text="{Binding Name}" Margin="6,0,0,0"
                                               VerticalAlignment="Center" />
 
                                    <TextBlock Text="{Binding Detail}" Margin="12,0,0,0" FontSize="11"
                                               VerticalAlignment="Center"
                                               Foreground="{DynamicResource HDTHintBrush}" />
                                </StackPanel>
                            </HierarchicalDataTemplate>
                        </TreeView.ItemTemplate>
                    </TreeView>
                </Border>
 
                <TextBlock Grid.Row="3" x:Name="HDTSelectionProfileSummaryText"
                           Style="{StaticResource HDTHintText}" Margin="0,8,0,0" MaxWidth="700"
                           HorizontalAlignment="Left" />
            </Grid>
        </Grid>
 
        <Grid Grid.Row="2" Margin="24,16,24,20">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
 
            <Border Grid.Row="0" Background="{DynamicResource HDTCommandBrush}"
                    BorderBrush="{DynamicResource HDTBorderBrush}" BorderThickness="1"
                    Padding="10,7,10,7">
                <!--
                    AcceptsReturn, ON A BOX NOBODY TYPES INTO. One press of Save
                    is two invocations - the splice and the write - and a TextBox
                    without this shows the first and silently eats the second.
                -->
                <TextBox x:Name="HDTSelectionProfileCommandText"
                         Text=""
                         IsReadOnly="True" BorderThickness="0"
                         AcceptsReturn="True" MaxHeight="76"
                         VerticalScrollBarVisibility="Auto"
                         Background="Transparent"
                         Foreground="{DynamicResource HDTCommandTextBrush}"
                         FontFamily="Consolas, Courier New" FontSize="12"
                         TextWrapping="Wrap" />
            </Border>
 
            <Grid Grid.Row="1" Margin="0,14,0,0">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>
 
                <StackPanel Grid.Column="1" Orientation="Horizontal">
                    <Button x:Name="HDTSelectionProfileSaveButton" MinWidth="96" />
                    <Button x:Name="HDTSelectionProfileCloseButton" MinWidth="96" Margin="0" />
                </StackPanel>
            </Grid>
        </Grid>
    </Grid>
</Window>