Add nullable colors and improve Profile.Icon in settings UI (#17870)

## Summary of the Pull Request
Adds some pre-existing settings ($profile.foreground,
$profile.background, $profile.selectionBackground, $profile.cursorColor)
to the settings UI. This was accomplished by introducing a new control:
NullableColorPicker. This control allows the user to pick a color from
the color scheme, set the color to null, and select a color from an
advanced color picker.

Improves the UI for the Profile.Icon setting by adding an "Icon Type"
combo box. This allows the user to pick from multiple options:
- None: sets the icon to "none" which is interpreted as no icon
- Built-in Icon: presents a combo box that enumerates the Segoe MDL 2
assets
- Emoji: presents a text box with a hint to open the emoji picker
- File: presents a text box to input the path of the image to use

Additionally, the rendered icon is displayed in the setting container.
If "none", "none" is presented to the user (localized).

## References and Relevant Issues
#10000

## Detailed Description of the Pull Request / Additional comments
- NullableColorPicker control
- includes a built-in NullColorButton to set the current value to null
- includes a "More colors..." button to display an advanced color picker
- uses data templates on data templates (data templates squared?) to
convert the current color scheme into a grid of color chips
- color chips display a checkmark (similar to Windows settings
personalization). This automatically updates its color to stay compliant
with color contrast.
- color chips are added to a list so we can (un)check them when a new
color is selected
- SettingsContainer changes
- Forked `ExpanderSettingContainerStyle` to allow for a custom preview
template. This way, we can display the current value in the expander and
we're not just limited to text.
- changed type of `CurrentValue` property from `String` to
`IInspectable`
- added `CurrentValueTemplate` property to control how to display the
current value
- Miscellaneous:
- Added a few converters (`BooleanToVisibility`, `ColorToString`,
`ColorToBrush`)
- Added `NameWithHexCode` to `ColorTableEntry` to expose a color as `Red
#RRGGBB` (used for tooltips and a11y)
- Added `ForegroundPreview` (and equivalent for other colors) to
AppearanceViewModel to deduce the color that will be used

## Validation Steps Performed
- [X] a11y pass (NVDA, keyboard)
- [X] set the color to one of the color chips
- [X] set the color to null
- [X] set the color to a value from the integrated color picker
- [X] control updates properly when a new color scheme is selected
- [X] control updates properly when a color scheme has multiple colors
of the same value

## Follow-ups
- [A11y] Screen readers don't read expander's preview text
- Add Tab Color to settings UI
- Update CursorColor preview to display #FFFFFF as "invert"
- Use Leonard's font picker UI, with the Segoe icon picker, so that you
can filter the list
This commit is contained in:
Carlos Zamora
2024-12-12 12:30:54 -08:00
committed by GitHub
parent bfab5fde4d
commit 5132f9c553
34 changed files with 3068 additions and 215 deletions

View File

@@ -99,6 +99,7 @@ Resources/(?!en)
^NOTICE.md ^NOTICE.md
^oss/ ^oss/
^samples/PixelShaders/Screenshots/ ^samples/PixelShaders/Screenshots/
^src/cascadia/TerminalSettingsEditor/SegoeFluentIconList.h$
^src/interactivity/onecore/BgfxEngine\. ^src/interactivity/onecore/BgfxEngine\.
^src/renderer/atlas/ ^src/renderer/atlas/
^src/renderer/wddmcon/WddmConRenderer\. ^src/renderer/wddmcon/WddmConRenderer\.

View File

@@ -221,6 +221,30 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
// box, prevent it from ever being changed again. // box, prevent it from ever being changed again.
_NotifyChanges(L"UseDesktopBGImage", L"BackgroundImageSettingsVisible"); _NotifyChanges(L"UseDesktopBGImage", L"BackgroundImageSettingsVisible");
} }
else if (viewModelProperty == L"Foreground")
{
_NotifyChanges(L"ForegroundPreview");
}
else if (viewModelProperty == L"Background")
{
_NotifyChanges(L"BackgroundPreview");
}
else if (viewModelProperty == L"SelectionBackground")
{
_NotifyChanges(L"SelectionBackgroundPreview");
}
else if (viewModelProperty == L"CursorColor")
{
_NotifyChanges(L"CursorColorPreview");
}
else if (viewModelProperty == L"DarkColorSchemeName" || viewModelProperty == L"LightColorSchemeName")
{
_NotifyChanges(L"CurrentColorScheme");
}
else if (viewModelProperty == L"CurrentColorScheme")
{
_NotifyChanges(L"ForegroundPreview", L"BackgroundPreview", L"SelectionBackgroundPreview", L"CursorColorPreview");
}
}); });
// Cache the original BG image path. If the user clicks "Use desktop // Cache the original BG image path. If the user clicks "Use desktop
@@ -928,7 +952,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
_NotifyChanges(L"CurrentColorScheme"); _NotifyChanges(L"CurrentColorScheme");
} }
Editor::ColorSchemeViewModel AppearanceViewModel::CurrentColorScheme() Editor::ColorSchemeViewModel AppearanceViewModel::CurrentColorScheme() const
{ {
const auto schemeName{ DarkColorSchemeName() }; const auto schemeName{ DarkColorSchemeName() };
const auto allSchemes{ SchemesList() }; const auto allSchemes{ SchemesList() };
@@ -950,6 +974,42 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
LightColorSchemeName(val.Name()); LightColorSchemeName(val.Name());
} }
static inline Windows::UI::Color _getColorPreview(const IReference<Microsoft::Terminal::Core::Color>& modelVal, Windows::UI::Color deducedVal)
{
if (modelVal)
{
// user defined an override value
return Windows::UI::Color{
.A = 255,
.R = modelVal.Value().R,
.G = modelVal.Value().G,
.B = modelVal.Value().B
};
}
// set to null --> deduce value from color scheme
return deducedVal;
}
Windows::UI::Color AppearanceViewModel::ForegroundPreview() const
{
return _getColorPreview(_appearance.Foreground(), CurrentColorScheme().ForegroundColor().Color());
}
Windows::UI::Color AppearanceViewModel::BackgroundPreview() const
{
return _getColorPreview(_appearance.Background(), CurrentColorScheme().BackgroundColor().Color());
}
Windows::UI::Color AppearanceViewModel::SelectionBackgroundPreview() const
{
return _getColorPreview(_appearance.SelectionBackground(), CurrentColorScheme().SelectionBackgroundColor().Color());
}
Windows::UI::Color AppearanceViewModel::CursorColorPreview() const
{
return _getColorPreview(_appearance.CursorColor(), CurrentColorScheme().CursorColor().Color());
}
DependencyProperty Appearances::_AppearanceProperty{ nullptr }; DependencyProperty Appearances::_AppearanceProperty{ nullptr };
Appearances::Appearances() Appearances::Appearances()

View File

@@ -127,9 +127,14 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void SetBackgroundImagePath(winrt::hstring path); void SetBackgroundImagePath(winrt::hstring path);
void ClearColorScheme(); void ClearColorScheme();
Editor::ColorSchemeViewModel CurrentColorScheme(); Editor::ColorSchemeViewModel CurrentColorScheme() const;
void CurrentColorScheme(const Editor::ColorSchemeViewModel& val); void CurrentColorScheme(const Editor::ColorSchemeViewModel& val);
Windows::UI::Color ForegroundPreview() const;
Windows::UI::Color BackgroundPreview() const;
Windows::UI::Color SelectionBackgroundPreview() const;
Windows::UI::Color CursorColorPreview() const;
WINRT_PROPERTY(bool, IsDefault, false); WINRT_PROPERTY(bool, IsDefault, false);
// These settings are not defined in AppearanceConfig, so we grab them // These settings are not defined in AppearanceConfig, so we grab them
@@ -153,6 +158,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
OBSERVABLE_PROJECTED_SETTING(_appearance, BackgroundImageAlignment); OBSERVABLE_PROJECTED_SETTING(_appearance, BackgroundImageAlignment);
OBSERVABLE_PROJECTED_SETTING(_appearance, IntenseTextStyle); OBSERVABLE_PROJECTED_SETTING(_appearance, IntenseTextStyle);
OBSERVABLE_PROJECTED_SETTING(_appearance, AdjustIndistinguishableColors); OBSERVABLE_PROJECTED_SETTING(_appearance, AdjustIndistinguishableColors);
OBSERVABLE_PROJECTED_SETTING(_appearance, Foreground);
OBSERVABLE_PROJECTED_SETTING(_appearance, Background);
OBSERVABLE_PROJECTED_SETTING(_appearance, SelectionBackground);
OBSERVABLE_PROJECTED_SETTING(_appearance, CursorColor);
WINRT_OBSERVABLE_PROPERTY(Windows::Foundation::Collections::IObservableVector<Editor::ColorSchemeViewModel>, SchemesList, _propertyChangedHandlers, nullptr); WINRT_OBSERVABLE_PROPERTY(Windows::Foundation::Collections::IObservableVector<Editor::ColorSchemeViewModel>, SchemesList, _propertyChangedHandlers, nullptr);
private: private:

View File

@@ -45,6 +45,11 @@ namespace Microsoft.Terminal.Settings.Editor
ColorSchemeViewModel CurrentColorScheme; ColorSchemeViewModel CurrentColorScheme;
IObservableVector<ColorSchemeViewModel> SchemesList; IObservableVector<ColorSchemeViewModel> SchemesList;
Windows.UI.Color ForegroundPreview { get; };
Windows.UI.Color BackgroundPreview { get; };
Windows.UI.Color SelectionBackgroundPreview { get; };
Windows.UI.Color CursorColorPreview { get; };
String MissingFontFaces { get; }; String MissingFontFaces { get; };
String ProportionalFontFaces { get; }; String ProportionalFontFaces { get; };
Boolean HasPowerlineCharacters { get; }; Boolean HasPowerlineCharacters { get; };
@@ -78,6 +83,11 @@ namespace Microsoft.Terminal.Settings.Editor
OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Microsoft.Terminal.Settings.Model.ConvergedAlignment, BackgroundImageAlignment); OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Microsoft.Terminal.Settings.Model.ConvergedAlignment, BackgroundImageAlignment);
OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Microsoft.Terminal.Settings.Model.IntenseStyle, IntenseTextStyle); OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Microsoft.Terminal.Settings.Model.IntenseStyle, IntenseTextStyle);
OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Microsoft.Terminal.Core.AdjustTextMode, AdjustIndistinguishableColors); OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Microsoft.Terminal.Core.AdjustTextMode, AdjustIndistinguishableColors);
OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, Foreground);
OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, Background);
OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, SelectionBackground);
OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, CursorColor);
} }
[default_interface] runtimeclass Appearances : Windows.UI.Xaml.Controls.UserControl, Windows.UI.Xaml.Data.INotifyPropertyChanged [default_interface] runtimeclass Appearances : Windows.UI.Xaml.Controls.UserControl, Windows.UI.Xaml.Data.INotifyPropertyChanged

View File

