Skip to content

Commit

Permalink
Allow editing font axes in the Settings UI (#16104)
Browse files Browse the repository at this point in the history
## Summary of the Pull Request
Allow editing of font features and axes in the SUI to get the UI closer
towards JSON parity

The allowed font axes are obtained directly from the currently selected
font, and their display names are presented to the user in the user's
current locale (if it exists). Otherwise, we just display the axis tag
to the user.

## References and Relevant Issues
#10000 

## Validation Steps Performed

- [x] Font Axes can be added/changed/removed from the Settings UI


![image](https://github.com/microsoft/terminal/assets/26824113/b1c3ed57-e329-4893-9f15-7b60154b5ea0)

![image](https://github.com/microsoft/terminal/assets/26824113/e1f1ea22-857d-4392-8a15-f81539fe9257)

## PR Checklist
- [ ] Closes #xxx
- [ ] Tests added/passed
- [ ] Documentation updated
- If checked, please file a pull request on [our docs
repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
- [ ] Schema updated (if necessary)
  • Loading branch information
PankajBhojwani authored Feb 29, 2024
1 parent 30dbd3b commit 99042d2
Show file tree
Hide file tree
Showing 11 changed files with 490 additions and 0 deletions.
1 change: 1 addition & 0 deletions .github/actions/spelling/allow/allow.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ CMMI
copyable
Counterintuitively
CtrlDToClose
CVS
CUI
cybersecurity
dalet
Expand Down
316 changes: 316 additions & 0 deletions src/cascadia/TerminalSettingsEditor/Appearances.cpp

Large diffs are not rendered by default.

42 changes: 42 additions & 0 deletions src/cascadia/TerminalSettingsEditor/Appearances.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Author(s):
#pragma once

#include "Font.g.h"
#include "AxisKeyValuePair.g.h"
#include "Appearances.g.h"
#include "AppearanceViewModel.g.h"
#include "Utils.h"
Expand All @@ -37,13 +38,39 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation

hstring ToString() { return _LocalizedName; }
bool HasPowerlineCharacters();
Windows::Foundation::Collections::IMap<winrt::hstring, winrt::hstring> FontAxesTagsAndNames();

WINRT_PROPERTY(hstring, Name);
WINRT_PROPERTY(hstring, LocalizedName);

private:
winrt::com_ptr<IDWriteFontFamily> _family;
std::optional<bool> _hasPowerlineCharacters;
winrt::hstring _axisTagToString(DWRITE_FONT_AXIS_TAG tag);
Windows::Foundation::Collections::IMap<winrt::hstring, winrt::hstring> _fontAxesTagsAndNames;
};

struct AxisKeyValuePair : AxisKeyValuePairT<AxisKeyValuePair>, ViewModelHelper<AxisKeyValuePair>
{
AxisKeyValuePair(winrt::hstring axisKey, float axisValue, const Windows::Foundation::Collections::IMap<winrt::hstring, float>& baseMap, const Windows::Foundation::Collections::IMap<winrt::hstring, winrt::hstring>& tagToNameMap);

winrt::hstring AxisKey();
void AxisKey(winrt::hstring axisKey);

float AxisValue();
void AxisValue(float axisValue);

int32_t AxisIndex();
void AxisIndex(int32_t axisIndex);

WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);

private:
winrt::hstring _AxisKey;
float _AxisValue;
int32_t _AxisIndex;
Windows::Foundation::Collections::IMap<winrt::hstring, float> _baseMap{ nullptr };
Windows::Foundation::Collections::IMap<winrt::hstring, winrt::hstring> _tagToNameMap{ nullptr };
};

struct AppearanceViewModel : AppearanceViewModelT<AppearanceViewModel>, ViewModelHelper<AppearanceViewModel>
Expand All @@ -69,6 +96,12 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
Editor::ColorSchemeViewModel CurrentColorScheme();
void CurrentColorScheme(const Editor::ColorSchemeViewModel& val);

void AddNewAxisKeyValuePair();
void DeleteAxisKeyValuePair(winrt::hstring key);
void InitializeFontAxesVector();
bool AreFontAxesAvailable();
bool CanFontAxesBeAdded();

WINRT_PROPERTY(bool, IsDefault, false);

// These settings are not defined in AppearanceConfig, so we grab them
Expand All @@ -79,6 +112,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
OBSERVABLE_PROJECTED_SETTING(_appearance.SourceProfile().FontInfo(), FontFace);
OBSERVABLE_PROJECTED_SETTING(_appearance.SourceProfile().FontInfo(), FontSize);
OBSERVABLE_PROJECTED_SETTING(_appearance.SourceProfile().FontInfo(), FontWeight);
OBSERVABLE_PROJECTED_SETTING(_appearance.SourceProfile().FontInfo(), FontAxes);
OBSERVABLE_PROJECTED_SETTING(_appearance.SourceProfile().FontInfo(), EnableBuiltinGlyphs);

OBSERVABLE_PROJECTED_SETTING(_appearance, RetroTerminalEffect);
Expand All @@ -93,10 +127,13 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
OBSERVABLE_PROJECTED_SETTING(_appearance, IntenseTextStyle);
OBSERVABLE_PROJECTED_SETTING(_appearance, AdjustIndistinguishableColors);
WINRT_OBSERVABLE_PROPERTY(Windows::Foundation::Collections::IObservableVector<Editor::ColorSchemeViewModel>, SchemesList, _propertyChangedHandlers, nullptr);
WINRT_OBSERVABLE_PROPERTY(Windows::Foundation::Collections::IObservableVector<Editor::AxisKeyValuePair>, FontAxesVector, _propertyChangedHandlers, nullptr);

private:
Model::AppearanceConfig _appearance;
winrt::hstring _lastBgImagePath;

Editor::AxisKeyValuePair _CreateAxisKeyValuePairHelper(winrt::hstring axisKey, float axisValue, const Windows::Foundation::Collections::IMap<winrt::hstring, float>& baseMap, const Windows::Foundation::Collections::IMap<winrt::hstring, winrt::hstring>& tagToNameMap);
};

struct Appearances : AppearancesT<Appearances>
Expand All @@ -117,6 +154,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
fire_and_forget BackgroundImage_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
void BIAlignment_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
void FontFace_SelectionChanged(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Controls::SelectionChangedEventArgs& e);
void DeleteAxisKeyValuePair_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
void AddNewAxisKeyValuePair_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);

