UI/Console/HDTApplicationDetection.xaml

<!--
    HOW AN APPLICATION IS DETECTED, as a type and the boxes that type takes.
 
    A RULE IS FOUR SHAPES, NOT ONE. msiProduct wants a product code; registry
    wants a key and optionally a value and its data; file wants a path and
    optionally a version; script wants a path. Typing that as YAML means knowing
    which keys the type takes and the indentation between them, and getting
    either wrong is a document the validator refuses after the fact.
 
    SO THE TYPE IS CHOSEN AND THE BOXES FOLLOW. Get-HDTConsoleDetectionForm says
    which boxes, what is in them, and whether they hold a rule that can be
    written; this window shows them and calls one cmdlet on Save.
 
    THE BOXES ARE BUILT AT RUNTIME, which is why there is a StackPanel here and
    not four named rows: the number of boxes and their labels change with the
    dropdown, and markup for the union of all four types would be markup where
    most of it is collapsed most of the time.
 
    NO RULE IS THE FIRST CHOICE, not a missing one. DESIGN 8 says an application
    that declares no detection installs every time - a decision somebody makes
    for a package with no way to be detected, and choosing it here is what
    clears the key.
 
    NO x:Class AND NO CODE-BEHIND, as every other window here. Handlers are
    attached in PowerShell, by name.
 
    NAMED CONTROLS ARE THE CONTRACT with New-HDTConsoleHost:
    HDTDetectionTitleText, HDTDetectionRootText, HDTDetectionTypeLabel,
    HDTDetectionTypeBox, HDTDetectionFieldPanel, HDTDetectionMessageText,
    HDTDetectionCommandText, HDTDetectionSaveButton and HDTCancelButton.
-->
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Detection"
        Width="620" Height="480"
        WindowStartupLocation="CenterOwner"
        ResizeMode="NoResize"
        ShowInTaskbar="False"
        Background="{DynamicResource HDTWindowBrush}"
        FontFamily="Segoe UI" FontSize="12">
 
    <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="HDTHintTextBrush" Color="#FF6B6B6B" />
        <SolidColorBrush x:Key="HDTErrorBrush" Color="#FFA31515" />
        <SolidColorBrush x:Key="HDTCommandTextBrush" Color="#FF0A3069" />
        <SolidColorBrush x:Key="HDTFooterBrush" Color="#FFE8E8E8" />
        <SolidColorBrush x:Key="HDTButtonBrush" Color="#FF0E639C" />
        <SolidColorBrush x:Key="HDTButtonTextBrush" Color="#FFFFFFFF" />
 
        <Style TargetType="TextBlock" x:Key="HDTFieldLabel">
            <Setter Property="Foreground" Value="{DynamicResource HDTPanelTextBrush}" />
            <Setter Property="FontSize" Value="12" />
            <Setter Property="VerticalAlignment" Value="Center" />
            <Setter Property="Margin" Value="0,0,10,10" />
        </Style>
 
        <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="Padding" Value="6,5,6,5" />
            <Setter Property="Margin" Value="0,0,0,10" />
            <Setter Property="VerticalContentAlignment" 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="Padding" Value="14,6,14,6" />
        </Style>
 
        <!-- THE ? THIS TOOLKIT'S PAGES USE. A Border rather than a bare glyph,
             because WPF raises a tooltip only over what is painted. -->
        <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>
 
        <!-- A DROPDOWN THAT DOES NOT LOOK READ-ONLY.
             WPF's default ComboBox template paints its own grey chrome and
             IGNORES Background, so a combo sitting beside white editable boxes
             and grey read-only ones reads as one of the grey ones - which is
             how the Log level dropdown came to look disabled while it was not.
 
             IsEditable puts a real text box in the closed control, which takes
             the Background above; IsReadOnly keeps it from being typed into, so
             it still behaves exactly like a dropdown - and the value can now be
             selected and copied, which the old one refused.
 
             NO ComboBox HERE USES AN ItemTemplate, so what the text box shows is
             what the closed box showed before: DisplayMemberPath where one is
             declared, ToString() otherwise. -->
        <Style TargetType="ComboBox">
            <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="Padding" Value="6,4,6,4" />
        </Style>
    </Window.Resources>
 
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
 
        <Border Grid.Row="0" Background="{DynamicResource HDTBannerBrush}" Padding="16,12,16,12">
            <StackPanel>
                <TextBlock x:Name="HDTDetectionTitleText"
                           Foreground="{DynamicResource HDTBannerTextBrush}"
                           FontSize="18" FontWeight="SemiBold" />
                <TextBlock x:Name="HDTDetectionRootText"
                           Foreground="{DynamicResource HDTBannerLabelBrush}"
                           FontFamily="Consolas, Courier New" FontSize="11"
                           Margin="0,3,0,0" TextTrimming="CharacterEllipsis" />
            </StackPanel>
        </Border>
 
        <Grid Grid.Row="1" Margin="16,14,16,0">
            <!-- 150, NOT 120: 'Value data (optional)' is the longest label a
                 type asks for, and 120 clipped it to 'Value name (optiona'. The
                 rows the host builds below use the same width. -->
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="150" />
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="30" />
            </Grid.ColumnDefinitions>
 
            <TextBlock Grid.Column="0" x:Name="HDTDetectionTypeLabel"
                       Style="{StaticResource HDTFieldLabel}" />
            <ComboBox Grid.Column="1" x:Name="HDTDetectionTypeBox"
                      DisplayMemberPath="Display" SelectedValuePath="Type"
                      Margin="0,0,0,10" />
        </Grid>
 
        <!-- ONE ROW PER KEY THE TYPE TAKES, built when the type is chosen. -->
        <ScrollViewer Grid.Row="2" Margin="16,4,16,0" VerticalScrollBarVisibility="Auto">
            <StackPanel x:Name="HDTDetectionFieldPanel" />
        </ScrollViewer>
 
        <Border Grid.Row="3" Margin="16,0,16,0" Padding="0,8,0,8">
            <StackPanel>
                <TextBlock x:Name="HDTDetectionMessageText"
                           Foreground="{DynamicResource HDTErrorBrush}"
                           TextWrapping="Wrap" Margin="0,0,0,6" />
                <TextBlock x:Name="HDTDetectionCommandText"
                           Foreground="{DynamicResource HDTCommandTextBrush}"
                           FontFamily="Consolas, Courier New" FontSize="11"
                           TextWrapping="Wrap" />
            </StackPanel>
        </Border>
 
        <Border Grid.Row="4" Background="{DynamicResource HDTFooterBrush}" Padding="16,12,16,12">
            <StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
                <Button x:Name="HDTDetectionSaveButton" MinWidth="96" IsDefault="True" />
                <Button x:Name="HDTCancelButton" MinWidth="96" Margin="8,0,0,0" IsCancel="True" />
            </StackPanel>
        </Border>
    </Grid>
</Window>