@@ -69,138 +69,188 @@
<!-- Grouping: Text --> <!-- Grouping: Text -->
<TextBlock x:Uid="Profile_TextHeader" <TextBlock x:Uid="Profile_TextHeader"
Style="{StaticResource TextBlockSubHeaderStyle}" /> Style="{StaticResource TextBlockSubHeaderStyle}" />
<!-- Color Scheme --> <!-- Color Scheme -->
<!-- This currently only display the Dark color scheme, even if the user has a pair of schemes set. --> <!-- This currently only display the Dark color scheme, even if the user has a pair of schemes set. -->
<local:SettingContainer x:Uid="Profile_ColorScheme" <local:SettingContainer x:Uid="Profile_ColorScheme"
ClearSettingValue="{x:Bind Appearance.ClearColorScheme}" ClearSettingValue="{x:Bind Appearance.ClearColorScheme}"
HasSettingValue="{x:Bind Appearance.HasDarkColorSchemeName, Mode=OneWay}" HasSettingValue="{x:Bind Appearance.HasDarkColorSchemeName, Mode=OneWay}"
SettingOverrideSource="{x:Bind Appearance.DarkColorSchemeNameOverrideSource, Mode=OneWay}"> SettingOverrideSource="{x:Bind Appearance.DarkColorSchemeNameOverrideSource, Mode=OneWay}"
<ComboBox Padding="4" Style="{StaticResource ExpanderSettingContainerStyleWithComplexPreview}">
ItemsSource="{x:Bind Appearance.SchemesList, Mode=OneWay}" <local:SettingContainer.CurrentValue>
SelectedItem="{x:Bind Appearance.CurrentColorScheme, Mode=TwoWay}" <ComboBox Padding="4"
Style="{StaticResource ComboBoxSettingStyle}"> ItemsSource="{x:Bind Appearance.SchemesList, Mode=OneWay}"
<ComboBox.ItemTemplate> SelectedItem="{x:Bind Appearance.CurrentColorScheme, Mode=TwoWay}"
<DataTemplate x:DataType="local:ColorSchemeViewModel"> Style="{StaticResource ComboBoxSettingStyle}">
<Grid Grid.Column="0" <ComboBox.ItemTemplate>
Padding="8" <DataTemplate x:DataType="local:ColorSchemeViewModel">
VerticalAlignment="Center" <Grid Grid.Column="0"
Background="{x:Bind mtu:Converters.ColorToBrush(BackgroundColor.Color), Mode=OneWay}" Padding="8"
ColumnSpacing="1" VerticalAlignment="Center"
CornerRadius="2" Background="{x:Bind mtu:Converters.ColorToBrush(BackgroundColor.Color), Mode=OneWay}"
RowSpacing="1"> ColumnSpacing="1"
<Grid.ColumnDefinitions> CornerRadius="2"
<ColumnDefinition Width="Auto" /> RowSpacing="1">
<ColumnDefinition Width="Auto" /> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" />
<Grid.RowDefinitions> <ColumnDefinition Width="Auto" />
<RowDefinition Height="Auto" /> </Grid.ColumnDefinitions>
<RowDefinition Height="Auto" /> <Grid.RowDefinitions>
</Grid.RowDefinitions> <RowDefinition Height="Auto" />
<ContentControl Grid.Row="0" <RowDefinition Height="Auto" />
Grid.Column="0" </Grid.RowDefinitions>
Content="{x:Bind ColorEntryAt(0), Mode=OneWay}" <ContentControl Grid.Row="0"
ContentTemplate="{StaticResource ColorChipTemplate}" Grid.Column="0"
IsTabStop="False" /> Content="{x:Bind ColorEntryAt(0), Mode=OneWay}"
<ContentControl Grid.Row="0" ContentTemplate="{StaticResource ColorChipTemplate}"
Grid.Column="1" IsTabStop="False" />
Content="{x:Bind ColorEntryAt(1), Mode=OneWay}" <ContentControl Grid.Row="0"
ContentTemplate="{StaticResource ColorChipTemplate}" Grid.Column="1"
IsTabStop="False" /> Content="{x:Bind ColorEntryAt(1), Mode=OneWay}"
<ContentControl Grid.Row="0" ContentTemplate="{StaticResource ColorChipTemplate}"
Grid.Column="2" IsTabStop="False" />
Content="{x:Bind ColorEntryAt(2), Mode=OneWay}" <ContentControl Grid.Row="0"
ContentTemplate="{StaticResource ColorChipTemplate}" Grid.Column="2"
IsTabStop="False" /> Content="{x:Bind ColorEntryAt(2), Mode=OneWay}"
<ContentControl Grid.Row="0" ContentTemplate="{StaticResource ColorChipTemplate}"
Grid.Column="3" IsTabStop="False" />
Content="{x:Bind ColorEntryAt(3), Mode=OneWay}" <ContentControl Grid.Row="0"
ContentTemplate="{StaticResource ColorChipTemplate}" Grid.Column="3"
IsTabStop="False" /> Content="{x:Bind ColorEntryAt(3), Mode=OneWay}"
<ContentControl Grid.Row="0" ContentTemplate="{StaticResource ColorChipTemplate}"
Grid.Column="4" IsTabStop="False" />
Content="{x:Bind ColorEntryAt(4), Mode=OneWay}" <ContentControl Grid.Row="0"
ContentTemplate="{StaticResource ColorChipTemplate}" Grid.Column="4"
IsTabStop="False" /> Content="{x:Bind ColorEntryAt(4), Mode=OneWay}"
<ContentControl Grid.Row="0" ContentTemplate="{StaticResource ColorChipTemplate}"
Grid.Column="5" IsTabStop="False" />
Content="{x:Bind ColorEntryAt(5), Mode=OneWay}" <ContentControl Grid.Row="0"
ContentTemplate="{StaticResource ColorChipTemplate}" Grid.Column="5"
IsTabStop="False" /> Content="{x:Bind ColorEntryAt(5), Mode=OneWay}"
<ContentControl Grid.Row="0" ContentTemplate="{StaticResource ColorChipTemplate}"
Grid.Column="6" IsTabStop="False" />
Content="{x:Bind ColorEntryAt(6), Mode=OneWay}" <ContentControl Grid.Row="0"
ContentTemplate="{StaticResource ColorChipTemplate}" Grid.Column="6"
IsTabStop="False" /> Content="{x:Bind ColorEntryAt(6), Mode=OneWay}"
<ContentControl Grid.Row="0" ContentTemplate="{StaticResource ColorChipTemplate}"
Grid.Column="7" IsTabStop="False" />
Content="{x:Bind ColorEntryAt(7), Mode=OneWay}" <ContentControl Grid.Row="0"
ContentTemplate="{StaticResource ColorChipTemplate}" Grid.Column="7"
IsTabStop="False" /> Content="{x:Bind ColorEntryAt(7), Mode=OneWay}"
<ContentControl Grid.Row="1" ContentTemplate="{StaticResource ColorChipTemplate}"
Grid.Column="0" IsTabStop="False" />
Content="{x:Bind ColorEntryAt(8), Mode=OneWay}" <ContentControl Grid.Row="1"
ContentTemplate="{StaticResource ColorChipTemplate}" Grid.Column="0"
IsTabStop="False" /> Content="{x:Bind ColorEntryAt(8), Mode=OneWay}"
<ContentControl Grid.Row="1" ContentTemplate="{StaticResource ColorChipTemplate}"
Grid.Column="1" IsTabStop="False" />
Content="{x:Bind ColorEntryAt(9), Mode=OneWay}" <ContentControl Grid.Row="1"
ContentTemplate="{StaticResource ColorChipTemplate}" Grid.Column="1"
IsTabStop="False" /> Content="{x:Bind ColorEntryAt(9), Mode=OneWay}"
<ContentControl Grid.Row="1" ContentTemplate="{StaticResource ColorChipTemplate}"
Grid.Column="2" IsTabStop="False" />
Content="{x:Bind ColorEntryAt(10), Mode=OneWay}" <ContentControl Grid.Row="1"
ContentTemplate="{StaticResource ColorChipTemplate}" Grid.Column="2"
IsTabStop="False" /> Content="{x:Bind ColorEntryAt(10), Mode=OneWay}"
<ContentControl Grid.Row="1" ContentTemplate="{StaticResource ColorChipTemplate}"
Grid.Column="3" IsTabStop="False" />
Content="{x:Bind ColorEntryAt(11), Mode=OneWay}" <ContentControl Grid.Row="1"
ContentTemplate="{StaticResource ColorChipTemplate}" Grid.Column="3"
IsTabStop="False" /> Content="{x:Bind ColorEntryAt(11), Mode=OneWay}"
<ContentControl Grid.Row="1" ContentTemplate="{StaticResource ColorChipTemplate}"
Grid.Column="4" IsTabStop="False" />
Content="{x:Bind ColorEntryAt(12), Mode=OneWay}" <ContentControl Grid.Row="1"
ContentTemplate="{StaticResource ColorChipTemplate}" Grid.Column="4"
IsTabStop="False" /> Content="{x:Bind ColorEntryAt(12), Mode=OneWay}"
<ContentControl Grid.Row="1" ContentTemplate="{StaticResource ColorChipTemplate}"
Grid.Column="5" IsTabStop="False" />
Content="{x:Bind ColorEntryAt(13), Mode=OneWay}" <ContentControl Grid.Row="1"
ContentTemplate="{StaticResource ColorChipTemplate}" Grid.Column="5"
IsTabStop="False" /> Content="{x:Bind ColorEntryAt(13), Mode=OneWay}"
<ContentControl Grid.Row="1" ContentTemplate="{StaticResource ColorChipTemplate}"
Grid.Column="6" IsTabStop="False" />
Content="{x:Bind ColorEntryAt(14), Mode=OneWay}" <ContentControl Grid.Row="1"
ContentTemplate="{StaticResource ColorChipTemplate}" Grid.Column="6"
IsTabStop="False" /> Content="{x:Bind ColorEntryAt(14), Mode=OneWay}"
<ContentControl Grid.Row="1" ContentTemplate="{StaticResource ColorChipTemplate}"
Grid.Column="7" IsTabStop="False" />
Content="{x:Bind ColorEntryAt(15), Mode=OneWay}" <ContentControl Grid.Row="1"
ContentTemplate="{StaticResource ColorChipTemplate}" Grid.Column="7"
IsTabStop="False" /> Content="{x:Bind ColorEntryAt(15), Mode=OneWay}"
<TextBlock Grid.RowSpan="2" ContentTemplate="{StaticResource ColorChipTemplate}"
Grid.Column="8" IsTabStop="False" />
MaxWidth="192" <TextBlock Grid.RowSpan="2"
Margin="4,0,4,0" Grid.Column="8"
HorizontalAlignment="Center" MaxWidth="192"
VerticalAlignment="Center" Margin="4,0,4,0"
AutomationProperties.AccessibilityView="Raw" HorizontalAlignment="Center"
FontFamily="Cascadia Code" VerticalAlignment="Center"
Foreground="{x:Bind mtu:Converters.ColorToBrush(ForegroundColor.Color), Mode=OneWay}" AutomationProperties.AccessibilityView="Raw"
Text="{x:Bind Name, Mode=OneWay}" FontFamily="Cascadia Code"
TextTrimming="WordEllipsis" /> Foreground="{x:Bind mtu:Converters.ColorToBrush(ForegroundColor.Color), Mode=OneWay}"
</Grid> Text="{x:Bind Name, Mode=OneWay}"
</DataTemplate> TextTrimming="WordEllipsis" />
</ComboBox.ItemTemplate> </Grid>
</ComboBox> </DataTemplate>
</local:SettingContainer> </ComboBox.ItemTemplate>
</ComboBox>
</local:SettingContainer.CurrentValue>
<local:SettingContainer.Content>
<StackPanel>
<!-- Foreground Color -->
<local:SettingContainer x:Name="Foreground"
x:Uid="Profile_Foreground"
ClearSettingValue="{x:Bind Appearance.ClearForeground}"
CurrentValue="{x:Bind Appearance.ForegroundPreview, Mode=OneWay}"
CurrentValueTemplate="{StaticResource ColorPreviewTemplate}"
HasSettingValue="{x:Bind Appearance.HasForeground, Mode=OneWay}"
SettingOverrideSource="{x:Bind Appearance.ForegroundOverrideSource, Mode=OneWay}"
Style="{StaticResource ExpanderSettingContainerStyleWithComplexPreview}">
<local:NullableColorPicker x:Uid="Profile_Foreground_NullableColorPicker"
ColorSchemeVM="{x:Bind Appearance.CurrentColorScheme, Mode=OneWay}"
CurrentColor="{x:Bind Appearance.Foreground, Mode=TwoWay}"
NullColorPreview="{x:Bind Appearance.CurrentColorScheme.ForegroundColor.Color, Mode=OneWay}" />
</local:SettingContainer>
<!-- Background Color -->
<local:SettingContainer x:Name="Background"
x:Uid="Profile_Background"
ClearSettingValue="{x:Bind Appearance.ClearBackground}"
CurrentValue="{x:Bind Appearance.BackgroundPreview, Mode=OneWay}"
CurrentValueTemplate="{StaticResource ColorPreviewTemplate}"
HasSettingValue="{x:Bind Appearance.HasBackground, Mode=OneWay}"
SettingOverrideSource="{x:Bind Appearance.BackgroundOverrideSource, Mode=OneWay}"
Style="{StaticResource ExpanderSettingContainerStyleWithComplexPreview}">
<local:NullableColorPicker x:Uid="Profile_Background_NullableColorPicker"
ColorSchemeVM="{x:Bind Appearance.CurrentColorScheme, Mode=OneWay}"
CurrentColor="{x:Bind Appearance.Background, Mode=TwoWay}"
NullColorPreview="{x:Bind Appearance.CurrentColorScheme.BackgroundColor.Color, Mode=OneWay}" />
</local:SettingContainer>
<!-- Selection Background Color -->
<local:SettingContainer x:Name="SelectionBackground"
x:Uid="Profile_SelectionBackground"
ClearSettingValue="{x:Bind Appearance.ClearSelectionBackground}"
CurrentValue="{x:Bind Appearance.SelectionBackgroundPreview, Mode=OneWay}"
CurrentValueTemplate="{StaticResource ColorPreviewTemplate}"
HasSettingValue="{x:Bind Appearance.HasSelectionBackground, Mode=OneWay}"
SettingOverrideSource="{x:Bind Appearance.SelectionBackgroundOverrideSource, Mode=OneWay}"
Style="{StaticResource ExpanderSettingContainerStyleWithComplexPreview}">
<local:NullableColorPicker x:Uid="Profile_SelectionBackground_NullableColorPicker"
ColorSchemeVM="{x:Bind Appearance.CurrentColorScheme, Mode=OneWay}"
CurrentColor="{x:Bind Appearance.SelectionBackground, Mode=TwoWay}"
NullColorPreview="{x:Bind Appearance.CurrentColorScheme.SelectionBackgroundColor.Color, Mode=OneWay}" />
</local:SettingContainer>
</StackPanel>
</local:SettingContainer.Content>
</local:SettingContainer>
<!-- Font Face --> <!-- Font Face -->
<local:SettingContainer x:Name="FontFaceContainer" <local:SettingContainer x:Name="FontFaceContainer"
x:Uid="Profile_FontFace" x:Uid="Profile_FontFace"
@@ -452,6 +502,21 @@
Text="{Binding ElementName=CursorHeightSlider, Path=Value, Mode=OneWay}" /> Text="{Binding ElementName=CursorHeightSlider, Path=Value, Mode=OneWay}" />
</Grid> </Grid>
</local:SettingContainer> </local:SettingContainer>
<!-- Cursor Color -->
<local:SettingContainer x:Name="CursorColor"
x:Uid="Profile_CursorColor"
ClearSettingValue="{x:Bind Appearance.ClearCursorColor}"
CurrentValue="{x:Bind Appearance.CursorColorPreview, Mode=OneWay}"
CurrentValueTemplate="{StaticResource ColorPreviewTemplate}"
HasSettingValue="{x:Bind Appearance.HasCursorColor, Mode=OneWay}"
SettingOverrideSource="{x:Bind Appearance.CursorColorOverrideSource, Mode=OneWay}"
Style="{StaticResource ExpanderSettingContainerStyleWithComplexPreview}">
<local:NullableColorPicker x:Uid="Profile_CursorColor_NullableColorPicker"
ColorSchemeVM="{x:Bind Appearance.CurrentColorScheme, Mode=OneWay}"
CurrentColor="{x:Bind Appearance.CursorColor, Mode=TwoWay}"
NullColorPreview="{x:Bind Appearance.CurrentColorScheme.CursorColor.Color, Mode=OneWay}" />
</local:SettingContainer>
</StackPanel> </StackPanel>
<!-- Grouping: Background --> <!-- Grouping: Background -->

View File

@@ -69,6 +69,11 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
return hstring{ fmt::format(FMT_COMPILE(L"{} RGB({}, {}, {})"), _Name, _Color.R, _Color.G, _Color.B) }; return hstring{ fmt::format(FMT_COMPILE(L"{} RGB({}, {}, {})"), _Name, _Color.R, _Color.G, _Color.B) };
} }
hstring NameWithHexCode() const
{
return hstring{ fmt::format(FMT_COMPILE(L"{} #{:02X}{:02X}{:02X}"), _Name, _Color.R, _Color.G, _Color.B) };
}
til::property_changed_event PropertyChanged; til::property_changed_event PropertyChanged;
WINRT_OBSERVABLE_PROPERTY(Windows::UI::Color, Color, PropertyChanged.raise); WINRT_OBSERVABLE_PROPERTY(Windows::UI::Color, Color, PropertyChanged.raise);
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, Name, PropertyChanged.raise); WINRT_OBSERVABLE_PROPERTY(winrt::hstring, Name, PropertyChanged.raise);

View File

@@ -36,5 +36,6 @@ namespace Microsoft.Terminal.Settings.Editor
IInspectable Tag; IInspectable Tag;
Windows.UI.Color Color; Windows.UI.Color Color;
String AccessibleName { get; }; String AccessibleName { get; };
String NameWithHexCode { get; };
} }
} }

View File

