diff --git a/.github/actions/spelling/allow/allow.txt b/.github/actions/spelling/allow/allow.txt index 27466018802..3ece2375e52 100644 --- a/.github/actions/spelling/allow/allow.txt +++ b/.github/actions/spelling/allow/allow.txt @@ -17,6 +17,7 @@ CMMI copyable Counterintuitively CtrlDToClose +CVS CUI cybersecurity dalet diff --git a/src/cascadia/TerminalSettingsEditor/Appearances.cpp b/src/cascadia/TerminalSettingsEditor/Appearances.cpp index 8a3c9f943a2..848cb99349f 100644 --- a/src/cascadia/TerminalSettingsEditor/Appearances.cpp +++ b/src/cascadia/TerminalSettingsEditor/Appearances.cpp @@ -4,6 +4,7 @@ #include "pch.h" #include "Appearances.h" #include "Appearances.g.cpp" +#include "AxisKeyValuePair.g.cpp" #include "EnumEntry.h" #include @@ -42,6 +43,154 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation return _hasPowerlineCharacters.value_or(false); } + Windows::Foundation::Collections::IMap Font::FontAxesTagsAndNames() + { + if (!_fontAxesTagsAndNames) + { + wil::com_ptr font; + THROW_IF_FAILED(_family->GetFont(0, font.put())); + wil::com_ptr fontFace; + THROW_IF_FAILED(font->CreateFontFace(fontFace.put())); + wil::com_ptr fontFace5; + if (fontFace5 = fontFace.try_query()) + { + wil::com_ptr fontResource; + THROW_IF_FAILED(fontFace5->GetFontResource(fontResource.put())); + + const auto axesCount = fontFace5->GetFontAxisValueCount(); + if (axesCount > 0) + { + std::vector axesVector(axesCount); + fontFace5->GetFontAxisValues(axesVector.data(), axesCount); + + uint32_t localeIndex; + BOOL localeExists; + wchar_t localeName[LOCALE_NAME_MAX_LENGTH]; + const auto localeToTry = GetUserDefaultLocaleName(localeName, LOCALE_NAME_MAX_LENGTH) ? localeName : L"en-US"; + + std::unordered_map fontAxesTagsAndNames; + for (uint32_t i = 0; i < axesCount; ++i) + { + wil::com_ptr names; + THROW_IF_FAILED(fontResource->GetAxisNames(i, names.put())); + + if (!SUCCEEDED(names->FindLocaleName(localeToTry, &localeIndex, &localeExists)) || !localeExists) + { + // default to the first locale in the list + localeIndex = 0; + } + + UINT32 length = 0; + if (SUCCEEDED(names->GetStringLength(localeIndex, &length))) + { + winrt::impl::hstring_builder builder{ length }; + if (SUCCEEDED(names->GetString(localeIndex, builder.data(), length + 1))) + { + fontAxesTagsAndNames.insert(std::pair(_axisTagToString(axesVector[i].axisTag), builder.to_hstring())); + continue; + } + } + // if there was no name found, it means the font does not actually support this axis + // don't insert anything into the vector in this case + } + _fontAxesTagsAndNames = winrt::single_threaded_map(std::move(fontAxesTagsAndNames)); + } + } + } + return _fontAxesTagsAndNames; + } + + winrt::hstring Font::_axisTagToString(DWRITE_FONT_AXIS_TAG tag) + { + std::wstring result; + for (int i = 0; i < 4; ++i) + { + result.push_back((tag >> (i * 8)) & 0xFF); + } + return winrt::hstring{ result }; + } + + AxisKeyValuePair::AxisKeyValuePair(winrt::hstring axisKey, float axisValue, const Windows::Foundation::Collections::IMap& baseMap, const Windows::Foundation::Collections::IMap& tagToNameMap) : + _AxisKey{ axisKey }, + _AxisValue{ axisValue }, + _baseMap{ baseMap }, + _tagToNameMap{ tagToNameMap } + { + if (_tagToNameMap.HasKey(_AxisKey)) + { + int32_t i{ 0 }; + // IMap guarantees that the iteration order is the same every time + // so this conversion of key to index is safe + for (const auto tagAndName : _tagToNameMap) + { + if (tagAndName.Key() == _AxisKey) + { + _AxisIndex = i; + break; + } + ++i; + } + } + } + + winrt::hstring AxisKeyValuePair::AxisKey() + { + return _AxisKey; + } + + float AxisKeyValuePair::AxisValue() + { + return _AxisValue; + } + + int32_t AxisKeyValuePair::AxisIndex() + { + return _AxisIndex; + } + + void AxisKeyValuePair::AxisValue(float axisValue) + { + if (axisValue != _AxisValue) + { + _baseMap.Remove(_AxisKey); + _AxisValue = axisValue; + _baseMap.Insert(_AxisKey, _AxisValue); + _PropertyChangedHandlers(*this, PropertyChangedEventArgs{ L"AxisValue" }); + } + } + + void AxisKeyValuePair::AxisKey(winrt::hstring axisKey) + { + if (axisKey != _AxisKey) + { + _baseMap.Remove(_AxisKey); + _AxisKey = axisKey; + _baseMap.Insert(_AxisKey, _AxisValue); + _PropertyChangedHandlers(*this, PropertyChangedEventArgs{ L"AxisKey" }); + } + } + + void AxisKeyValuePair::AxisIndex(int32_t axisIndex) + { + if (axisIndex != _AxisIndex) + { + _AxisIndex = axisIndex; + + int32_t i{ 0 }; + // same as in the constructor, iterating through IMap + // gives us the same order every time + for (const auto tagAndName : _tagToNameMap) + { + if (i == _AxisIndex) + { + AxisKey(tagAndName.Key()); + break; + } + ++i; + } + } + } + AppearanceViewModel::AppearanceViewModel(const Model::AppearanceConfig& appearance) : _appearance{ appearance } { @@ -60,8 +209,18 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation // box, prevent it from ever being changed again. _NotifyChanges(L"UseDesktopBGImage", L"BackgroundImageSettingsVisible"); } + else if (viewModelProperty == L"FontAxes") + { + // this is a weird one + // we manually make the observable vector based on the map in the settings model + // (this is due to xaml being unable to bind a list view to a map) + // so when the FontAxes change (say from the reset button), reinitialize the observable vector + InitializeFontAxesVector(); + } }); + InitializeFontAxesVector(); + // Cache the original BG image path. If the user clicks "Use desktop // wallpaper", then un-checks it, this is the string we'll restore to // them. @@ -205,6 +364,119 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation LightColorSchemeName(val.Name()); } + void AppearanceViewModel::AddNewAxisKeyValuePair() + { + if (!_appearance.SourceProfile().FontInfo().FontAxes()) + { + _appearance.SourceProfile().FontInfo().FontAxes(winrt::single_threaded_map()); + } + auto fontAxesMap = _appearance.SourceProfile().FontInfo().FontAxes(); + + // find one axis that does not already exist, and add that + // if there are no more possible axes to add, the button is disabled so there shouldn't be a way to get here + const auto possibleAxesTagsAndNames = ProfileViewModel::FindFontWithLocalizedName(FontFace()).FontAxesTagsAndNames(); + for (const auto tagAndName : possibleAxesTagsAndNames) + { + if (!fontAxesMap.HasKey(tagAndName.Key())) + { + fontAxesMap.Insert(tagAndName.Key(), gsl::narrow(0)); + FontAxesVector().Append(_CreateAxisKeyValuePairHelper(tagAndName.Key(), gsl::narrow(0), fontAxesMap, possibleAxesTagsAndNames)); + break; + } + } + _NotifyChanges(L"CanFontAxesBeAdded"); + } + + void AppearanceViewModel::DeleteAxisKeyValuePair(winrt::hstring key) + { + for (uint32_t i = 0; i < _FontAxesVector.Size(); i++) + { + if (_FontAxesVector.GetAt(i).AxisKey() == key) + { + FontAxesVector().RemoveAt(i); + _appearance.SourceProfile().FontInfo().FontAxes().Remove(key); + if (_FontAxesVector.Size() == 0) + { + _appearance.SourceProfile().FontInfo().ClearFontAxes(); + } + break; + } + } + _NotifyChanges(L"CanFontAxesBeAdded"); + } + + void AppearanceViewModel::InitializeFontAxesVector() + { + if (!_FontAxesVector) + { + _FontAxesVector = winrt::single_threaded_observable_vector(); + } + + _FontAxesVector.Clear(); + if (const auto fontAxesMap = _appearance.SourceProfile().FontInfo().FontAxes()) + { + const auto fontAxesTagToNameMap = ProfileViewModel::FindFontWithLocalizedName(FontFace()).FontAxesTagsAndNames(); + for (const auto axis : fontAxesMap) + { + // only show the axes that the font supports + // any axes that the font doesn't support continue to be stored in the json, we just don't show them in the UI + if (fontAxesTagToNameMap.HasKey(axis.Key())) + { + _FontAxesVector.Append(_CreateAxisKeyValuePairHelper(axis.Key(), axis.Value(), fontAxesMap, fontAxesTagToNameMap)); + } + } + } + _NotifyChanges(L"AreFontAxesAvailable", L"CanFontAxesBeAdded"); + } + + // Method Description: + // - Determines whether the currently selected font has any variable font axes + bool AppearanceViewModel::AreFontAxesAvailable() + { + return ProfileViewModel::FindFontWithLocalizedName(FontFace()).FontAxesTagsAndNames().Size() > 0; + } + + // Method Description: + // - Determines whether the currently selected font has any variable font axes that have not already been set + bool AppearanceViewModel::CanFontAxesBeAdded() + { + if (const auto fontAxesTagToNameMap = ProfileViewModel::FindFontWithLocalizedName(FontFace()).FontAxesTagsAndNames(); fontAxesTagToNameMap.Size() > 0) + { + if (const auto fontAxesMap = _appearance.SourceProfile().FontInfo().FontAxes()) + { + for (const auto tagAndName : fontAxesTagToNameMap) + { + if (!fontAxesMap.HasKey(tagAndName.Key())) + { + // we found an axis that has not been set + return true; + } + } + // all possible axes have been set already + return false; + } + // the font supports font axes but the profile has none set + return true; + } + // the font does not support any font axes + return false; + } + + // Method Description: + // - Creates an AxisKeyValuePair and sets up an event handler for it + Editor::AxisKeyValuePair AppearanceViewModel::_CreateAxisKeyValuePairHelper(winrt::hstring axisKey, float axisValue, const Windows::Foundation::Collections::IMap& baseMap, const Windows::Foundation::Collections::IMap& tagToNameMap) + { + const auto axisKeyValuePair = winrt::make(axisKey, axisValue, baseMap, tagToNameMap); + // when either the key or the value changes, send an event for the preview control to catch + axisKeyValuePair.PropertyChanged([weakThis = get_weak()](auto& /*sender*/, auto& /*e*/) { + if (auto appVM{ weakThis.get() }) + { + appVM->_NotifyChanges(L"AxisKeyValuePair"); + } + }); + return axisKeyValuePair; + } + DependencyProperty Appearances::_AppearanceProperty{ nullptr }; Appearances::Appearances() : @@ -271,6 +543,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation const auto backgroundImgCheckboxTooltip{ ToolTipService::GetToolTip(UseDesktopImageCheckBox()) }; Automation::AutomationProperties::SetFullDescription(UseDesktopImageCheckBox(), unbox_value(backgroundImgCheckboxTooltip)); + _FontAxesNames = winrt::single_threaded_observable_vector(); + FontAxesNamesCVS().Source(_FontAxesNames); + INITIALIZE_BINDABLE_ENUM_SETTING(IntenseTextStyle, IntenseTextStyle, winrt::Microsoft::Terminal::Settings::Model::IntenseStyle, L"Appearance_IntenseTextStyle", L"Content"); } @@ -330,6 +605,28 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation { ShowProportionalFontWarning(false); } + + _FontAxesNames.Clear(); + const auto axesTagsAndNames = newFontFace.FontAxesTagsAndNames(); + for (const auto tagAndName : axesTagsAndNames) + { + _FontAxesNames.Append(tagAndName.Value()); + } + + // when the font face changes, we have to tell the view model to update the font axes vector + // since the new font may not have the same possible axes as the previous one + Appearance().InitializeFontAxesVector(); + if (!Appearance().AreFontAxesAvailable()) + { + // if the previous font had available font axes and the expander was expanded, + // at this point the expander would be set to disabled so manually collapse it + FontAxesContainer().SetExpanded(false); + FontAxesContainer().HelpText(RS_(L"Profile_FontAxesUnavailable/Text")); + } + else + { + FontAxesContainer().HelpText(RS_(L"Profile_FontAxesAvailable/Text")); + } } void Appearances::_ViewModelChanged(const DependencyObject& d, const DependencyPropertyChangedEventArgs& /*args*/) @@ -348,6 +645,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation biButton.IsChecked(biButton.Tag().as() == biAlignmentVal); } + FontAxesCVS().Source(Appearance().FontAxesVector()); + Appearance().AreFontAxesAvailable() ? FontAxesContainer().HelpText(RS_(L"Profile_FontAxesAvailable/Text")) : FontAxesContainer().HelpText(RS_(L"Profile_FontAxesUnavailable/Text")); + _ViewModelChangedRevoker = Appearance().PropertyChanged(winrt::auto_revoke, [=](auto&&, const PropertyChangedEventArgs& args) { const auto settingName{ args.PropertyName() }; if (settingName == L"CursorShape") @@ -470,6 +770,22 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation } } + void Appearances::DeleteAxisKeyValuePair_Click(const IInspectable& sender, const RoutedEventArgs& /*e*/) + { + if (const auto& button{ sender.try_as() }) + { + if (const auto& tag{ button.Tag().try_as() }) + { + Appearance().DeleteAxisKeyValuePair(tag.value()); + } + } + } + + void Appearances::AddNewAxisKeyValuePair_Click(const IInspectable& /*sender*/, const RoutedEventArgs& /*e*/) + { + Appearance().AddNewAxisKeyValuePair(); + } + bool Appearances::IsVintageCursor() const { return Appearance().CursorShape() == Core::CursorStyle::Vintage; diff --git a/src/cascadia/TerminalSettingsEditor/Appearances.h b/src/cascadia/TerminalSettingsEditor/Appearances.h index 4f220ef5e78..6e0edcc5d80 100644 --- a/src/cascadia/TerminalSettingsEditor/Appearances.h +++ b/src/cascadia/TerminalSettingsEditor/Appearances.h @@ -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" @@ -45,6 +46,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation hstring ToString() { return _LocalizedName; } bool HasPowerlineCharacters(); + Windows::Foundation::Collections::IMap FontAxesTagsAndNames(); WINRT_PROPERTY(hstring, Name); WINRT_PROPERTY(hstring, LocalizedName); @@ -52,6 +54,31 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation private: winrt::com_ptr _family; std::optional _hasPowerlineCharacters; + winrt::hstring _axisTagToString(DWRITE_FONT_AXIS_TAG tag); + Windows::Foundation::Collections::IMap _fontAxesTagsAndNames; + }; + + struct AxisKeyValuePair : AxisKeyValuePairT, ViewModelHelper + { + AxisKeyValuePair(winrt::hstring axisKey, float axisValue, const Windows::Foundation::Collections::IMap& baseMap, const Windows::Foundation::Collections::IMap& 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 _baseMap{ nullptr }; + Windows::Foundation::Collections::IMap _tagToNameMap{ nullptr }; }; struct AppearanceViewModel : AppearanceViewModelT, ViewModelHelper @@ -77,6 +104,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 @@ -87,6 +120,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); @@ -101,10 +135,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, SchemesList, _propertyChangedHandlers, nullptr); + WINRT_OBSERVABLE_PROPERTY(Windows::Foundation::Collections::IObservableVector, FontAxesVector, _propertyChangedHandlers, nullptr); private: Model::AppearanceConfig _appearance; winrt::hstring _lastBgImagePath; + + Editor::AxisKeyValuePair _CreateAxisKeyValuePairHelper(winrt::hstring axisKey, float axisValue, const Windows::Foundation::Collections::IMap& baseMap, const Windows::Foundation::Collections::IMap& tagToNameMap); }; struct Appearances : AppearancesT @@ -125,6 +162,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; @@ -152,6 +191,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation Windows::Foundation::Collections::IMap _FontWeightMap; Editor::EnumEntry _CustomFontWeight{ nullptr }; + Windows::Foundation::Collections::IObservableVector _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(); @@ -161,4 +202,5 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation { BASIC_FACTORY(Appearances); + BASIC_FACTORY(AxisKeyValuePair); } diff --git a/src/cascadia/TerminalSettingsEditor/Appearances.idl b/src/cascadia/TerminalSettingsEditor/Appearances.idl index ddab88a6beb..68bd887d217 100644 --- a/src/cascadia/TerminalSettingsEditor/Appearances.idl +++ b/src/cascadia/TerminalSettingsEditor/Appearances.idl @@ -13,6 +13,8 @@ import "ColorSchemesPageViewModel.idl"; OBSERVABLE_PROJECTED_SETTING(Type, Name); \ Object Name##OverrideSource { get; } +#define COMMA , + namespace Microsoft.Terminal.Settings.Editor { runtimeclass Font : Windows.Foundation.IStringable @@ -20,6 +22,17 @@ namespace Microsoft.Terminal.Settings.Editor String Name { get; }; String LocalizedName { get; }; Boolean HasPowerlineCharacters { get; }; + Windows.Foundation.Collections.IMap 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 baseMap, Windows.Foundation.Collections.IMap tagToNameMap); + String AxisKey; + Single AxisValue; + Int32 AxisIndex; } runtimeclass AppearanceViewModel : Windows.UI.Xaml.Data.INotifyPropertyChanged @@ -37,6 +50,14 @@ namespace Microsoft.Terminal.Settings.Editor ColorSchemeViewModel CurrentColorScheme; Windows.Foundation.Collections.IObservableVector SchemesList; + void AddNewAxisKeyValuePair(); + void DeleteAxisKeyValuePair(String key); + void InitializeFontAxesVector(); + Boolean AreFontAxesAvailable { get; }; + Boolean CanFontAxesBeAdded { get; }; + Windows.Foundation.Collections.IObservableVector FontAxesVector; + OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Windows.Foundation.Collections.IMap, FontAxes); + OBSERVABLE_PROJECTED_APPEARANCE_SETTING(String, FontFace); OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Single, FontSize); OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Double, LineHeight); diff --git a/src/cascadia/TerminalSettingsEditor/Appearances.xaml b/src/cascadia/TerminalSettingsEditor/Appearances.xaml index f1f13d8fbd6..0b5a9c2abfa 100644 --- a/src/cascadia/TerminalSettingsEditor/Appearances.xaml +++ b/src/cascadia/TerminalSettingsEditor/Appearances.xaml @@ -37,6 +37,8 @@ Background="{x:Bind local:Converters.ColorToBrush(Color)}" CornerRadius="1" /> + @@ -286,6 +288,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Browse... Button label that opens a file picker in a new window. The "..." is standard to mean it will open a new window. + + Add new + Button label that adds a new font axis for the current font. + Background image opacity Name for a control to choose the opacity of the image presented on the background of the app. @@ -922,6 +926,18 @@ Sets the weight (lightness or heaviness of the strokes) for the given font. A description for what the "font weight" setting does. Presented near "Profile_FontWeight". + + Variable font axes + Header for a control to allow editing the font axes. + + + Add or remove font axes for the given font. + A description for what the "font axes" setting does. Presented near "Profile_FontAxes". + + + The selected font has no variable font axes. + A description provided when the font axes setting is disabled. Presented near "Profile_FontAxes". + General Header for a sub-page of profile settings focused on more general scenarios. diff --git a/src/cascadia/TerminalSettingsEditor/SettingContainer.cpp b/src/cascadia/TerminalSettingsEditor/SettingContainer.cpp index 539165294c6..9bf3912e3aa 100644 --- a/src/cascadia/TerminalSettingsEditor/SettingContainer.cpp +++ b/src/cascadia/TerminalSettingsEditor/SettingContainer.cpp @@ -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() }) + { + expander.IsExpanded(expanded); + } + } + } + // Method Description: // - Updates the override system visibility and text // Arguments: diff --git a/src/cascadia/TerminalSettingsEditor/SettingContainer.h b/src/cascadia/TerminalSettingsEditor/SettingContainer.h index 5b48b438f51..be543681b3c 100644 --- a/src/cascadia/TerminalSettingsEditor/SettingContainer.h +++ b/src/cascadia/TerminalSettingsEditor/SettingContainer.h @@ -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); diff --git a/src/cascadia/TerminalSettingsEditor/SettingContainer.idl b/src/cascadia/TerminalSettingsEditor/SettingContainer.idl index 1148e0eb6d9..8b5fd0eba95 100644 --- a/src/cascadia/TerminalSettingsEditor/SettingContainer.idl +++ b/src/cascadia/TerminalSettingsEditor/SettingContainer.idl @@ -7,6 +7,8 @@ namespace Microsoft.Terminal.Settings.Editor { SettingContainer(); + void SetExpanded(Boolean expanded); + IInspectable Header; static Windows.UI.Xaml.DependencyProperty HeaderProperty { get; }; diff --git a/src/cascadia/TerminalSettingsModel/FontConfig.cpp b/src/cascadia/TerminalSettingsModel/FontConfig.cpp index fafdf0976bc..b01ec960658 100644 --- a/src/cascadia/TerminalSettingsModel/FontConfig.cpp +++ b/src/cascadia/TerminalSettingsModel/FontConfig.cpp @@ -30,6 +30,18 @@ winrt::com_ptr 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 fontAxes; + for (const auto keyValuePair : source->_FontAxes.value()) + { + fontAxes.insert(std::pair(keyValuePair.Key(), keyValuePair.Value())); + } + fontInfo->_FontAxes = winrt::single_threaded_map(std::move(fontAxes)); + } + return fontInfo; }