// manually bind FontWeight
Windows::Foundation::IInspectable CurrentFontWeight() const;
Expand Down Expand Up @@ -144,6 +183,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
Windows::Foundation::Collections::IMap<uint16_t, Microsoft::Terminal::Settings::Editor::EnumEntry> _FontWeightMap;
Editor::EnumEntry _CustomFontWeight{ nullptr };

Windows::Foundation::Collections::IObservableVector<winrt::hstring> _FontAxesNames;

Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _ViewModelChangedRevoker;
static void _ViewModelChanged(const Windows::UI::Xaml::DependencyObject& d, const Windows::UI::Xaml::DependencyPropertyChangedEventArgs& e);
void _UpdateWithNewViewModel();
Expand All @@ -153,4 +194,5 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation
{
BASIC_FACTORY(Appearances);
BASIC_FACTORY(AxisKeyValuePair);
}
21 changes: 21 additions & 0 deletions src/cascadia/TerminalSettingsEditor/Appearances.idl
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,26 @@ import "ColorSchemesPageViewModel.idl";
OBSERVABLE_PROJECTED_SETTING(Type, Name); \
Object Name##OverrideSource { get; }

#define COMMA ,

namespace Microsoft.Terminal.Settings.Editor
{
runtimeclass Font : Windows.Foundation.IStringable
{
String Name { get; };
String LocalizedName { get; };
Boolean HasPowerlineCharacters { get; };
Windows.Foundation.Collections.IMap<String, String> FontAxesTagsAndNames { get; };
}

// We have to make this because we cannot bind an IObservableMap to a ListView in XAML (in c++)
// So instead we make an IObservableVector of these AxisKeyValuePair objects
runtimeclass AxisKeyValuePair : Windows.UI.Xaml.Data.INotifyPropertyChanged
{
AxisKeyValuePair(String axisKey, Single axisValue, Windows.Foundation.Collections.IMap<String, Single> baseMap, Windows.Foundation.Collections.IMap<String, String> tagToNameMap);
String AxisKey;
Single AxisValue;
Int32 AxisIndex;
}

runtimeclass AppearanceViewModel : Windows.UI.Xaml.Data.INotifyPropertyChanged
Expand All @@ -37,6 +50,14 @@ namespace Microsoft.Terminal.Settings.Editor
ColorSchemeViewModel CurrentColorScheme;
Windows.Foundation.Collections.IObservableVector<ColorSchemeViewModel> SchemesList;

void AddNewAxisKeyValuePair();
void DeleteAxisKeyValuePair(String key);
void InitializeFontAxesVector();
Boolean AreFontAxesAvailable { get; };
Boolean CanFontAxesBeAdded { get; };
Windows.Foundation.Collections.IObservableVector<AxisKeyValuePair> FontAxesVector;
OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Windows.Foundation.Collections.IMap<String COMMA Single>, FontAxes);