@@ -4,6 +4,8 @@
--> -->
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Microsoft.Terminal.Settings.Editor"
xmlns:mtu="using:Microsoft.Terminal.UI"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"> xmlns:muxc="using:Microsoft.UI.Xaml.Controls">
<!-- Merge SettingContainerStyle here to give every page access to the SettingContainer --> <!-- Merge SettingContainerStyle here to give every page access to the SettingContainer -->
@@ -60,6 +62,9 @@
</ResourceDictionary> </ResourceDictionary>
</ResourceDictionary.ThemeDictionaries> </ResourceDictionary.ThemeDictionaries>
<local:ColorToBrushConverter x:Key="ColorToBrushConverter" />
<local:ColorToStringConverter x:Key="ColorToStringConverter" />
<Color x:Key="DeleteButtonColor">Firebrick</Color> <Color x:Key="DeleteButtonColor">Firebrick</Color>
<x:Double x:Key="StandardIconSize">14.0</x:Double> <x:Double x:Key="StandardIconSize">14.0</x:Double>
@@ -69,6 +74,32 @@
<x:Double x:Key="StandardControlMaxWidth">1000</x:Double> <x:Double x:Key="StandardControlMaxWidth">1000</x:Double>
<Thickness x:Key="SettingStackMargin">13,0,13,48</Thickness> <Thickness x:Key="SettingStackMargin">13,0,13,48</Thickness>
<!-- We're purposefully not providing a DataType here.
This is expected to be used with an IReference<Microsoft::Terminal::Core::Color>.
We're doing all the data type handling in the used converters.-->
<DataTemplate x:Key="ColorPreviewTemplate">
<Grid ColumnSpacing="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Rectangle Grid.Column="0"
Width="13"
Height="13"
VerticalAlignment="Center"
Fill="{Binding Converter={StaticResource ColorToBrushConverter}}"
RadiusX="2"
RadiusY="2" />
<TextBlock Grid.Column="1"
Margin="0,0,0,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
FontFamily="Segoe UI, Segoe Fluent Icons, Segoe MDL2 Assets"
Style="{StaticResource SettingsPageItemDescriptionStyle}"
Text="{Binding Converter={StaticResource ColorToStringConverter}}" />
</Grid>
</DataTemplate>
<!-- <!--
This is for styling the entire items control used on the This is for styling the entire items control used on the
color schemes page color schemes page
@@ -399,6 +430,91 @@
</Setter> </Setter>
</Style> </Style>
<Style x:Key="ColorToggleButtonStyle"
TargetType="ToggleButton">
<Setter Property="BackgroundSizing" Value="OuterBorderEdge" />
<Setter Property="BorderBrush" Value="{ThemeResource ToggleButtonBorderThemeBrush}" />
<Setter Property="BorderThickness" Value="{ThemeResource ToggleButtonBorderThemeThickness}" />
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />
<Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}" />
<Setter Property="FocusVisualMargin" Value="-3" />
<Setter Property="Width" Value="32" />
<Setter Property="Height" Value="32" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Grid>
<Border x:Name="ColorButtonBorder"
BorderBrush="{TemplateBinding Background}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<Grid>
<Border x:Name="ColorButtonBackground"
Background="{TemplateBinding Background}"
BorderThickness="0" />
<!-- We have to use Binding here! We're trying to do a template binding with a converter, so we have to use the verbose syntax. -->
<FontIcon Margin="0,0,-1,-1"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
FontFamily="Segoe Fluent Icons"
FontSize="12"
Foreground="{TemplateBinding BorderBrush}"
Glyph="&#xE73D;"
Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsChecked, Mode=OneWay}" />
</Grid>
</Border>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColorButtonBackground"
Storyboard.TargetProperty="Opacity">
<DiscreteObjectKeyFrame KeyTime="0"
Value="0.7" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColorButtonBorder"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{Binding Path=BorderBrush, RelativeSource={RelativeSource TemplatedParent}}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColorButtonBackground"
Storyboard.TargetProperty="Opacity">
<DiscreteObjectKeyFrame KeyTime="0"
Value="0.5" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColorButtonBorder"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{Binding Path=BorderBrush, RelativeSource={RelativeSource TemplatedParent}}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Checked">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColorButtonBorder"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{Binding Path=BorderBrush, RelativeSource={RelativeSource TemplatedParent}}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Slider-Related Styling --> <!-- Slider-Related Styling -->
<Style x:Key="SliderValueLabelStyle" <Style x:Key="SliderValueLabelStyle"
TargetType="TextBlock"> TargetType="TextBlock">

View File

@@ -752,9 +752,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
if (auto menuItem{ weakMenuItem.get() }) if (auto menuItem{ weakMenuItem.get() })
{ {
const auto& tag{ menuItem.Tag().as<Editor::ProfileViewModel>() }; const auto& tag{ menuItem.Tag().as<Editor::ProfileViewModel>() };
if (args.PropertyName() == L"Icon") if (args.PropertyName() == L"Icon" || args.PropertyName() == L"EvaluatedIcon")
{ {
menuItem.Icon(UI::IconPathConverter::IconWUX(tag.Icon())); menuItem.Icon(UI::IconPathConverter::IconWUX(tag.EvaluatedIcon()));
} }
else if (args.PropertyName() == L"Name") else if (args.PropertyName() == L"Name")
{ {

View File

@@ -57,6 +57,10 @@
<DependentUpon>ColorSchemes.xaml</DependentUpon> <DependentUpon>ColorSchemes.xaml</DependentUpon>
<SubType>Code</SubType> <SubType>Code</SubType>
</ClInclude> </ClInclude>
<ClInclude Include="NullableColorPicker.h">
<DependentUpon>NullableColorPicker.xaml</DependentUpon>
<SubType>Code</SubType>
</ClInclude>
<ClInclude Include="EditColorScheme.h"> <ClInclude Include="EditColorScheme.h">
<DependentUpon>EditColorScheme.xaml</DependentUpon> <DependentUpon>EditColorScheme.xaml</DependentUpon>
<SubType>Code</SubType> <SubType>Code</SubType>
@@ -88,6 +92,11 @@
<DependentUpon>ActionsViewModel.idl</DependentUpon> <DependentUpon>ActionsViewModel.idl</DependentUpon>
<SubType>Code</SubType> <SubType>Code</SubType>
</ClInclude> </ClInclude>
<ClInclude Include="SegoeFluentIconList.h" />
<ClInclude Include="TerminalColorConverters.h">
<DependentUpon>TerminalColorConverters.idl</DependentUpon>
<SubType>Code</SubType>
</ClInclude>
<ClInclude Include="ColorSchemeViewModel.h"> <ClInclude Include="ColorSchemeViewModel.h">
<DependentUpon>ColorSchemeViewModel.idl</DependentUpon> <DependentUpon>ColorSchemeViewModel.idl</DependentUpon>
<SubType>Code</SubType> <SubType>Code</SubType>
@@ -166,6 +175,9 @@
<Page Include="ColorSchemes.xaml"> <Page Include="ColorSchemes.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Include="NullableColorPicker.xaml">
<SubType>Designer</SubType>
</Page>
<Page Include="EditColorScheme.xaml"> <Page Include="EditColorScheme.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
@@ -227,6 +239,10 @@
<DependentUpon>ColorSchemes.xaml</DependentUpon> <DependentUpon>ColorSchemes.xaml</DependentUpon>
<SubType>Code</SubType> <SubType>Code</SubType>
</ClCompile> </ClCompile>
<ClCompile Include="NullableColorPicker.cpp">
<DependentUpon>NullableColorPicker.xaml</DependentUpon>
<SubType>Code</SubType>
</ClCompile>
<ClCompile Include="EditColorScheme.cpp"> <ClCompile Include="EditColorScheme.cpp">
<DependentUpon>EditColorScheme.xaml</DependentUpon> <DependentUpon>EditColorScheme.xaml</DependentUpon>
<SubType>Code</SubType> <SubType>Code</SubType>
@@ -261,6 +277,10 @@
<DependentUpon>ActionsViewModel.idl</DependentUpon> <DependentUpon>ActionsViewModel.idl</DependentUpon>
<SubType>Code</SubType> <SubType>Code</SubType>
</ClCompile> </ClCompile>
<ClCompile Include="TerminalColorConverters.cpp">
<DependentUpon>TerminalColorConverters.idl</DependentUpon>
<SubType>Code</SubType>
</ClCompile>
<ClCompile Include="ColorSchemeViewModel.cpp"> <ClCompile Include="ColorSchemeViewModel.cpp">
<DependentUpon>ColorSchemeViewModel.idl</DependentUpon> <DependentUpon>ColorSchemeViewModel.idl</DependentUpon>
<SubType>Code</SubType> <SubType>Code</SubType>
@@ -343,6 +363,10 @@
<DependentUpon>ColorSchemes.xaml</DependentUpon> <DependentUpon>ColorSchemes.xaml</DependentUpon>
<SubType>Code</SubType> <SubType>Code</SubType>
</Midl> </Midl>
<Midl Include="NullableColorPicker.idl">
<DependentUpon>NullableColorPicker.xaml</DependentUpon>
<SubType>Code</SubType>
</Midl>
<Midl Include="EditColorScheme.idl"> <Midl Include="EditColorScheme.idl">
<DependentUpon>EditColorScheme.xaml</DependentUpon> <DependentUpon>EditColorScheme.xaml</DependentUpon>
<SubType>Code</SubType> <SubType>Code</SubType>
@@ -376,6 +400,7 @@
</Midl> </Midl>
<Midl Include="ProfileViewModel.idl" /> <Midl Include="ProfileViewModel.idl" />
<Midl Include="ActionsViewModel.idl" /> <Midl Include="ActionsViewModel.idl" />
<Midl Include="TerminalColorConverters.idl" />
<Midl Include="ColorSchemeViewModel.idl" /> <Midl Include="ColorSchemeViewModel.idl" />
<Midl Include="ColorSchemesPageViewModel.idl" /> <Midl Include="ColorSchemesPageViewModel.idl" />
<Midl Include="RenderingViewModel.idl" /> <Midl Include="RenderingViewModel.idl" />
@@ -439,7 +464,6 @@
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalConnection\TerminalConnection.vcxproj"> <ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalConnection\TerminalConnection.vcxproj">
<Private>false</Private> <Private>false</Private>
</ProjectReference> </ProjectReference>
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalControl\dll\TerminalControl.vcxproj"> <ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalControl\dll\TerminalControl.vcxproj">
<!-- Private:false and ReferenceOutputAssembly:false, in combination with <!-- Private:false and ReferenceOutputAssembly:false, in combination with
the manual reference to TerminalControl.winmd below make sure that this the manual reference to TerminalControl.winmd below make sure that this
@@ -452,7 +476,6 @@
<Private>false</Private> <Private>false</Private>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<!-- Manually add a reference to TerminalControl here. We need this so <!-- Manually add a reference to TerminalControl here. We need this so
MDMERGE will know where the TermControl types are defined. However, we need MDMERGE will know where the TermControl types are defined. However, we need
@@ -471,17 +494,13 @@
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies> <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemDefinitionGroup> <ItemDefinitionGroup>
<Link> <Link>
<AdditionalDependencies>shell32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>shell32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" /> <Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
<!-- This -must- go after cppwinrt.build.post.props because that includes many VS-provided props including appcontainer.common.props, which stomps on what cppwinrt.targets did. --> <!-- This -must- go after cppwinrt.build.post.props because that includes many VS-provided props including appcontainer.common.props, which stomps on what cppwinrt.targets did. -->
<Import Project="$(OpenConsoleDir)src\common.nugetversions.targets" /> <Import Project="$(OpenConsoleDir)src\common.nugetversions.targets" />
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" /> <Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
</Project> </Project>

View File

@@ -2,6 +2,7 @@
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup> <ItemGroup>
<Natvis Include="$(SolutionDir)tools\ConsoleTypes.natvis" /> <Natvis Include="$(SolutionDir)tools\ConsoleTypes.natvis" />
<Natvis Include="$(MSBuildThisFileDirectory)..\..\natvis\wil.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PRIResource Include="Resources\en-US\Resources.resw" /> <PRIResource Include="Resources\en-US\Resources.resw" />
@@ -15,6 +16,7 @@
<ClInclude Include="pch.h" /> <ClInclude Include="pch.h" />
<ClInclude Include="Utils.h" /> <ClInclude Include="Utils.h" />
<ClInclude Include="PreviewConnection.h" /> <ClInclude Include="PreviewConnection.h" />
<ClInclude Include="SegoeFluentIconList.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Midl Include="ProfileViewModel.idl" /> <Midl Include="ProfileViewModel.idl" />
@@ -27,10 +29,10 @@
<Midl Include="LaunchViewModel.idl" /> <Midl Include="LaunchViewModel.idl" />
<Midl Include="EnumEntry.idl" /> <Midl Include="EnumEntry.idl" />
<Midl Include="SettingContainer.idl" /> <Midl Include="SettingContainer.idl" />
<Midl Include="TerminalColorConverters.idl" />
<Midl Include="NewTabMenuViewModel.idl" /> <Midl Include="NewTabMenuViewModel.idl" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="packages.config" />
<None Include="$(ProjectName).def" /> <None Include="$(ProjectName).def" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@@ -50,6 +52,7 @@
<Page Include="SettingContainerStyle.xaml" /> <Page Include="SettingContainerStyle.xaml" />
<Page Include="AddProfile.xaml" /> <Page Include="AddProfile.xaml" />
<Page Include="KeyChordListener.xaml" /> <Page Include="KeyChordListener.xaml" />
<Page Include="NullableColorPicker.xaml" />
<Page Include="NewTabMenu.xaml" /> <Page Include="NewTabMenu.xaml" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -335,7 +335,8 @@
<!-- Add Profile --> <!-- Add Profile -->
<local:SettingContainer x:Uid="NewTabMenu_AddProfile" <local:SettingContainer x:Uid="NewTabMenu_AddProfile"
FontIconGlyph="&#xE756;"> FontIconGlyph="&#xE756;"
Style="{StaticResource SettingContainerWithIcon}">
<StackPanel Orientation="Horizontal" <StackPanel Orientation="Horizontal"
Spacing="5"> Spacing="5">
@@ -383,7 +384,8 @@
<!-- Add Separator --> <!-- Add Separator -->
<local:SettingContainer x:Uid="NewTabMenu_AddSeparator" <local:SettingContainer x:Uid="NewTabMenu_AddSeparator"
FontIconGlyph="&#xE76f;"> FontIconGlyph="&#xE76f;"
Style="{StaticResource SettingContainerWithIcon}">
<Button x:Name="AddSeparatorButton" <Button x:Name="AddSeparatorButton"
x:Uid="NewTabMenu_AddSeparatorButton" x:Uid="NewTabMenu_AddSeparatorButton"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
@@ -398,7 +400,8 @@
<!-- Add Folder --> <!-- Add Folder -->
<local:SettingContainer x:Uid="NewTabMenu_AddFolder" <local:SettingContainer x:Uid="NewTabMenu_AddFolder"
FontIconGlyph="&#xF12B;"> FontIconGlyph="&#xF12B;"
Style="{StaticResource SettingContainerWithIcon}">
<StackPanel Orientation="Horizontal" <StackPanel Orientation="Horizontal"
Spacing="5"> Spacing="5">
<TextBox x:Name="FolderNameTextBox" <TextBox x:Name="FolderNameTextBox"
@@ -424,7 +427,7 @@
<!-- Add Match Profiles --> <!-- Add Match Profiles -->
<local:SettingContainer x:Uid="NewTabMenu_AddMatchProfiles" <local:SettingContainer x:Uid="NewTabMenu_AddMatchProfiles"
FontIconGlyph="&#xE748;" FontIconGlyph="&#xE748;"
Style="{StaticResource ExpanderSettingContainerStyle}"> Style="{StaticResource ExpanderSettingContainerStyleWithIcon}">
<StackPanel Spacing="10"> <StackPanel Spacing="10">
<TextBox x:Uid="NewTabMenu_AddMatchProfiles_Name" <TextBox x:Uid="NewTabMenu_AddMatchProfiles_Name"
Text="{x:Bind ViewModel.ProfileMatcherName, Mode=TwoWay}" /> Text="{x:Bind ViewModel.ProfileMatcherName, Mode=TwoWay}" />
@@ -448,7 +451,8 @@
<!-- Add Remaining Profiles --> <!-- Add Remaining Profiles -->
<local:SettingContainer x:Uid="NewTabMenu_AddRemainingProfiles" <local:SettingContainer x:Uid="NewTabMenu_AddRemainingProfiles"
FontIconGlyph="&#xE902;"> FontIconGlyph="&#xE902;"
Style="{StaticResource SettingContainerWithIcon}">
<Button x:Name="AddRemainingProfilesButton" <Button x:Name="AddRemainingProfilesButton"
x:Uid="NewTabMenu_AddRemainingProfilesButton" x:Uid="NewTabMenu_AddRemainingProfilesButton"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"

View File

@@ -0,0 +1,226 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "NullableColorPicker.h"
#include "NullableColorPicker.g.cpp"
#include <LibraryResources.h>
using namespace winrt;
using namespace winrt::Windows::UI;
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Navigation;
using namespace winrt::Windows::UI::Xaml::Controls;
using namespace winrt::Windows::UI::Xaml::Media;
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::Foundation::Collections;
using namespace winrt::Microsoft::UI::Xaml::Controls;
namespace winrt
{
namespace MUX = Microsoft::UI::Xaml;
namespace WUX = Windows::UI::Xaml;
}
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
static constexpr bool equalsColor(Windows::UI::Color a, Microsoft::Terminal::Core::Color b)
{
return a.R == b.R && a.G == b.G && a.B == b.B;
}
DependencyProperty NullableColorPicker::_ColorSchemeVMProperty{ nullptr };
DependencyProperty NullableColorPicker::_CurrentColorProperty{ nullptr };
DependencyProperty NullableColorPicker::_ShowNullColorButtonProperty{ nullptr };
DependencyProperty NullableColorPicker::_NullColorButtonLabelProperty{ nullptr };
DependencyProperty NullableColorPicker::_NullColorPreviewProperty{ nullptr };
NullableColorPicker::NullableColorPicker()
{
_InitializeProperties();
InitializeComponent();
}
void NullableColorPicker::_InitializeProperties()
{
// Initialize any dependency properties here.
// This performs a lazy load on these properties, instead of
// initializing them when the DLL loads.
if (!_ColorSchemeVMProperty)
{
_ColorSchemeVMProperty =
DependencyProperty::Register(
L"ColorSchemeVM",
xaml_typename<Editor::ColorSchemeViewModel>(),
xaml_typename<Editor::NullableColorPicker>(),
PropertyMetadata{ nullptr });
}
if (!_CurrentColorProperty)
{
_CurrentColorProperty =
DependencyProperty::Register(
L"CurrentColor",
xaml_typename<Windows::Foundation::IReference<Microsoft::Terminal::Core::Color>>(),
xaml_typename<Editor::NullableColorPicker>(),
PropertyMetadata{ nullptr, PropertyChangedCallback{ &NullableColorPicker::_OnCurrentColorValueChanged } });
}
if (!_ShowNullColorButtonProperty)
{
_ShowNullColorButtonProperty =
DependencyProperty::Register(
L"ShowNullColorButton",
xaml_typename<bool>(),
xaml_typename<Editor::NullableColorPicker>(),
PropertyMetadata{ box_value(true) });
}
if (!_NullColorButtonLabelProperty)
{
_NullColorButtonLabelProperty =
DependencyProperty::Register(
L"NullColorButtonLabel",
xaml_typename<hstring>(),
xaml_typename<Editor::NullableColorPicker>(),
PropertyMetadata{ nullptr });
}
if (!_NullColorPreviewProperty)
{
_NullColorPreviewProperty =
DependencyProperty::Register(
L"NullColorPreview",
xaml_typename<Windows::UI::Color>(),
xaml_typename<Editor::NullableColorPicker>(),
PropertyMetadata{ box_value(Windows::UI::Colors::Transparent()) });
}
}
void NullableColorPicker::_OnCurrentColorValueChanged(const DependencyObject& d, const DependencyPropertyChangedEventArgs& /*e*/)
{
const auto& obj{ d.try_as<Editor::NullableColorPicker>() };
get_self<NullableColorPicker>(obj)->_UpdateColorChips();
}
void NullableColorPicker::_UpdateColorChips()
{
const auto& currentColor = CurrentColor();
for (const auto& colorChip : _colorChips)
{
const auto& chipColor = colorChip.DataContext().as<Editor::ColorTableEntry>().Color();
colorChip.IsChecked(currentColor ?
equalsColor(chipColor, currentColor.Value()) :
false);
}
}
SolidColorBrush NullableColorPicker::CalculateBorderBrush(const Windows::UI::Color& color)
{
static constexpr auto isColorLight = [](const winrt::Windows::UI::Color& clr) -> bool {
return (((5 * clr.G) + (2 * clr.R) + clr.B) > (8 * 128));
};
if (isColorLight(color))
{
return SolidColorBrush(Colors::Black());
}
else
{
return SolidColorBrush(Colors::White());
}
}
void NullableColorPicker::ColorChip_Clicked(const IInspectable& sender, const RoutedEventArgs& /*args*/)
{
const auto& btn = sender.as<Windows::UI::Xaml::Controls::Primitives::ToggleButton>();
const auto& colorEntryColor = btn.DataContext().as<Editor::ColorTableEntry>().Color();
const Microsoft::Terminal::Core::Color terminalColor{ colorEntryColor.R, colorEntryColor.G, colorEntryColor.B, colorEntryColor.A };
CurrentColor(terminalColor);
btn.IsChecked(true);
}
void NullableColorPicker::ColorChip_DataContextChanged(const IInspectable& sender, const DataContextChangedEventArgs& args)
{
if (const auto& toggleBtn = sender.try_as<Controls::Primitives::ToggleButton>())
{
if (const auto& currentColor = CurrentColor())
{
const auto& currentColorVal = currentColor.Value();
const auto& newChipColor = args.NewValue().as<Editor::ColorTableEntry>().Color();
toggleBtn.IsChecked(equalsColor(newChipColor, currentColorVal));
}
}
}
bool NullableColorPicker::IsNull(IReference<Microsoft::Terminal::Core::Color> color)
{
return color == nullptr;
}
void NullableColorPicker::NullColorButton_Clicked(const IInspectable& /*sender*/, const RoutedEventArgs& /*args*/)
{
CurrentColor(nullptr);
}
safe_void_coroutine NullableColorPicker::MoreColors_Clicked(const IInspectable& /*sender*/, const RoutedEventArgs& /*args*/)
{
co_await ColorPickerDialog().ShowAsync();
}
void NullableColorPicker::ColorPickerDialog_Opened(const IInspectable& /*sender*/, const ContentDialogOpenedEventArgs& /*args*/)
{
// Initialize color picker with current color
if (CurrentColor())
{
const auto& terminalColor = CurrentColor().Value();
const Windows::UI::Color winuiColor{
.A = terminalColor.A,
.R = terminalColor.R,
.G = terminalColor.G,
.B = terminalColor.B
};
ColorPickerControl().Color(winuiColor);
}
else
{
// No current color (null), use the deduced value for null
ColorPickerControl().Color(NullColorPreview());
}
}
void NullableColorPicker::ColorPickerDialog_PrimaryButtonClick(const IInspectable& /*sender*/, const ContentDialogButtonClickEventArgs& /*args*/)
{
const auto& selectedColor = ColorPickerControl().Color();
const Microsoft::Terminal::Core::Color terminalColor{ selectedColor.R, selectedColor.G, selectedColor.B, selectedColor.A };
CurrentColor(terminalColor);
}
void NullableColorPicker::ColorChip_Loaded(const IInspectable& sender, const RoutedEventArgs& /*args*/)
{
if (const auto& toggleBtn = sender.try_as<Controls::Primitives::ToggleButton>())
{
if (const auto& currentColor = CurrentColor())
{
const auto& currentColorVal = currentColor.Value();
const auto& chipColor = toggleBtn.DataContext().as<Editor::ColorTableEntry>().Color();
if (equalsColor(chipColor, currentColorVal))
{
toggleBtn.IsChecked(true);
}
}
_colorChips.push_back(toggleBtn);
}
}
void NullableColorPicker::ColorChip_Unloaded(const IInspectable& sender, const RoutedEventArgs& /*args*/)
{
if (const auto& toggleBtn = sender.try_as<Controls::Primitives::ToggleButton>())
{
for (auto it = _colorChips.begin(); it != _colorChips.end(); ++it)
{
if (*it == toggleBtn)
{
_colorChips.erase(it);
break;
}
}
}
}
}

View File

@@ -0,0 +1,49 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include "NullableColorPicker.g.h"
#include "Utils.h"
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
struct NullableColorPicker : public HasScrollViewer<NullableColorPicker>, NullableColorPickerT<NullableColorPicker>
{
public:
NullableColorPicker();
static winrt::Windows::UI::Xaml::Media::SolidColorBrush CalculateBorderBrush(const Windows::UI::Color& color);
static bool IsNull(Windows::Foundation::IReference<Microsoft::Terminal::Core::Color> color);
void ColorChip_Loaded(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::RoutedEventArgs& args);
void ColorChip_Unloaded(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::RoutedEventArgs& args);
void ColorChip_Clicked(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::RoutedEventArgs& args);
void ColorChip_DataContextChanged(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::DataContextChangedEventArgs& args);
void NullColorButton_Clicked(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::RoutedEventArgs& args);
safe_void_coroutine MoreColors_Clicked(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::RoutedEventArgs& args);
void ColorPickerDialog_Opened(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::Controls::ContentDialogOpenedEventArgs& args);
void ColorPickerDialog_PrimaryButtonClick(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::Controls::ContentDialogButtonClickEventArgs& args);
DEPENDENCY_PROPERTY(Editor::ColorSchemeViewModel, ColorSchemeVM);
DEPENDENCY_PROPERTY(Windows::Foundation::IReference<Microsoft::Terminal::Core::Color>, CurrentColor);
DEPENDENCY_PROPERTY(bool, ShowNullColorButton);
DEPENDENCY_PROPERTY(hstring, NullColorButtonLabel);
DEPENDENCY_PROPERTY(Windows::UI::Color, NullColorPreview);
private:
static void _InitializeProperties();
static void _OnCurrentColorValueChanged(const Windows::UI::Xaml::DependencyObject& d, const Windows::UI::Xaml::DependencyPropertyChangedEventArgs& e);
void _UpdateColorChips();
std::vector<Windows::UI::Xaml::Controls::Primitives::ToggleButton> _colorChips;
};
}
namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation
{
BASIC_FACTORY(NullableColorPicker);
}

View File

@@ -0,0 +1,30 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import "ColorSchemeViewModel.idl";
namespace Microsoft.Terminal.Settings.Editor
{
[default_interface] runtimeclass NullableColorPicker : Windows.UI.Xaml.Controls.UserControl
{
NullableColorPicker();
ColorSchemeViewModel ColorSchemeVM;
static Windows.UI.Xaml.DependencyProperty ColorSchemeVMProperty { get; };
Windows.Foundation.IReference<Microsoft.Terminal.Core.Color> CurrentColor;
static Windows.UI.Xaml.DependencyProperty CurrentColorProperty { get; };
Boolean ShowNullColorButton;
static Windows.UI.Xaml.DependencyProperty ShowNullColorButtonProperty { get; };
String NullColorButtonLabel;
static Windows.UI.Xaml.DependencyProperty NullColorButtonLabelProperty { get; };
Windows.UI.Color NullColorPreview;
static Windows.UI.Xaml.DependencyProperty NullColorPreviewProperty { get; };
static Windows.UI.Xaml.Media.SolidColorBrush CalculateBorderBrush(Windows.UI.Color color);
static Boolean IsNull(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color> color);
}
}

View File

@@ -0,0 +1,155 @@
<!--
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
the MIT License. See LICENSE in the project root for license information.
-->
<UserControl x:Class="Microsoft.Terminal.Settings.Editor.NullableColorPicker"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.Terminal.Settings.Editor"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:model="using:Microsoft.Terminal.Settings.Model"
xmlns:mtu="using:Microsoft.Terminal.UI"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
mc:Ignorable="d">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="CommonResources.xaml" />
</ResourceDictionary.MergedDictionaries>
<DataTemplate x:Key="ColorPreviewChipTemplate"
x:DataType="local:ColorTableEntry">
<ToggleButton Margin="0,0,4,4"
AutomationProperties.Name="{x:Bind NameWithHexCode}"
Background="{x:Bind mtu:Converters.ColorToBrush(Color)}"
BorderBrush="{x:Bind local:NullableColorPicker.CalculateBorderBrush(Color), Mode=OneWay}"
BorderThickness="2"
Click="ColorChip_Clicked"
DataContextChanged="ColorChip_DataContextChanged"
Loaded="ColorChip_Loaded"
Style="{StaticResource ColorToggleButtonStyle}"
ToolTipService.ToolTip="{x:Bind NameWithHexCode}"
Unloaded="ColorChip_Unloaded" />
</DataTemplate>
<DataTemplate x:Key="ColorSchemeTemplate"
x:DataType="local:ColorSchemeViewModel">
<VariableSizedWrapGrid Name="ColorSchemeGrid"
HorizontalAlignment="Left"
MaximumRowsOrColumns="4"
Orientation="Horizontal"
XYFocusKeyboardNavigation="Enabled">
<ContentControl Content="{x:Bind ColorEntryAt(0), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
<ContentControl Content="{x:Bind ColorEntryAt(1), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
<ContentControl Content="{x:Bind ColorEntryAt(2), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
<ContentControl Content="{x:Bind ColorEntryAt(3), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
<ContentControl Content="{x:Bind ColorEntryAt(4), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
<ContentControl Content="{x:Bind ColorEntryAt(5), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
<ContentControl Content="{x:Bind ColorEntryAt(6), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
<ContentControl Content="{x:Bind ColorEntryAt(7), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
<ContentControl Content="{x:Bind ColorEntryAt(8), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
<ContentControl Content="{x:Bind ColorEntryAt(9), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
<ContentControl Content="{x:Bind ColorEntryAt(10), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
<ContentControl Content="{x:Bind ColorEntryAt(11), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
<ContentControl Content="{x:Bind ColorEntryAt(12), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
<ContentControl Content="{x:Bind ColorEntryAt(13), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
<ContentControl Content="{x:Bind ColorEntryAt(14), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
<ContentControl Content="{x:Bind ColorEntryAt(15), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
</VariableSizedWrapGrid>
</DataTemplate>
</ResourceDictionary>
</UserControl.Resources>
<Grid ColumnSpacing="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ContentDialog x:Name="ColorPickerDialog"
x:Uid="NullableColorPicker_ColorPickerContentDialog"
DefaultButton="Primary"
Opened="ColorPickerDialog_Opened"
PrimaryButtonClick="ColorPickerDialog_PrimaryButtonClick"
TabFocusNavigation="Cycle">
<muxc:ColorPicker x:Name="ColorPickerControl"
Margin="0,0,0,-40"
ColorSpectrumShape="Box"
IsAlphaEnabled="False"
IsAlphaSliderVisible="True"
IsAlphaTextInputVisible="True"
IsColorChannelTextInputVisible="False"
IsColorSliderVisible="False"
IsHexInputVisible="False"
IsMoreButtonVisible="False"
Orientation="Horizontal" />
</ContentDialog>
<ContentPresenter Grid.Column="0"
Content="{x:Bind ColorSchemeVM, Mode=OneWay}"
ContentTemplate="{StaticResource ColorSchemeTemplate}" />
<StackPanel Grid.Column="1"
Spacing="5">
<ToggleButton AutomationProperties.Name="{x:Bind NullColorButtonLabel}"
Click="NullColorButton_Clicked"
IsChecked="{x:Bind IsNull(CurrentColor), Mode=OneWay}">
<Grid ColumnSpacing="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Border Grid.Column="0"
Width="20"
Height="20"
Background="{x:Bind mtu:Converters.ColorToBrush(NullColorPreview), Mode=OneWay}"
BorderThickness="1"
CornerRadius="{ThemeResource ControlCornerRadius}" />
<TextBlock Grid.Column="1"
Text="{x:Bind NullColorButtonLabel}" />
</Grid>
</ToggleButton>
<Button x:Uid="NullableColorPicker_MoreColorsButton"
HorizontalAlignment="Stretch"
Click="MoreColors_Clicked" />
</StackPanel>
</Grid>
</UserControl>

View File

@@ -10,6 +10,7 @@
#include <LibraryResources.h> #include <LibraryResources.h>
#include "../WinRTUtils/inc/Utils.h" #include "../WinRTUtils/inc/Utils.h"
#include "../../renderer/base/FontCache.h" #include "../../renderer/base/FontCache.h"
#include "SegoeFluentIconList.h"
using namespace winrt::Windows::UI::Text; using namespace winrt::Windows::UI::Text;
using namespace winrt::Windows::UI::Xaml; using namespace winrt::Windows::UI::Xaml;
@@ -26,6 +27,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
Windows::Foundation::Collections::IObservableVector<Editor::Font> ProfileViewModel::_MonospaceFontList{ nullptr }; Windows::Foundation::Collections::IObservableVector<Editor::Font> ProfileViewModel::_MonospaceFontList{ nullptr };
Windows::Foundation::Collections::IObservableVector<Editor::Font> ProfileViewModel::_FontList{ nullptr }; Windows::Foundation::Collections::IObservableVector<Editor::Font> ProfileViewModel::_FontList{ nullptr };
Windows::Foundation::Collections::IVector<IInspectable> ProfileViewModel::_BuiltInIcons{ nullptr };
static constexpr std::wstring_view HideIconValue{ L"none" }; static constexpr std::wstring_view HideIconValue{ L"none" };
@@ -41,6 +43,17 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
INITIALIZE_BINDABLE_ENUM_SETTING(ScrollState, ScrollbarState, winrt::Microsoft::Terminal::Control::ScrollbarState, L"Profile_ScrollbarVisibility", L"Content"); INITIALIZE_BINDABLE_ENUM_SETTING(ScrollState, ScrollbarState, winrt::Microsoft::Terminal::Control::ScrollbarState, L"Profile_ScrollbarVisibility", L"Content");
INITIALIZE_BINDABLE_ENUM_SETTING(PathTranslationStyle, PathTranslationStyle, winrt::Microsoft::Terminal::Control::PathTranslationStyle, L"Profile_PathTranslationStyle", L"Content"); INITIALIZE_BINDABLE_ENUM_SETTING(PathTranslationStyle, PathTranslationStyle, winrt::Microsoft::Terminal::Control::PathTranslationStyle, L"Profile_PathTranslationStyle", L"Content");
// set up IconTypes
std::vector<IInspectable> iconTypes;
iconTypes.reserve(4);
iconTypes.emplace_back(make<EnumEntry>(RS_(L"Profile_IconTypeNone"), box_value(IconType::None)));
iconTypes.emplace_back(make<EnumEntry>(RS_(L"Profile_IconTypeFontIcon"), box_value(IconType::FontIcon)));
iconTypes.emplace_back(make<EnumEntry>(RS_(L"Profile_IconTypeEmoji"), box_value(IconType::Emoji)));
iconTypes.emplace_back(make<EnumEntry>(RS_(L"Profile_IconTypeImage"), box_value(IconType::Image)));
_IconTypes = winrt::single_threaded_vector<IInspectable>(std::move(iconTypes));
_DeduceCurrentIconType();
_DeduceCurrentBuiltInIcon();
// Add a property changed handler to our own property changed event. // Add a property changed handler to our own property changed event.
// This propagates changes from the settings model to anybody listening to our // This propagates changes from the settings model to anybody listening to our
// unique view model members. // unique view model members.
@@ -75,7 +88,29 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
} }
else if (viewModelProperty == L"Icon") else if (viewModelProperty == L"Icon")
{ {
_NotifyChanges(L"HideIcon"); // _DeduceCurrentIconType() ends with a "CurrentIconType" notification
// so we don't need to call _UpdateIconPreview() here
_DeduceCurrentIconType();
}
else if (viewModelProperty == L"CurrentIconType")
{
// "Using*" handles the visibility of the IconType-related UI.
// The others propagate the rendered icon into a preview (i.e. nav view, container item)
_NotifyChanges(L"UsingNoIcon",
L"UsingBuiltInIcon",
L"UsingEmojiIcon",
L"UsingImageIcon",
L"LocalizedIcon",
L"IconPreview",
L"EvaluatedIcon");
}
else if (viewModelProperty == L"CurrentBuiltInIcon")
{
Icon(unbox_value<hstring>(_CurrentBuiltInIcon.as<Editor::EnumEntry>().EnumValue()));
}
else if (viewModelProperty == L"CurrentEmojiIcon")
{
Icon(CurrentEmojiIcon());
} }
else if (viewModelProperty == L"PathTranslationStyle") else if (viewModelProperty == L"PathTranslationStyle")
{ {
@@ -107,6 +142,61 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
_defaultAppearanceViewModel.IsDefault(true); _defaultAppearanceViewModel.IsDefault(true);
} }
void ProfileViewModel::_UpdateBuiltInIcons()
{
std::vector<IInspectable> builtInIcons;
for (auto& [val, name] : s_SegoeFluentIcons)
{
builtInIcons.emplace_back(make<EnumEntry>(hstring{ name }, box_value(val)));
}
_BuiltInIcons = single_threaded_vector<IInspectable>(std::move(builtInIcons));
}
void ProfileViewModel::_DeduceCurrentIconType()
{
const auto& profileIcon = _profile.Icon();
if (profileIcon == HideIconValue)
{
_currentIconType = _IconTypes.GetAt(0);
}
else if (L"\uE700" <= profileIcon && profileIcon <= L"\uF8B3")
{
_currentIconType = _IconTypes.GetAt(1);
_DeduceCurrentBuiltInIcon();
}
else if (profileIcon.size() <= 2)
{
// We already did a range check for MDL2 Assets in the previous one,
// so if we're out of that range but still short, assume we're an emoji
_currentIconType = _IconTypes.GetAt(2);
}
else
{
_currentIconType = _IconTypes.GetAt(3);
}
_NotifyChanges(L"CurrentIconType");
}
void ProfileViewModel::_DeduceCurrentBuiltInIcon()
{
if (!_BuiltInIcons)
{
_UpdateBuiltInIcons();
}
const auto& profileIcon = Icon();
for (uint32_t i = 0; i < _BuiltInIcons.Size(); i++)
{
const auto& builtIn = _BuiltInIcons.GetAt(i);
if (profileIcon == unbox_value<hstring>(builtIn.as<Editor::EnumEntry>().EnumValue()))
{
_CurrentBuiltInIcon = builtIn;
return;
}
}
_CurrentBuiltInIcon = _BuiltInIcons.GetAt(0);
_NotifyChanges(L"CurrentBuiltInIcon");
}
void ProfileViewModel::LeftPadding(double value) noexcept void ProfileViewModel::LeftPadding(double value) noexcept
{ {
const hstring& padding = _GetNewPadding(PaddingDirection::Left, value); const hstring& padding = _GetNewPadding(PaddingDirection::Left, value);
@@ -483,26 +573,103 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
} }
} }
bool ProfileViewModel::HideIcon() winrt::hstring ProfileViewModel::LocalizedIcon() const
{ {
return Icon() == HideIconValue; if (_currentIconType && unbox_value<IconType>(_currentIconType.as<Editor::EnumEntry>().EnumValue()) == IconType::None)
{
return RS_(L"Profile_IconTypeNone");
}
return Icon();
} }
void ProfileViewModel::HideIcon(const bool hide)
Windows::UI::Xaml::Controls::IconElement ProfileViewModel::IconPreview() const
{ {
if (hide) // IconWUX sets the icon width/height to 32 by default
auto icon = Microsoft::Terminal::UI::IconPathConverter::IconWUX(EvaluatedIcon());
icon.Width(16);
icon.Height(16);
return icon;
}
void ProfileViewModel::CurrentIconType(const Windows::Foundation::IInspectable& value)
{
if (_currentIconType != value)
{ {
// Stash the current value of Icon. If the user // Switching from...
// checks and un-checks the "Hide Icon" checkbox, we want if (_currentIconType && unbox_value<IconType>(_currentIconType.as<Editor::EnumEntry>().EnumValue()) == IconType::Image)
// the path that we display in the text box to remain unchanged. {
_lastIcon = Icon(); // Stash the current value of Icon. If the user
Icon(HideIconValue); // switches out of then back to IconType::Image, we want
} // the path that we display in the text box to remain unchanged.
else _lastIconPath = Icon();
{ }
Icon(_lastIcon);
// Set the member here instead of after setting Icon() below!
// We have an Icon property changed handler defined for when we discard changes.
// Inadvertently, that means that we call this setter again.
// Setting the member here means that we early exit at the beginning of the function
// because _currentIconType == value.
_currentIconType = value;
// Switched to...
switch (unbox_value<IconType>(value.as<Editor::EnumEntry>().EnumValue()))
{
case IconType::None:
{
_profile.Icon(HideIconValue);
break;
}
case IconType::Image:
{
if (!_lastIconPath.empty())
{
// Conversely, if we switch to Image,
// retrieve that saved value and apply it
_profile.Icon(_lastIconPath);
}
break;
}
case IconType::FontIcon:
{
if (_CurrentBuiltInIcon)
{
_profile.Icon(unbox_value<hstring>(_CurrentBuiltInIcon.as<Editor::EnumEntry>().EnumValue()));
}
break;
}
case IconType::Emoji:
{
// Don't set Icon here!
// Clear out the text box so we direct the user to use the emoji picker.
CurrentEmojiIcon({});
}
}
// We're not using the VM's Icon() setter above,
// so notify HasIcon changed manually
_NotifyChanges(L"CurrentIconType", L"HasIcon");
} }
} }
bool ProfileViewModel::UsingNoIcon() const
{
return _currentIconType == _IconTypes.GetAt(0);
}
bool ProfileViewModel::UsingBuiltInIcon() const
{
return _currentIconType == _IconTypes.GetAt(1);
}
bool ProfileViewModel::UsingEmojiIcon() const
{
return _currentIconType == _IconTypes.GetAt(2);
}
bool ProfileViewModel::UsingImageIcon() const
{
return _currentIconType == _IconTypes.GetAt(3);
}
bool ProfileViewModel::IsBellStyleFlagSet(const uint32_t flag) bool ProfileViewModel::IsBellStyleFlagSet(const uint32_t flag)
{ {
return (WI_EnumValue(BellStyle()) & flag) == flag; return (WI_EnumValue(BellStyle()) & flag) == flag;

View File

@@ -33,6 +33,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
static void UpdateFontList() noexcept; static void UpdateFontList() noexcept;
static Windows::Foundation::Collections::IObservableVector<Editor::Font> CompleteFontList() noexcept { return _FontList; }; static Windows::Foundation::Collections::IObservableVector<Editor::Font> CompleteFontList() noexcept { return _FontList; };
static Windows::Foundation::Collections::IObservableVector<Editor::Font> MonospaceFontList() noexcept { return _MonospaceFontList; }; static Windows::Foundation::Collections::IObservableVector<Editor::Font> MonospaceFontList() noexcept { return _MonospaceFontList; };
static Windows::Foundation::Collections::IVector<IInspectable> BuiltInIcons() noexcept { return _BuiltInIcons; };
ProfileViewModel(const Model::Profile& profile, const Model::CascadiaSettings& settings); ProfileViewModel(const Model::Profile& profile, const Model::CascadiaSettings& settings);
Model::TerminalSettings TermSettings() const; Model::TerminalSettings TermSettings() const;
@@ -64,16 +65,23 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{ {
return _profile.EvaluatedIcon(); return _profile.EvaluatedIcon();
} }
Windows::Foundation::IInspectable CurrentIconType() const noexcept
{
return _currentIconType;
}
Windows::UI::Xaml::Controls::IconElement IconPreview() const;
winrt::hstring LocalizedIcon() const;
void CurrentIconType(const Windows::Foundation::IInspectable& value);
bool UsingNoIcon() const;
bool UsingBuiltInIcon() const;
bool UsingEmojiIcon() const;
bool UsingImageIcon() const;
// starting directory // starting directory
bool UseParentProcessDirectory(); bool UseParentProcessDirectory();
void UseParentProcessDirectory(const bool useParent); void UseParentProcessDirectory(const bool useParent);
bool UseCustomStartingDirectory(); bool UseCustomStartingDirectory();
// icon
bool HideIcon();
void HideIcon(const bool hide);
// general profile knowledge // general profile knowledge
winrt::guid OriginalProfileGuid() const noexcept; winrt::guid OriginalProfileGuid() const noexcept;
bool CanDeleteProfile() const; bool CanDeleteProfile() const;
@@ -94,6 +102,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
til::typed_event<Editor::ProfileViewModel, Editor::DeleteProfileEventArgs> DeleteProfileRequested; til::typed_event<Editor::ProfileViewModel, Editor::DeleteProfileEventArgs> DeleteProfileRequested;
VIEW_MODEL_OBSERVABLE_PROPERTY(ProfileSubPage, CurrentPage); VIEW_MODEL_OBSERVABLE_PROPERTY(ProfileSubPage, CurrentPage);
VIEW_MODEL_OBSERVABLE_PROPERTY(Windows::Foundation::IInspectable, CurrentBuiltInIcon);
VIEW_MODEL_OBSERVABLE_PROPERTY(hstring, CurrentEmojiIcon);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_profile, Guid); PERMANENT_OBSERVABLE_PROJECTED_SETTING(_profile, Guid);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_profile, ConnectionType); PERMANENT_OBSERVABLE_PROJECTED_SETTING(_profile, ConnectionType);
@@ -110,10 +120,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
OBSERVABLE_PROJECTED_SETTING(_profile, Commandline); OBSERVABLE_PROJECTED_SETTING(_profile, Commandline);
OBSERVABLE_PROJECTED_SETTING(_profile, StartingDirectory); OBSERVABLE_PROJECTED_SETTING(_profile, StartingDirectory);
OBSERVABLE_PROJECTED_SETTING(_profile, AntialiasingMode); OBSERVABLE_PROJECTED_SETTING(_profile, AntialiasingMode);
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), Foreground);
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), Background);
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), SelectionBackground);
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), CursorColor);
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), Opacity); OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), Opacity);
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), UseAcrylic); OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), UseAcrylic);
OBSERVABLE_PROJECTED_SETTING(_profile, HistorySize); OBSERVABLE_PROJECTED_SETTING(_profile, HistorySize);
@@ -134,6 +140,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
WINRT_PROPERTY(bool, IsBaseLayer, false); WINRT_PROPERTY(bool, IsBaseLayer, false);
WINRT_PROPERTY(bool, FocusDeleteButton, false); WINRT_PROPERTY(bool, FocusDeleteButton, false);
WINRT_PROPERTY(Windows::Foundation::Collections::IVector<Windows::Foundation::IInspectable>, IconTypes);
GETSET_BINDABLE_ENUM_SETTING(AntiAliasingMode, Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode); GETSET_BINDABLE_ENUM_SETTING(AntiAliasingMode, Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode);
GETSET_BINDABLE_ENUM_SETTING(CloseOnExitMode, Microsoft::Terminal::Settings::Model::CloseOnExitMode, CloseOnExit); GETSET_BINDABLE_ENUM_SETTING(CloseOnExitMode, Microsoft::Terminal::Settings::Model::CloseOnExitMode, CloseOnExit);
GETSET_BINDABLE_ENUM_SETTING(ScrollState, Microsoft::Terminal::Control::ScrollbarState, ScrollState); GETSET_BINDABLE_ENUM_SETTING(ScrollState, Microsoft::Terminal::Control::ScrollbarState, ScrollState);
@@ -144,11 +151,13 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
winrt::guid _originalProfileGuid{}; winrt::guid _originalProfileGuid{};
winrt::hstring _lastBgImagePath; winrt::hstring _lastBgImagePath;
winrt::hstring _lastStartingDirectoryPath; winrt::hstring _lastStartingDirectoryPath;
winrt::hstring _lastIcon; winrt::hstring _lastIconPath;
Windows::Foundation::IInspectable _currentIconType{};
Editor::AppearanceViewModel _defaultAppearanceViewModel; Editor::AppearanceViewModel _defaultAppearanceViewModel;
static Windows::Foundation::Collections::IObservableVector<Editor::Font> _MonospaceFontList; static Windows::Foundation::Collections::IObservableVector<Editor::Font> _MonospaceFontList;
static Windows::Foundation::Collections::IObservableVector<Editor::Font> _FontList; static Windows::Foundation::Collections::IObservableVector<Editor::Font> _FontList;
static Windows::Foundation::Collections::IVector<Windows::Foundation::IInspectable> _BuiltInIcons;
Model::CascadiaSettings _appSettings; Model::CascadiaSettings _appSettings;
Editor::AppearanceViewModel _unfocusedAppearanceViewModel; Editor::AppearanceViewModel _unfocusedAppearanceViewModel;
@@ -163,6 +172,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
winrt::hstring _GetNewPadding(PaddingDirection paddingDirection, double newPaddingValue) const; winrt::hstring _GetNewPadding(PaddingDirection paddingDirection, double newPaddingValue) const;
double _GetPaddingValue(PaddingDirection paddingDirection) const; double _GetPaddingValue(PaddingDirection paddingDirection) const;
void _UpdateBuiltInIcons();
void _DeduceCurrentIconType();
void _DeduceCurrentBuiltInIcon();
}; };
struct DeleteProfileEventArgs : struct DeleteProfileEventArgs :