OBSERVABLE_PROJECTED_APPEARANCE_SETTING(String, FontFace);
OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Single, FontSize);
OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Double, LineHeight);
Expand Down
63 changes: 63 additions & 0 deletions src/cascadia/TerminalSettingsEditor/Appearances.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
Background="{x:Bind local:Converters.ColorToBrush(Color)}"
CornerRadius="1" />
</DataTemplate>
<CollectionViewSource x:Key="FontAxesCVS"
x:Name="FontAxesCVS" />
</ResourceDictionary>
</UserControl.Resources>

Expand Down Expand Up @@ -286,6 +288,67 @@
</Grid>
</StackPanel>
</local:SettingContainer>
<local:SettingContainer x:Name="FontAxesContainer"
x:Uid="Profile_FontAxes"
ClearSettingValue="{x:Bind Appearance.ClearFontAxes}"
HasSettingValue="{x:Bind Appearance.HasFontAxes, Mode=OneWay}"
IsEnabled="{x:Bind Appearance.AreFontAxesAvailable, Mode=OneWay}"
SettingOverrideSource="{x:Bind Appearance.FontAxesOverrideSource, Mode=OneWay}"
Style="{StaticResource ExpanderSettingContainerStyle}">
<StackPanel Spacing="16">
<ListView IsItemClickEnabled="False"
ItemsSource="{Binding Source={StaticResource FontAxesCVS}}"
SelectionMode="None">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Padding" Value="0" />
<Setter Property="Margin" Value="0" />
</Style>
</ListView.ItemContainerStyle>
<ListView.Resources>
<CollectionViewSource x:Key="FontAxesNamesCVS"
x:Name="FontAxesNamesCVS" />
</ListView.Resources>
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:AxisKeyValuePair">
<Grid ColumnSpacing="8">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ComboBox Grid.Column="0"
IsSynchronizedWithCurrentItem="False"
ItemsSource="{Binding Source={StaticResource FontAxesNamesCVS}}"
SelectedIndex="{x:Bind AxisIndex, Mode=TwoWay}" />
<muxc:NumberBox Grid.Column="1"
Value="{x:Bind AxisValue, Mode=TwoWay}" />
<Button Grid.Column="2"
HorizontalAlignment="Right"
Click="DeleteAxisKeyValuePair_Click"
Style="{StaticResource DeleteButtonStyle}"
Tag="{x:Bind AxisKey}">
<FontIcon FontSize="{StaticResource StandardIconSize}"
Glyph="&#xE74D;" />
</Button>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button Click="AddNewAxisKeyValuePair_Click"
IsEnabled="{x:Bind Appearance.CanFontAxesBeAdded, Mode=OneWay}">
<Button.Content>
<StackPanel Orientation="Horizontal">
<FontIcon VerticalAlignment="Bottom"
FontSize="{StaticResource StandardIconSize}"
Glyph="&#xE710;" />
<TextBlock x:Uid="Profile_AddNewFontAxis"
Style="{StaticResource IconButtonTextBlockStyle}" />
</StackPanel>
</Button.Content>
</Button>
</StackPanel>
</local:SettingContainer>