View File

@@ -33,6 +33,14 @@ namespace Microsoft.Terminal.Settings.Editor
Advanced = 3 Advanced = 3
}; };
enum IconType
{
None = 0,
FontIcon,
Image,
Emoji
};
runtimeclass ProfileViewModel : Windows.UI.Xaml.Data.INotifyPropertyChanged runtimeclass ProfileViewModel : Windows.UI.Xaml.Data.INotifyPropertyChanged
{ {
Microsoft.Terminal.Settings.Model.TerminalSettings TermSettings { get; }; Microsoft.Terminal.Settings.Model.TerminalSettings TermSettings { get; };
@@ -71,7 +79,6 @@ namespace Microsoft.Terminal.Settings.Editor
ProfileSubPage CurrentPage; ProfileSubPage CurrentPage;
Boolean UseParentProcessDirectory; Boolean UseParentProcessDirectory;
Boolean UseCustomStartingDirectory { get; }; Boolean UseCustomStartingDirectory { get; };
Boolean HideIcon;
AppearanceViewModel DefaultAppearance { get; }; AppearanceViewModel DefaultAppearance { get; };
Guid OriginalProfileGuid { get; }; Guid OriginalProfileGuid { get; };
Boolean HasUnfocusedAppearance { get; }; Boolean HasUnfocusedAppearance { get; };
@@ -83,7 +90,19 @@ namespace Microsoft.Terminal.Settings.Editor
Boolean AutoMarkPromptsAvailable { get; }; Boolean AutoMarkPromptsAvailable { get; };
Boolean RepositionCursorWithMouseAvailable { get; }; Boolean RepositionCursorWithMouseAvailable { get; };
Windows.UI.Xaml.Controls.IconElement IconPreview { get; };
String EvaluatedIcon { get; }; String EvaluatedIcon { get; };
String LocalizedIcon { get; };
String CurrentEmojiIcon;
IInspectable CurrentIconType;
Windows.Foundation.Collections.IVector<IInspectable> IconTypes { get; };
Boolean UsingNoIcon { get; };
Boolean UsingBuiltInIcon { get; };
Boolean UsingEmojiIcon { get; };
Boolean UsingImageIcon { get; };
IInspectable CurrentBuiltInIcon;
Windows.Foundation.Collections.IVector<IInspectable> BuiltInIcons { get; };
void CreateUnfocusedAppearance(); void CreateUnfocusedAppearance();
void DeleteUnfocusedAppearance(); void DeleteUnfocusedAppearance();
@@ -106,10 +125,6 @@ namespace Microsoft.Terminal.Settings.Editor
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, Commandline); OBSERVABLE_PROJECTED_PROFILE_SETTING(String, Commandline);
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, StartingDirectory); OBSERVABLE_PROJECTED_PROFILE_SETTING(String, StartingDirectory);
OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Control.TextAntialiasingMode, AntialiasingMode); OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Control.TextAntialiasingMode, AntialiasingMode);
OBSERVABLE_PROJECTED_PROFILE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, Foreground);
OBSERVABLE_PROJECTED_PROFILE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, Background);
OBSERVABLE_PROJECTED_PROFILE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, SelectionBackground);
OBSERVABLE_PROJECTED_PROFILE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, CursorColor);
OBSERVABLE_PROJECTED_PROFILE_SETTING(Int32, HistorySize); OBSERVABLE_PROJECTED_PROFILE_SETTING(Int32, HistorySize);
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, SnapOnInput); OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, SnapOnInput);
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, AltGrAliasing); OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, AltGrAliasing);

View File

@@ -148,4 +148,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
_Profile.StartingDirectory(folder); _Profile.StartingDirectory(folder);
} }
} }
Windows::UI::Xaml::Controls::IconSource Profiles_Base::BuiltInIconConverter(const IInspectable& iconVal)
{
return Microsoft::Terminal::UI::IconPathConverter::IconSourceWUX(unbox_value<hstring>(iconVal));
}
} }

View File

@@ -25,6 +25,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void Advanced_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e); void Advanced_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
void DeleteConfirmation_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e); void DeleteConfirmation_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
static Windows::UI::Xaml::Controls::IconSource BuiltInIconConverter(const Windows::Foundation::IInspectable& iconVal);
til::property_changed_event PropertyChanged; til::property_changed_event PropertyChanged;
WINRT_PROPERTY(Editor::ProfileViewModel, Profile, nullptr); WINRT_PROPERTY(Editor::ProfileViewModel, Profile, nullptr);

View File

@@ -9,5 +9,7 @@ namespace Microsoft.Terminal.Settings.Editor
{ {
Profiles_Base(); Profiles_Base();
ProfileViewModel Profile { get; }; ProfileViewModel Profile { get; };
static Windows.UI.Xaml.Controls.IconSource BuiltInIconConverter(IInspectable iconVal);
} }
} }

View File

@@ -102,28 +102,98 @@
<!-- Icon --> <!-- Icon -->
<local:SettingContainer x:Uid="Profile_Icon" <local:SettingContainer x:Uid="Profile_Icon"
ClearSettingValue="{x:Bind Profile.ClearIcon}" ClearSettingValue="{x:Bind Profile.ClearIcon}"
CurrentValue="{x:Bind Profile.Icon, Mode=OneWay}"
HasSettingValue="{x:Bind Profile.HasIcon, Mode=OneWay}" HasSettingValue="{x:Bind Profile.HasIcon, Mode=OneWay}"
SettingOverrideSource="{x:Bind Profile.IconOverrideSource, Mode=OneWay}" SettingOverrideSource="{x:Bind Profile.IconOverrideSource, Mode=OneWay}"
Style="{StaticResource ExpanderSettingContainerStyle}"> Style="{StaticResource ExpanderSettingContainerStyleWithComplexPreview}">
<StackPanel> <local:SettingContainer.CurrentValue>
<TextBox x:Uid="Profile_IconBox" <Grid>
FontFamily="Segoe UI, Segoe Fluent Icons, Segoe MDL2 Assets" <ContentControl Width="16"
IsEnabled="{x:Bind mtu:Converters.InvertBoolean(Profile.HideIcon), Mode=OneWay}" Height="16"
IsSpellCheckEnabled="False" Content="{x:Bind Profile.IconPreview, Mode=OneWay}"
Style="{StaticResource TextBoxSettingStyle}" Visibility="{x:Bind mtu:Converters.InvertedBooleanToVisibility(Profile.UsingNoIcon), Mode=OneWay}" />
Text="{x:Bind Profile.Icon, Mode=TwoWay}" <TextBlock Margin="0,0,0,0"
Visibility="{x:Bind mtu:Converters.InvertedBooleanToVisibility(Profile.HideIcon), Mode=OneWay}" /> HorizontalAlignment="Right"
<Button x:Uid="Profile_IconBrowse" VerticalAlignment="Center"
Margin="0,10,0,0" FontFamily="Segoe UI, Segoe Fluent Icons, Segoe MDL2 Assets"
Click="Icon_Click" Style="{StaticResource SettingsPageItemDescriptionStyle}"
Style="{StaticResource BrowseButtonStyle}" Text="{x:Bind Profile.LocalizedIcon, Mode=OneWay}"
Visibility="{x:Bind mtu:Converters.InvertedBooleanToVisibility(Profile.HideIcon), Mode=OneWay}" /> Visibility="{x:Bind Profile.UsingNoIcon, Mode=OneWay}" />
<CheckBox x:Name="HideIconCheckbox" </Grid>
x:Uid="Profile_HideIconCheckbox" </local:SettingContainer.CurrentValue>
Margin="0,5,0,0" <local:SettingContainer.Content>
IsChecked="{x:Bind Profile.HideIcon, Mode=TwoWay}" /> <Grid ColumnSpacing="10">
</StackPanel> <Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<!-- Icon Type -->
<ComboBox x:Uid="Profile_IconType"
Grid.Column="0"
ItemsSource="{x:Bind Profile.IconTypes}"
SelectedItem="{x:Bind Profile.CurrentIconType, Mode=TwoWay}">
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="local:EnumEntry">
<TextBlock Text="{x:Bind EnumName}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<!-- Built-In Icon -->
<ComboBox x:Uid="Profile_BuiltInIcon"
Grid.Column="1"
ItemsSource="{x:Bind Profile.BuiltInIcons}"
SelectedItem="{x:Bind Profile.CurrentBuiltInIcon, Mode=TwoWay}"
Visibility="{x:Bind Profile.UsingBuiltInIcon, Mode=OneWay}">
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="local:EnumEntry">
<Grid ColumnSpacing="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<IconSourceElement Grid.Column="0"
Width="16"
Height="16"
IconSource="{x:Bind local:Profiles_Base.BuiltInIconConverter(EnumValue), Mode=OneTime}" />
<TextBlock Grid.Column="1"
Text="{x:Bind EnumName}" />
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<!-- Image (File) Icon -->
<TextBox x:Uid="Profile_IconBox"
Grid.Column="1"
MaxWidth="Infinity"
HorizontalAlignment="Stretch"
FontFamily="Segoe UI, Segoe Fluent Icons, Segoe MDL2 Assets"
IsSpellCheckEnabled="False"
Style="{StaticResource TextBoxSettingStyle}"
Text="{x:Bind Profile.Icon, Mode=TwoWay}"
Visibility="{x:Bind Profile.UsingImageIcon, Mode=OneWay}" />
<Button x:Uid="Profile_IconBrowse"
Grid.Column="2"
Margin="0"
VerticalAlignment="Top"
Click="Icon_Click"
Style="{StaticResource BrowseButtonStyle}"
Visibility="{x:Bind Profile.UsingImageIcon, Mode=OneWay}" />
<!-- Emoji Icon -->
<TextBox x:Uid="Profile_IconEmojiBox"
Grid.Column="1"
MaxWidth="Infinity"
FontFamily="Segoe UI, Segoe Fluent Icons, Segoe MDL2 Assets"
IsSpellCheckEnabled="False"
Style="{StaticResource TextBoxSettingStyle}"
Text="{x:Bind Profile.CurrentEmojiIcon, Mode=TwoWay}"
Visibility="{x:Bind Profile.UsingEmojiIcon, Mode=OneWay}" />
</Grid>
</local:SettingContainer.Content>
</local:SettingContainer> </local:SettingContainer>
<!-- Tab Title --> <!-- Tab Title -->