<!-- Builtin Glyphs -->
<local:SettingContainer x:Uid="Profile_EnableBuiltinGlyphs"
Expand Down
4 changes: 4 additions & 0 deletions src/cascadia/TerminalSettingsEditor/ProfileViewModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
Editor::Font fallbackFont{ nullptr };
try
{
if (!CompleteFontList())
{
UpdateFontList();
}
const auto& currentFontList{ CompleteFontList() };
for (const auto& font : currentFontList)
{
Expand Down
16 changes: 16 additions & 0 deletions src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,10 @@
<value>Browse...</value>
<comment>Button label that opens a file picker in a new window. The "..." is standard to mean it will open a new window.</comment>
</data>
<data name="Profile_AddNewFontAxis.Text" xml:space="preserve">
<value>Add new</value>
<comment>Button label that adds a new font axis for the current font.</comment>
</data>
<data name="Profile_BackgroundImageOpacitySlider.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Background image opacity</value>
<comment>Name for a control to choose the opacity of the image presented on the background of the app.</comment>
Expand Down Expand Up @@ -922,6 +926,18 @@
<value>Sets the weight (lightness or heaviness of the strokes) for the given font.</value>
<comment>A description for what the "font weight" setting does. Presented near "Profile_FontWeight".</comment>
</data>
<data name="Profile_FontAxes.Header" xml:space="preserve">
<value>Variable font axes</value>
<comment>Header for a control to allow editing the font axes.</comment>
</data>
<data name="Profile_FontAxesAvailable.Text" xml:space="preserve">
<value>Add or remove font axes for the given font.</value>
<comment>A description for what the "font axes" setting does. Presented near "Profile_FontAxes".</comment>
</data>
<data name="Profile_FontAxesUnavailable.Text" xml:space="preserve">
<value>The selected font has no variable font axes.</value>
<comment>A description provided when the font axes setting is disabled. Presented near "Profile_FontAxes".</comment>
</data>
<data name="Profile_General.Header" xml:space="preserve">
<value>General</value>
<comment>Header for a sub-page of profile settings focused on more general scenarios.</comment>
Expand Down
11 changes: 11 additions & 0 deletions src/cascadia/TerminalSettingsEditor/SettingContainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,17 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
}
}

void SettingContainer::SetExpanded(bool expanded)
{
if (const auto& child{ GetTemplateChild(L"Expander") })
{
if (const auto& expander{ child.try_as<Microsoft::UI::Xaml::Controls::Expander>() })
{
expander.IsExpanded(expanded);
}
}
}

// Method Description:
// - Updates the override system visibility and text
// Arguments:
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalSettingsEditor/SettingContainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation

void OnApplyTemplate();

void SetExpanded(bool expanded);

DEPENDENCY_PROPERTY(Windows::Foundation::IInspectable, Header);
DEPENDENCY_PROPERTY(hstring, HelpText);
DEPENDENCY_PROPERTY(hstring, CurrentValue);
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalSettingsEditor/SettingContainer.idl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ namespace Microsoft.Terminal.Settings.Editor
{
SettingContainer();

void SetExpanded(Boolean expanded);

IInspectable Header;
static Windows.UI.Xaml.DependencyProperty HeaderProperty { get; };

Expand Down
12 changes: 12 additions & 0 deletions src/cascadia/TerminalSettingsModel/FontConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,18 @@ winrt::com_ptr<FontConfig> FontConfig::CopyFontInfo(const FontConfig* source, wi
MTSM_FONT_SETTINGS(FONT_SETTINGS_COPY)
#undef FONT_SETTINGS_COPY

// We cannot simply copy the font axes and features with `fontInfo->_FontAxes = source->_FontAxes;`
// since that'll just create a reference; we have to manually copy the values.
if (source->_FontAxes)
{
std::map<winrt::hstring, float> fontAxes;
for (const auto keyValuePair : source->_FontAxes.value())
{
fontAxes.insert(std::pair<winrt::hstring, float>(keyValuePair.Key(), keyValuePair.Value()));
}
fontInfo->_FontAxes = winrt::single_threaded_map(std::move(fontAxes));
}

return fontInfo;
}

Expand Down

0 comments on commit 99042d2

Please sign in to comment.