View File

@@ -894,6 +894,10 @@
<value>Color scheme</value> <value>Color scheme</value>
<comment>Header for a control to select the scheme (or set) of colors used in the session. This is selected from a list of options managed by the user.</comment> <comment>Header for a control to select the scheme (or set) of colors used in the session. This is selected from a list of options managed by the user.</comment>
</data> </data>
<data name="Profile_ColorScheme.HelpText" xml:space="preserve">
<value>Expand to override the foreground, background, and selection background.</value>
<comment>Help text for a control to select the scheme (or set) of colors used in the session. Directs the user to expand the control to access overrides for certain values in the color scheme.</comment>
</data>
<data name="Profile_Commandline.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve"> <data name="Profile_Commandline.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Command line</value> <value>Command line</value>
<comment>Name for a control to determine commandline executable (i.e. a .exe file) to run when a terminal session of this profile is launched.</comment> <comment>Name for a control to determine commandline executable (i.e. a .exe file) to run when a terminal session of this profile is launched.</comment>
@@ -1121,6 +1125,10 @@
<value>Icon</value> <value>Icon</value>
<comment>Name for a control to determine what icon can be used to represent this profile. This is not necessarily a file path, but can be one.</comment> <comment>Name for a control to determine what icon can be used to represent this profile. This is not necessarily a file path, but can be one.</comment>
</data> </data>
<data name="Profile_IconEmojiBox.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Icon</value>
<comment>Name for a control to determine what icon can be used to represent this profile.</comment>
</data>
<data name="Profile_Icon.HelpText" xml:space="preserve"> <data name="Profile_Icon.HelpText" xml:space="preserve">
<value>Emoji or image file location of the icon used in the profile.</value> <value>Emoji or image file location of the icon used in the profile.</value>
<comment>A description for what the "icon" setting does. Presented near "Profile_Icon".</comment> <comment>A description for what the "icon" setting does. Presented near "Profile_Icon".</comment>
@@ -1929,6 +1937,102 @@
<value>Non-monospace fonts:</value> <value>Non-monospace fonts:</value>
<comment>This is a label that is followed by a list of proportional fonts.</comment> <comment>This is a label that is followed by a list of proportional fonts.</comment>
</data> </data>
<data name="Profile_TabColor.Header" xml:space="preserve">
<value>Tab color</value>
<comment>Header for a control to determine the color of the tab.</comment>
</data>
<data name="Profile_Foreground.Header" xml:space="preserve">
<value>Foreground</value>
<comment>Header for a control to determine the foreground color of text.</comment>
</data>
<data name="Profile_Background.Header" xml:space="preserve">
<value>Background</value>
<comment>Header for a control to determine the background color of text.</comment>
</data>
<data name="Profile_SelectionBackground.Header" xml:space="preserve">
<value>Selection background</value>
<comment>Header for a control to determine the background color of selected text.</comment>
</data>
<data name="Profile_CursorColor.Header" xml:space="preserve">
<value>Cursor color</value>
<comment>Header for a control to determine the color of the cursor.</comment>
</data>
<data name="Profile_Foreground.HelpText" xml:space="preserve">
<value>Overrides the foreground color from the color scheme.</value>
<comment>A description for what the "foreground" setting does. Presented near "Profile_Foreground".</comment>
</data>
<data name="Profile_CursorColor.HelpText" xml:space="preserve">
<value>Overrides the cursor color from the color scheme.</value>
<comment>A description for what the "cursor color" setting does. Presented near "Profile_CursorColor".</comment>
</data>
<data name="Profile_Background.HelpText" xml:space="preserve">
<value>Overrides the background color from the color scheme.</value>
<comment>A description for what the "background" setting does. Presented near "Profile_Background".</comment>
</data>
<data name="Profile_SelectionBackground.HelpText" xml:space="preserve">
<value>Overrides the selection background color from the color scheme.</value>
<comment>A description for what the "selection background" setting does. Presented near "Profile_SelectionBackground".</comment>
</data>
<data name="NullableColorPicker_MoreColorsButton.Content" xml:space="preserve">
<value>More colors...</value>
<comment>Text label for a button that allows the user to select from more colors in a new window. {Locked="..."}</comment>
</data>
<data name="NullableColorPicker_ColorPickerContentDialog.Title" xml:space="preserve">
<value>Pick a color</value>
<comment>Title displayed on a content dialog directing the user to pick a color.</comment>
</data>
<data name="NullableColorPicker_ColorPickerContentDialog.PrimaryButtonText" xml:space="preserve">
<value>OK</value>
<comment>Button label for the color picker content dialog. Used as confirmation to apply the selected color.</comment>
</data>
<data name="NullableColorPicker_ColorPickerContentDialog.SecondaryButtonText" xml:space="preserve">
<value>Cancel</value>
<comment>Text label for secondary button the color picker content dialog. When clicked, the operation of selecting a color is cancelled by the user.</comment>
</data>
<data name="Profile_CursorColor_NullableColorPicker.NullColorButtonLabel" xml:space="preserve">
<value>Use cursor color from color scheme</value>
<comment>Label for a button directing the user to use the cursor color defined in the terminal's current color scheme.</comment>
</data>
<data name="Profile_Foreground_NullableColorPicker.NullColorButtonLabel" xml:space="preserve">
<value>Use foreground color from color scheme</value>
<comment>Label for a button directing the user to use the foreground color defined in the terminal's current color scheme.</comment>
</data>
<data name="Profile_Background_NullableColorPicker.NullColorButtonLabel" xml:space="preserve">
<value>Use background color from color scheme</value>
<comment>Label for a button directing the user to use the background color defined in the terminal's current color scheme.</comment>
</data>
<data name="Profile_SelectionBackground_NullableColorPicker.NullColorButtonLabel" xml:space="preserve">
<value>Use selection background color from color scheme</value>
<comment>Label for a button directing the user to use the selection background color defined in the terminal's current color scheme.</comment>
</data>
<data name="Profile_IconTypeNone" xml:space="preserve">
<value>None</value>
<comment>An option to choose from for the "icon style" dropdown. When selected, there will be no icon for the profile.</comment>
</data>
<data name="Profile_IconTypeImage" xml:space="preserve">
<value>File</value>
<comment>An option to choose from for the "icon style" dropdown. When selected, a custom image can set for the profile's icon.</comment>
</data>
<data name="Profile_IconTypeEmoji" xml:space="preserve">
<value>Emoji</value>
<comment>An option to choose from for the "icon style" dropdown. When selected, an emoji can be set for the profile's icon.</comment>
</data>
<data name="Profile_IconTypeFontIcon" xml:space="preserve">
<value>Built-in Icon</value>
<comment>An option to choose from for the "icon style" dropdown. When selected, the user can choose from several preselected options to set the profile's icon.</comment>
</data>
<data name="Profile_IconEmojiBox.PlaceholderText" xml:space="preserve">
<value>Use "Win + period" to open the emoji picker</value>
<comment>"Win + period" refers to the OS key binding to open the emoji picker.</comment>
</data>
<data name="Profile_IconType.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Icon type</value>
<comment>Accessible name for a control allowing the user to select the type of icon they would like to use.</comment>
</data>
<data name="Profile_BuiltInIcon.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Icon</value>
<comment>Accessible name for a control allowing the user to select the icon from a list of built in icons.</comment>
</data>
<data name="Nav_NewTabMenu.Content" xml:space="preserve"> <data name="Nav_NewTabMenu.Content" xml:space="preserve">
<value>New Tab Menu</value> <value>New Tab Menu</value>
<comment>Header for the "new tab menu" menu item. This navigates to a page that lets you see and modify settings related to the app's new tab menu (i.e. profile ordering, nested folders, dividers, etc.)</comment> <comment>Header for the "new tab menu" menu item. This navigates to a page that lets you see and modify settings related to the app's new tab menu (i.e. profile ordering, nested folders, dividers, etc.)</comment>

File diff suppressed because it is too large Load Diff

View File

@@ -14,6 +14,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
DependencyProperty SettingContainer::_HelpTextProperty{ nullptr }; DependencyProperty SettingContainer::_HelpTextProperty{ nullptr };
DependencyProperty SettingContainer::_FontIconGlyphProperty{ nullptr }; DependencyProperty SettingContainer::_FontIconGlyphProperty{ nullptr };
DependencyProperty SettingContainer::_CurrentValueProperty{ nullptr }; DependencyProperty SettingContainer::_CurrentValueProperty{ nullptr };
DependencyProperty SettingContainer::_CurrentValueTemplateProperty{ nullptr };
DependencyProperty SettingContainer::_HasSettingValueProperty{ nullptr }; DependencyProperty SettingContainer::_HasSettingValueProperty{ nullptr };
DependencyProperty SettingContainer::_SettingOverrideSourceProperty{ nullptr }; DependencyProperty SettingContainer::_SettingOverrideSourceProperty{ nullptr };
DependencyProperty SettingContainer::_StartExpandedProperty{ nullptr }; DependencyProperty SettingContainer::_StartExpandedProperty{ nullptr };
@@ -60,9 +61,18 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
_CurrentValueProperty = _CurrentValueProperty =
DependencyProperty::Register( DependencyProperty::Register(
L"CurrentValue", L"CurrentValue",
xaml_typename<hstring>(), xaml_typename<IInspectable>(),
xaml_typename<Editor::SettingContainer>(), xaml_typename<Editor::SettingContainer>(),
PropertyMetadata{ box_value(L"") }); PropertyMetadata{ nullptr });
}
if (!_CurrentValueTemplateProperty)
{
_CurrentValueTemplateProperty =
DependencyProperty::Register(
L"CurrentValueTemplate",
xaml_typename<Windows::UI::Xaml::DataTemplate>(),
xaml_typename<Editor::SettingContainer>(),
PropertyMetadata{ nullptr });
} }
if (!_HasSettingValueProperty) if (!_HasSettingValueProperty)
{ {

View File

@@ -36,7 +36,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
DEPENDENCY_PROPERTY(Windows::Foundation::IInspectable, Header); DEPENDENCY_PROPERTY(Windows::Foundation::IInspectable, Header);
DEPENDENCY_PROPERTY(hstring, HelpText); DEPENDENCY_PROPERTY(hstring, HelpText);
DEPENDENCY_PROPERTY(hstring, FontIconGlyph); DEPENDENCY_PROPERTY(hstring, FontIconGlyph);
DEPENDENCY_PROPERTY(hstring, CurrentValue); DEPENDENCY_PROPERTY(Windows::Foundation::IInspectable, CurrentValue);
DEPENDENCY_PROPERTY(Windows::UI::Xaml::DataTemplate, CurrentValueTemplate);
DEPENDENCY_PROPERTY(bool, HasSettingValue); DEPENDENCY_PROPERTY(bool, HasSettingValue);
DEPENDENCY_PROPERTY(bool, StartExpanded); DEPENDENCY_PROPERTY(bool, StartExpanded);
DEPENDENCY_PROPERTY(IInspectable, SettingOverrideSource); DEPENDENCY_PROPERTY(IInspectable, SettingOverrideSource);

View File

@@ -18,9 +18,12 @@ namespace Microsoft.Terminal.Settings.Editor
String FontIconGlyph; String FontIconGlyph;
static Windows.UI.Xaml.DependencyProperty FontIconGlyphProperty { get; }; static Windows.UI.Xaml.DependencyProperty FontIconGlyphProperty { get; };
String CurrentValue; IInspectable CurrentValue;
static Windows.UI.Xaml.DependencyProperty CurrentValueProperty { get; }; static Windows.UI.Xaml.DependencyProperty CurrentValueProperty { get; };
Windows.UI.Xaml.DataTemplate CurrentValueTemplate;
static Windows.UI.Xaml.DependencyProperty CurrentValueTemplateProperty { get; };
Boolean HasSettingValue; Boolean HasSettingValue;
static Windows.UI.Xaml.DependencyProperty HasSettingValueProperty { get; }; static Windows.UI.Xaml.DependencyProperty HasSettingValueProperty { get; };

View File

@@ -178,11 +178,67 @@
<Setter Property="TextWrapping" Value="WrapWholeWords" /> <Setter Property="TextWrapping" Value="WrapWholeWords" />
</Style> </Style>
<DataTemplate x:Key="ExpanderSettingContainerStringPreviewTemplate">
<TextBlock MaxWidth="250"
Margin="0,0,-16,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
FontFamily="Segoe UI, Segoe Fluent Icons, Segoe MDL2 Assets"
Style="{StaticResource SettingsPageItemDescriptionStyle}"
Text="{Binding}" />
</DataTemplate>
<!-- A setting container for a setting that has no additional options --> <!-- A setting container for a setting that has no additional options -->
<Style TargetType="local:SettingContainer"> <Style TargetType="local:SettingContainer">
<Setter Property="Margin" Value="0,4,0,0" /> <Setter Property="Margin" Value="0,4,0,0" />
<Setter Property="IsTabStop" Value="False" /> <Setter Property="IsTabStop" Value="False" />
<Setter Property="MaxWidth" Value="1000" /> <Setter Property="MaxWidth" Value="1000" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:SettingContainer">
<Grid AutomationProperties.Name="{TemplateBinding Header}"
Style="{StaticResource NonExpanderGrid}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0"
Style="{StaticResource StackPanelInExpanderStyle}">
<StackPanel Orientation="Horizontal">
<TextBlock Style="{StaticResource SettingsPageItemHeaderStyle}"
Text="{TemplateBinding Header}" />
<Button x:Name="ResetButton"
Style="{StaticResource SettingContainerResetButtonStyle}">
<FontIcon Glyph="&#xE845;"
Style="{StaticResource SettingContainerFontIconStyle}" />
</Button>
</StackPanel>
<TextBlock x:Name="HelpTextBlock"
Style="{StaticResource SettingsPageItemDescriptionStyle}"
Text="{TemplateBinding HelpText}" />
</StackPanel>
<ContentPresenter Grid.Column="1"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Content="{TemplateBinding Content}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--
A setting container for a setting that has no additional options.
Includes space for an icon on the left side of the header.
XAML applies the margin/padding of the icon regardless of its
existence (which caused inconsistent padding). It's easier to just create
another style and move on.
-->
<Style x:Key="SettingContainerWithIcon"
TargetType="local:SettingContainer">
<Setter Property="Margin" Value="0,4,0,0" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="MaxWidth" Value="1000" />
<Setter Property="Template"> <Setter Property="Template">
<Setter.Value> <Setter.Value>
<ControlTemplate TargetType="local:SettingContainer"> <ControlTemplate TargetType="local:SettingContainer">
@@ -194,9 +250,9 @@
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<FontIcon Grid.Column="0" <FontIcon Grid.Column="0"
Margin="0,0,10,0"
Glyph="{TemplateBinding FontIconGlyph}" /> Glyph="{TemplateBinding FontIconGlyph}" />
<StackPanel Grid.Column="1" <StackPanel Grid.Column="1"
Padding="14,12,0,12"
Style="{StaticResource StackPanelInExpanderStyle}"> Style="{StaticResource StackPanelInExpanderStyle}">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<TextBlock Style="{StaticResource SettingsPageItemHeaderStyle}" <TextBlock Style="{StaticResource SettingsPageItemHeaderStyle}"
@@ -238,14 +294,10 @@
<muxc:Expander.Header> <muxc:Expander.Header>
<Grid MinHeight="64"> <Grid MinHeight="64">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<FontIcon Grid.Column="0" <StackPanel Grid.Column="0"
Margin="0,0,10,0"
Glyph="{TemplateBinding FontIconGlyph}" />
<StackPanel Grid.Column="1"
Style="{StaticResource StackPanelInExpanderStyle}"> Style="{StaticResource StackPanelInExpanderStyle}">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<TextBlock Style="{StaticResource SettingsPageItemHeaderStyle}" <TextBlock Style="{StaticResource SettingsPageItemHeaderStyle}"
@@ -260,14 +312,114 @@
Style="{StaticResource SettingsPageItemDescriptionStyle}" Style="{StaticResource SettingsPageItemDescriptionStyle}"
Text="{TemplateBinding HelpText}" /> Text="{TemplateBinding HelpText}" />
</StackPanel> </StackPanel>
<TextBlock Grid.Column="2" <ContentPresenter Grid.Column="1"
MaxWidth="250" Content="{TemplateBinding CurrentValue}"
Margin="0,0,-16,0" ContentTemplate="{StaticResource ExpanderSettingContainerStringPreviewTemplate}" />
HorizontalAlignment="Right" </Grid>
VerticalAlignment="Center" </muxc:Expander.Header>
FontFamily="Segoe UI, Segoe Fluent Icons, Segoe MDL2 Assets" </muxc:Expander>
Style="{StaticResource SettingsPageItemDescriptionStyle}" </ControlTemplate>
Text="{TemplateBinding CurrentValue}" /> </Setter.Value>
</Setter>
</Style>
<!--
A setting container which can expand. Includes space for an icon on the left side of the header.
XAML applies the margin/padding of the icon regardless of its
existence (which caused inconsistent padding). It's easier to just create
another style and move on.
-->
<Style x:Key="ExpanderSettingContainerStyleWithIcon"
TargetType="local:SettingContainer">
<Setter Property="MaxWidth" Value="1000" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:SettingContainer">
<muxc:Expander x:Name="Expander"
Margin="0,4,0,0"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
Content="{TemplateBinding Content}"
IsExpanded="{TemplateBinding StartExpanded}">
<muxc:Expander.Header>
<Grid MinHeight="64">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<FontIcon Grid.Column="0"
Glyph="{TemplateBinding FontIconGlyph}" />
<StackPanel Grid.Column="1"
Padding="14,12,0,12"
Style="{StaticResource StackPanelInExpanderStyle}">
<StackPanel Orientation="Horizontal">
<TextBlock Style="{StaticResource SettingsPageItemHeaderStyle}"
Text="{TemplateBinding Header}" />
<Button x:Name="ResetButton"
Style="{StaticResource SettingContainerResetButtonStyle}">
<FontIcon Glyph="&#xE845;"
Style="{StaticResource SettingContainerFontIconStyle}" />
</Button>
</StackPanel>
<TextBlock x:Name="HelpTextBlock"
Style="{StaticResource SettingsPageItemDescriptionStyle}"
Text="{TemplateBinding HelpText}" />
</StackPanel>
<ContentPresenter Grid.Column="2"
Content="{TemplateBinding CurrentValue}"
ContentTemplate="{StaticResource ExpanderSettingContainerStringPreviewTemplate}" />
</Grid>
</muxc:Expander.Header>
</muxc:Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- A setting container which can expand. Supports data template override for preview -->
<Style x:Key="ExpanderSettingContainerStyleWithComplexPreview"
TargetType="local:SettingContainer">
<Setter Property="MaxWidth" Value="1000" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:SettingContainer">
<muxc:Expander x:Name="Expander"
Margin="0,4,0,0"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
Content="{TemplateBinding Content}"
IsExpanded="{TemplateBinding StartExpanded}">
<muxc:Expander.Header>
<Grid MinHeight="64">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0"
Style="{StaticResource StackPanelInExpanderStyle}">
<StackPanel Orientation="Horizontal">
<TextBlock Style="{StaticResource SettingsPageItemHeaderStyle}"
Text="{TemplateBinding Header}" />
<Button x:Name="ResetButton"
Style="{StaticResource SettingContainerResetButtonStyle}">
<FontIcon Glyph="&#xE845;"
Style="{StaticResource SettingContainerFontIconStyle}" />
</Button>
</StackPanel>
<TextBlock x:Name="HelpTextBlock"
Style="{StaticResource SettingsPageItemDescriptionStyle}"
Text="{TemplateBinding HelpText}" />
</StackPanel>
<ContentPresenter Grid.Column="1"
MaxWidth="250"
Margin="0,0,-16,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Content="{TemplateBinding CurrentValue}"
ContentTemplate="{TemplateBinding CurrentValueTemplate}" />
</Grid> </Grid>
</muxc:Expander.Header> </muxc:Expander.Header>
</muxc:Expander> </muxc:Expander>

View File

@@ -0,0 +1,35 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "TerminalColorConverters.h"
#include "ColorToBrushConverter.g.cpp"
#include "ColorToStringConverter.g.cpp"
using namespace winrt::Microsoft::Terminal::Settings::Model;
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
Windows::Foundation::IInspectable ColorToBrushConverter::Convert(Windows::Foundation::IInspectable const& value, Windows::UI::Xaml::Interop::TypeName const& /*targetType*/, Windows::Foundation::IInspectable const& /*parameter*/, hstring const& /*language*/)
{
const auto color = value.as<Windows::UI::Color>();
return Microsoft::Terminal::UI::Converters::ColorToBrush(color);
}
Windows::Foundation::IInspectable ColorToBrushConverter::ConvertBack(Windows::Foundation::IInspectable const& /*value*/, Windows::UI::Xaml::Interop::TypeName const& /*targetType*/, Windows::Foundation::IInspectable const& /*parameter*/, hstring const& /*language*/)
{
throw hresult_not_implemented();
}
Windows::Foundation::IInspectable ColorToStringConverter::Convert(Windows::Foundation::IInspectable const& value, Windows::UI::Xaml::Interop::TypeName const& /*targetType*/, Windows::Foundation::IInspectable const& /*parameter*/, hstring const& /*language*/)
{
const auto color = value.as<Windows::UI::Color>();
return winrt::box_value(fmt::format(FMT_COMPILE(L"#{:02X}{:02X}{:02X}"), color.R, color.G, color.B));
}
Windows::Foundation::IInspectable ColorToStringConverter::ConvertBack(Windows::Foundation::IInspectable const& /*value*/, Windows::UI::Xaml::Interop::TypeName const& /*targetType*/, Windows::Foundation::IInspectable const& /*parameter*/, hstring const& /*language*/)
{
throw hresult_not_implemented();
}
}

View File

@@ -0,0 +1,33 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include "ColorToBrushConverter.g.h"
#include "ColorToStringConverter.g.h"
#include "Utils.h"
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
struct ColorToBrushConverter : ColorToBrushConverterT<ColorToBrushConverter>
{
ColorToBrushConverter() = default;
Windows::Foundation::IInspectable Convert(Windows::Foundation::IInspectable const& value, Windows::UI::Xaml::Interop::TypeName const& targetType, Windows::Foundation::IInspectable const& parameter, hstring const& language);
Windows::Foundation::IInspectable ConvertBack(Windows::Foundation::IInspectable const& value, Windows::UI::Xaml::Interop::TypeName const& targetType, Windows::Foundation::IInspectable const& parameter, hstring const& language);
};
struct ColorToStringConverter : ColorToStringConverterT<ColorToStringConverter>
{
ColorToStringConverter() = default;
Windows::Foundation::IInspectable Convert(Windows::Foundation::IInspectable const& value, Windows::UI::Xaml::Interop::TypeName const& targetType, Windows::Foundation::IInspectable const& parameter, hstring const& language);
Windows::Foundation::IInspectable ConvertBack(Windows::Foundation::IInspectable const& value, Windows::UI::Xaml::Interop::TypeName const& targetType, Windows::Foundation::IInspectable const& parameter, hstring const& language);
};
};
namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation
{
BASIC_FACTORY(ColorToBrushConverter);
BASIC_FACTORY(ColorToStringConverter);
}

View File

@@ -0,0 +1,15 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
namespace Microsoft.Terminal.Settings.Editor
{
runtimeclass ColorToBrushConverter : [default] Windows.UI.Xaml.Data.IValueConverter
{
ColorToBrushConverter();
}
runtimeclass ColorToStringConverter : [default] Windows.UI.Xaml.Data.IValueConverter
{
ColorToStringConverter();
}
}

View File

@@ -409,6 +409,61 @@ winrt::hstring Profile::_evaluateIcon() const
return winrt::hstring{ cmdline.c_str() }; return winrt::hstring{ cmdline.c_str() };
} }
bool Profile::HasIcon() const
{
return _Icon.has_value();
}
winrt::Microsoft::Terminal::Settings::Model::Profile Profile::IconOverrideSource()
{
for (const auto& parent : _parents)
{
if (auto source{ parent->_getIconOverrideSourceImpl() })
{
return source;
}
}
return nullptr;
}
void Profile::ClearIcon()
{
_Icon = std::nullopt;
_evaluatedIcon = std::nullopt;
}
std::optional<winrt::hstring> Profile::_getIconImpl() const
{
if (_Icon)
{
return _Icon;
}
for (const auto& parent : _parents)
{
if (auto val{ parent->_getIconImpl() })
{
return val;
}
}
return std::nullopt;
}
winrt::Microsoft::Terminal::Settings::Model::Profile Profile::_getIconOverrideSourceImpl() const
{
if (_Icon)
{
return *this;
}
for (const auto& parent : _parents)
{
if (auto source{ parent->_getIconOverrideSourceImpl() })
{
return source;
}
}
return nullptr;
}
// Given a commandLine like the following: // Given a commandLine like the following:
// * "C:\WINDOWS\System32\cmd.exe" // * "C:\WINDOWS\System32\cmd.exe"
// * "pwsh -WorkingDirectory ~" // * "pwsh -WorkingDirectory ~"

View File

@@ -102,17 +102,22 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
Model::IAppearanceConfig DefaultAppearance(); Model::IAppearanceConfig DefaultAppearance();
Model::FontConfig FontInfo(); Model::FontConfig FontInfo();
winrt::hstring EvaluatedIcon();
static std::wstring NormalizeCommandLine(LPCWSTR commandLine); static std::wstring NormalizeCommandLine(LPCWSTR commandLine);
void _FinalizeInheritance() override; void _FinalizeInheritance() override;
void LogSettingChanges(std::set<std::string>& changes, const std::string_view& context) const; void LogSettingChanges(std::set<std::string>& changes, const std::string_view& context) const;
// Special fields // EvaluatedIcon depends on Icon. It allows us to grab the
// icon from an exe path.
// As a result, we can't use the INHERITABLE_SETTING macro for Icon,
// as we manually have to set/unset _evaluatedIcon when Icon changes.
winrt::hstring EvaluatedIcon();
hstring Icon() const; hstring Icon() const;
void Icon(const hstring& value); void Icon(const hstring& value);
bool HasIcon() const;
Model::Profile IconOverrideSource();
void ClearIcon();
WINRT_PROPERTY(bool, Deleted, false); WINRT_PROPERTY(bool, Deleted, false);
WINRT_PROPERTY(bool, Orphaned, false); WINRT_PROPERTY(bool, Orphaned, false);
@@ -129,8 +134,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
INHERITABLE_SETTING(Model::Profile, bool, Hidden, false); INHERITABLE_SETTING(Model::Profile, bool, Hidden, false);
INHERITABLE_SETTING(Model::Profile, guid, Guid, _GenerateGuidForProfile(Name(), Source())); INHERITABLE_SETTING(Model::Profile, guid, Guid, _GenerateGuidForProfile(Name(), Source()));
INHERITABLE_SETTING(Model::Profile, hstring, Padding, DEFAULT_PADDING); INHERITABLE_SETTING(Model::Profile, hstring, Padding, DEFAULT_PADDING);
// Icon is _very special_ because we want to customize its setter
_BASE_INHERITABLE_SETTING(Model::Profile, std::optional<hstring>, Icon, L"\uE756");
public: public:
#define PROFILE_SETTINGS_INITIALIZE(type, name, jsonKey, ...) \ #define PROFILE_SETTINGS_INITIALIZE(type, name, jsonKey, ...) \
@@ -142,6 +145,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
Model::IAppearanceConfig _DefaultAppearance{ winrt::make<AppearanceConfig>(weak_ref<Model::Profile>(*this)) }; Model::IAppearanceConfig _DefaultAppearance{ winrt::make<AppearanceConfig>(weak_ref<Model::Profile>(*this)) };
Model::FontConfig _FontInfo{ winrt::make<FontConfig>(weak_ref<Model::Profile>(*this)) }; Model::FontConfig _FontInfo{ winrt::make<FontConfig>(weak_ref<Model::Profile>(*this)) };
std::optional<hstring> _Icon{ std::nullopt };
std::optional<winrt::hstring> _evaluatedIcon{ std::nullopt }; std::optional<winrt::hstring> _evaluatedIcon{ std::nullopt };
std::set<std::string> _changeLog; std::set<std::string> _changeLog;
@@ -150,6 +154,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
static guid _GenerateGuidForProfile(const std::wstring_view& name, const std::wstring_view& source) noexcept; static guid _GenerateGuidForProfile(const std::wstring_view& name, const std::wstring_view& source) noexcept;
winrt::hstring _evaluateIcon() const; winrt::hstring _evaluateIcon() const;
std::optional<hstring> _getIconImpl() const;
Model::Profile _getIconOverrideSourceImpl() const;
void _logSettingSet(const std::string_view& setting); void _logSettingSet(const std::string_view& setting);
void _logSettingIfSet(const std::string_view& setting, const bool isSet); void _logSettingIfSet(const std::string_view& setting, const bool isSet);