diff --git a/src/cascadia/TerminalSettingsEditor/CommonResources.xaml b/src/cascadia/TerminalSettingsEditor/CommonResources.xaml
index 2b290a3167..fbced179e7 100644
--- a/src/cascadia/TerminalSettingsEditor/CommonResources.xaml
+++ b/src/cascadia/TerminalSettingsEditor/CommonResources.xaml
@@ -8,14 +8,27 @@
xmlns:mtu="using:Microsoft.Terminal.UI"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls">
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 16
+
+
+
+
+
diff --git a/src/cascadia/TerminalSettingsEditor/ControlSizeTrigger.cpp b/src/cascadia/TerminalSettingsEditor/ControlSizeTrigger.cpp
deleted file mode 100644
index 52ba58d0c5..0000000000
--- a/src/cascadia/TerminalSettingsEditor/ControlSizeTrigger.cpp
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT license.
-
-#include "pch.h"
-#include "ControlSizeTrigger.h"
-#include "ControlSizeTrigger.g.cpp"
-
-#include
-
-using namespace winrt::Windows::Foundation;
-using namespace winrt::Windows::UI::Xaml;
-
-namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
-{
- DependencyProperty ControlSizeTrigger::_CanTriggerProperty{ nullptr };
- DependencyProperty ControlSizeTrigger::_MinWidthProperty{ nullptr };
- DependencyProperty ControlSizeTrigger::_MaxWidthProperty{ nullptr };
- DependencyProperty ControlSizeTrigger::_MinHeightProperty{ nullptr };
- DependencyProperty ControlSizeTrigger::_MaxHeightProperty{ nullptr };
- DependencyProperty ControlSizeTrigger::_TargetElementProperty{ nullptr };
-
- ControlSizeTrigger::ControlSizeTrigger()
- {
- _InitializeProperties();
- }
-
- void ControlSizeTrigger::_InitializeProperties()
- {
- // Defaults mirror the toolkit: trigger is always evaluatable, bounds
- // are wide open, no target element until one is bound.
- if (!_CanTriggerProperty)
- {
- _CanTriggerProperty = DependencyProperty::Register(
- L"CanTrigger",
- xaml_typename(),
- xaml_typename(),
- PropertyMetadata{ box_value(true), PropertyChangedCallback{ &ControlSizeTrigger::_OnTriggerInputChanged } });
- }
- if (!_MinWidthProperty)
- {
- _MinWidthProperty = DependencyProperty::Register(
- L"MinWidth",
- xaml_typename(),
- xaml_typename(),
- PropertyMetadata{ box_value(0.0), PropertyChangedCallback{ &ControlSizeTrigger::_OnTriggerInputChanged } });
- }
- if (!_MaxWidthProperty)
- {
- _MaxWidthProperty = DependencyProperty::Register(
- L"MaxWidth",
- xaml_typename(),
- xaml_typename(),
- PropertyMetadata{ box_value(std::numeric_limits::infinity()), PropertyChangedCallback{ &ControlSizeTrigger::_OnTriggerInputChanged } });
- }
- if (!_MinHeightProperty)
- {
- _MinHeightProperty = DependencyProperty::Register(
- L"MinHeight",
- xaml_typename(),
- xaml_typename(),
- PropertyMetadata{ box_value(0.0), PropertyChangedCallback{ &ControlSizeTrigger::_OnTriggerInputChanged } });
- }
- if (!_MaxHeightProperty)
- {
- _MaxHeightProperty = DependencyProperty::Register(
- L"MaxHeight",
- xaml_typename(),
- xaml_typename(),
- PropertyMetadata{ box_value(std::numeric_limits::infinity()), PropertyChangedCallback{ &ControlSizeTrigger::_OnTriggerInputChanged } });
- }
- if (!_TargetElementProperty)
- {
- _TargetElementProperty = DependencyProperty::Register(
- L"TargetElement",
- xaml_typename(),
- xaml_typename(),
- PropertyMetadata{ nullptr, PropertyChangedCallback{ &ControlSizeTrigger::_OnTargetElementChanged } });
- }
- }
-
- void ControlSizeTrigger::_OnTriggerInputChanged(const DependencyObject& d, const DependencyPropertyChangedEventArgs& /*e*/)
- {
- if (const auto obj{ d.try_as() })
- {
- get_self(obj)->_UpdateTrigger();
- }
- }
-
- void ControlSizeTrigger::_OnTargetElementChanged(const DependencyObject& d, const DependencyPropertyChangedEventArgs& e)
- {
- const auto obj{ d.try_as() };
- if (!obj)
- {
- return;
- }
- const auto oldElement = e.OldValue().try_as();
- const auto newElement = e.NewValue().try_as();
- get_self(obj)->_UpdateTargetElement(oldElement, newElement);
- }
-
- void ControlSizeTrigger::_UpdateTargetElement(const FrameworkElement& /*oldValue*/, const FrameworkElement& newValue)
- {
- // Revoking handles both unhooking the previous element and a null `newValue`.
- _sizeChangedRevoker.revoke();
- if (newValue)
- {
- _sizeChangedRevoker = newValue.SizeChanged(winrt::auto_revoke, [weakThis = get_weak()](auto&&, auto&&) {
- if (const auto strongThis = weakThis.get())
- {
- strongThis->_UpdateTrigger();
- }
- });
- }
- _UpdateTrigger();
- }
-
- void ControlSizeTrigger::_UpdateTrigger()
- {
- const auto target = TargetElement();
- if (!target || !CanTrigger())
- {
- _isActive = false;
- SetActive(false);
- return;
- }
-
- const auto width = target.ActualWidth();
- const auto height = target.ActualHeight();
-
- const bool activate =
- MinWidth() <= width &&
- width < MaxWidth() &&
- MinHeight() <= height &&
- height < MaxHeight();
-
- _isActive = activate;
- SetActive(activate);
- }
-}
diff --git a/src/cascadia/TerminalSettingsEditor/ControlSizeTrigger.h b/src/cascadia/TerminalSettingsEditor/ControlSizeTrigger.h
deleted file mode 100644
index 49e6a561f1..0000000000
--- a/src/cascadia/TerminalSettingsEditor/ControlSizeTrigger.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*++
-Copyright (c) Microsoft Corporation
-Licensed under the MIT license.
-
-Module Name:
-- ControlSizeTrigger
-
-Abstract:
-- A conditional state trigger that activates based on the size (width and/or
- height) of a target FrameworkElement. Lets XAML visual states swap based on
- the live size of a templated part. Ported from the Windows Community Toolkit
- primitive `CommunityToolkit.WinUI.ControlSizeTrigger`.
-
- The trigger is "active" when:
- MinWidth <= TargetElement.ActualWidth < MaxWidth AND
- MinHeight <= TargetElement.ActualHeight < MaxHeight
-
- Defaults: MinWidth = MinHeight = 0; MaxWidth = MaxHeight = +inf, which makes
- the trigger always active unless `CanTrigger` is false or `TargetElement` is
- null.
-
-Author(s):
-- Carlos Zamora - May 2026 (port from CommunityToolkit.WinUI.ControlSizeTrigger)
-
---*/
-
-#pragma once
-
-#include "ControlSizeTrigger.g.h"
-#include "Utils.h"
-
-namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
-{
- struct ControlSizeTrigger : ControlSizeTriggerT
- {
- public:
- ControlSizeTrigger();
-
- bool IsActive() const { return _isActive; }
-
- DEPENDENCY_PROPERTY(bool, CanTrigger);
- DEPENDENCY_PROPERTY(double, MinWidth);
- DEPENDENCY_PROPERTY(double, MaxWidth);
- DEPENDENCY_PROPERTY(double, MinHeight);
- DEPENDENCY_PROPERTY(double, MaxHeight);
- DEPENDENCY_PROPERTY(Windows::UI::Xaml::FrameworkElement, TargetElement);
-
- private:
- static void _InitializeProperties();
- static void _OnTriggerInputChanged(const Windows::UI::Xaml::DependencyObject& d, const Windows::UI::Xaml::DependencyPropertyChangedEventArgs& e);
- static void _OnTargetElementChanged(const Windows::UI::Xaml::DependencyObject& d, const Windows::UI::Xaml::DependencyPropertyChangedEventArgs& e);
-
- void _UpdateTargetElement(const Windows::UI::Xaml::FrameworkElement& oldValue, const Windows::UI::Xaml::FrameworkElement& newValue);
- void _UpdateTrigger();
-
- Windows::UI::Xaml::FrameworkElement::SizeChanged_revoker _sizeChangedRevoker;
- bool _isActive{ false };
- };
-}
-
-namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation
-{
- BASIC_FACTORY(ControlSizeTrigger);
-}
diff --git a/src/cascadia/TerminalSettingsEditor/ControlSizeTrigger.idl b/src/cascadia/TerminalSettingsEditor/ControlSizeTrigger.idl
deleted file mode 100644
index 7bfabbc5ae..0000000000
--- a/src/cascadia/TerminalSettingsEditor/ControlSizeTrigger.idl
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT license.
-
-namespace Microsoft.Terminal.Settings.Editor
-{
- [default_interface] runtimeclass ControlSizeTrigger : Windows.UI.Xaml.StateTriggerBase
- {
- ControlSizeTrigger();
-
- Boolean CanTrigger;
- static Windows.UI.Xaml.DependencyProperty CanTriggerProperty { get; };
-
- Double MinWidth;
- static Windows.UI.Xaml.DependencyProperty MinWidthProperty { get; };
-
- Double MaxWidth;
- static Windows.UI.Xaml.DependencyProperty MaxWidthProperty { get; };
-
- Double MinHeight;
- static Windows.UI.Xaml.DependencyProperty MinHeightProperty { get; };
-
- Double MaxHeight;
- static Windows.UI.Xaml.DependencyProperty MaxHeightProperty { get; };
-
- Windows.UI.Xaml.FrameworkElement TargetElement;
- static Windows.UI.Xaml.DependencyProperty TargetElementProperty { get; };
-
- Boolean IsActive { get; };
- }
-}
diff --git a/src/cascadia/TerminalSettingsEditor/CornerRadiusFilterConverters.cpp b/src/cascadia/TerminalSettingsEditor/CornerRadiusFilterConverters.cpp
deleted file mode 100644
index 0d9b9168b6..0000000000
--- a/src/cascadia/TerminalSettingsEditor/CornerRadiusFilterConverters.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT license.
-
-#include "pch.h"
-#include "CornerRadiusFilterConverters.h"
-#include "CornerRadiusConverter.g.cpp"
-#include "TopCornerRadiusFilterConverter.g.cpp"
-#include "BottomCornerRadiusFilterConverter.g.cpp"
-
-using namespace winrt::Windows::UI::Xaml;
-
-namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
-{
- winrt::Windows::Foundation::IInspectable CornerRadiusConverter::Convert(const winrt::Windows::Foundation::IInspectable& value, const Interop::TypeName& /*targetType*/, const winrt::Windows::Foundation::IInspectable& /*parameter*/, const hstring& /*language*/)
- {
- if (!value)
- {
- return value;
- }
- const auto cr = unbox_value_or(value, CornerRadius{ 0, 0, 0, 0 });
- return box_value(CornerRadius{ 0, 0, cr.BottomRight, cr.BottomLeft });
- }
-
- winrt::Windows::Foundation::IInspectable CornerRadiusConverter::ConvertBack(const winrt::Windows::Foundation::IInspectable& value, const Interop::TypeName& /*targetType*/, const winrt::Windows::Foundation::IInspectable& /*parameter*/, const hstring& /*language*/)
- {
- return value;
- }
-
- winrt::Windows::Foundation::IInspectable TopCornerRadiusFilterConverter::Convert(const winrt::Windows::Foundation::IInspectable& value, const Interop::TypeName& /*targetType*/, const winrt::Windows::Foundation::IInspectable& /*parameter*/, const hstring& /*language*/)
- {
- if (!value)
- {
- return value;
- }
- const auto cr = unbox_value_or(value, CornerRadius{ 0, 0, 0, 0 });
- return box_value(CornerRadius{ cr.TopLeft, cr.TopRight, 0, 0 });
- }
-
- winrt::Windows::Foundation::IInspectable TopCornerRadiusFilterConverter::ConvertBack(const winrt::Windows::Foundation::IInspectable& value, const Interop::TypeName& /*targetType*/, const winrt::Windows::Foundation::IInspectable& /*parameter*/, const hstring& /*language*/)
- {
- return value;
- }
-
- winrt::Windows::Foundation::IInspectable BottomCornerRadiusFilterConverter::Convert(const winrt::Windows::Foundation::IInspectable& value, const Interop::TypeName& /*targetType*/, const winrt::Windows::Foundation::IInspectable& /*parameter*/, const hstring& /*language*/)
- {
- if (!value)
- {
- return value;
- }
- const auto cr = unbox_value_or(value, CornerRadius{ 0, 0, 0, 0 });
- return box_value(CornerRadius{ 0, 0, cr.BottomRight, cr.BottomLeft });
- }
-
- winrt::Windows::Foundation::IInspectable BottomCornerRadiusFilterConverter::ConvertBack(const winrt::Windows::Foundation::IInspectable& value, const Interop::TypeName& /*targetType*/, const winrt::Windows::Foundation::IInspectable& /*parameter*/, const hstring& /*language*/)
- {
- return value;
- }
-}
diff --git a/src/cascadia/TerminalSettingsEditor/CornerRadiusFilterConverters.h b/src/cascadia/TerminalSettingsEditor/CornerRadiusFilterConverters.h
deleted file mode 100644
index bd7b9b01c1..0000000000
--- a/src/cascadia/TerminalSettingsEditor/CornerRadiusFilterConverters.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) Microsoft Corporation
-// Licensed under the MIT license.
-
-#pragma once
-
-#include "CornerRadiusConverter.g.h"
-#include "TopCornerRadiusFilterConverter.g.h"
-#include "BottomCornerRadiusFilterConverter.g.h"
-
-namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
-{
- struct CornerRadiusConverter : CornerRadiusConverterT
- {
- CornerRadiusConverter() = default;
-
- Windows::Foundation::IInspectable Convert(const Windows::Foundation::IInspectable& value, const Windows::UI::Xaml::Interop::TypeName& targetType, const Windows::Foundation::IInspectable& parameter, const hstring& language);
- Windows::Foundation::IInspectable ConvertBack(const Windows::Foundation::IInspectable& value, const Windows::UI::Xaml::Interop::TypeName& targetType, const Windows::Foundation::IInspectable& parameter, const hstring& language);
- };
-
- struct TopCornerRadiusFilterConverter : TopCornerRadiusFilterConverterT
- {
- TopCornerRadiusFilterConverter() = default;
-
- Windows::Foundation::IInspectable Convert(const Windows::Foundation::IInspectable& value, const Windows::UI::Xaml::Interop::TypeName& targetType, const Windows::Foundation::IInspectable& parameter, const hstring& language);
- Windows::Foundation::IInspectable ConvertBack(const Windows::Foundation::IInspectable& value, const Windows::UI::Xaml::Interop::TypeName& targetType, const Windows::Foundation::IInspectable& parameter, const hstring& language);
- };
-
- struct BottomCornerRadiusFilterConverter : BottomCornerRadiusFilterConverterT
- {
- BottomCornerRadiusFilterConverter() = default;
-
- Windows::Foundation::IInspectable Convert(const Windows::Foundation::IInspectable& value, const Windows::UI::Xaml::Interop::TypeName& targetType, const Windows::Foundation::IInspectable& parameter, const hstring& language);
- Windows::Foundation::IInspectable ConvertBack(const Windows::Foundation::IInspectable& value, const Windows::UI::Xaml::Interop::TypeName& targetType, const Windows::Foundation::IInspectable& parameter, const hstring& language);
- };
-}
-
-namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation
-{
- BASIC_FACTORY(CornerRadiusConverter);
- BASIC_FACTORY(TopCornerRadiusFilterConverter);
- BASIC_FACTORY(BottomCornerRadiusFilterConverter);
-}
diff --git a/src/cascadia/TerminalSettingsEditor/CornerRadiusFilterConverters.idl b/src/cascadia/TerminalSettingsEditor/CornerRadiusFilterConverters.idl
deleted file mode 100644
index 83b5a87a4c..0000000000
--- a/src/cascadia/TerminalSettingsEditor/CornerRadiusFilterConverters.idl
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT license.
-
-namespace Microsoft.Terminal.Settings.Editor
-{
- [default_interface] runtimeclass CornerRadiusConverter : Windows.UI.Xaml.Data.IValueConverter
- {
- CornerRadiusConverter();
- }
-
- [default_interface] runtimeclass TopCornerRadiusFilterConverter : Windows.UI.Xaml.Data.IValueConverter
- {
- TopCornerRadiusFilterConverter();
- }
-
- [default_interface] runtimeclass BottomCornerRadiusFilterConverter : Windows.UI.Xaml.Data.IValueConverter
- {
- BottomCornerRadiusFilterConverter();
- }
-}
diff --git a/src/cascadia/TerminalSettingsEditor/Extensions.xaml b/src/cascadia/TerminalSettingsEditor/Extensions.xaml
index 22d03d8832..c10a8fb145 100644
--- a/src/cascadia/TerminalSettingsEditor/Extensions.xaml
+++ b/src/cascadia/TerminalSettingsEditor/Extensions.xaml
@@ -201,7 +201,7 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 16
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/cascadia/TerminalSettingsEditor/SettingsCard.cpp b/src/cascadia/TerminalSettingsEditor/SettingsCard.cpp
index 333a31ff8c..43f90c05e8 100644
--- a/src/cascadia/TerminalSettingsEditor/SettingsCard.cpp
+++ b/src/cascadia/TerminalSettingsEditor/SettingsCard.cpp
@@ -5,7 +5,7 @@
#include "SettingsCard.h"
#include "SettingsCard.g.cpp"
#include "SettingsCardAutomationPeer.g.cpp"
-#include "StyleExtensions.h"
+#include "SettingsControlsHelpers.h"
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::System;
diff --git a/src/cascadia/TerminalSettingsEditor/SettingsControlsHelpers.cpp b/src/cascadia/TerminalSettingsEditor/SettingsControlsHelpers.cpp
new file mode 100644
index 0000000000..a0f40e0b46
--- /dev/null
+++ b/src/cascadia/TerminalSettingsEditor/SettingsControlsHelpers.cpp
@@ -0,0 +1,276 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "pch.h"
+#include "SettingsControlsHelpers.h"
+#include "ControlSizeTrigger.g.cpp"
+#include "TopCornerRadiusFilterConverter.g.cpp"
+#include "BottomCornerRadiusFilterConverter.g.cpp"
+#include "StringDefaultTemplateSelector.g.cpp"
+#include "StyleExtensions.g.cpp"
+
+#include
+
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::Foundation::Collections;
+using namespace winrt::Windows::UI::Xaml;
+
+namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
+{
+#pragma region ControlSizeTrigger
+
+ DependencyProperty ControlSizeTrigger::_CanTriggerProperty{ nullptr };
+ DependencyProperty ControlSizeTrigger::_MinWidthProperty{ nullptr };
+ DependencyProperty ControlSizeTrigger::_MaxWidthProperty{ nullptr };
+ DependencyProperty ControlSizeTrigger::_MinHeightProperty{ nullptr };
+ DependencyProperty ControlSizeTrigger::_MaxHeightProperty{ nullptr };
+ DependencyProperty ControlSizeTrigger::_TargetElementProperty{ nullptr };
+
+ ControlSizeTrigger::ControlSizeTrigger()
+ {
+ _InitializeProperties();
+ }
+
+ void ControlSizeTrigger::_InitializeProperties()
+ {
+ // Defaults mirror the toolkit: trigger is always evaluatable, bounds
+ // are wide open, no target element until one is bound.
+ if (!_CanTriggerProperty)
+ {
+ _CanTriggerProperty = DependencyProperty::Register(
+ L"CanTrigger",
+ xaml_typename(),
+ xaml_typename(),
+ PropertyMetadata{ box_value(true), PropertyChangedCallback{ &ControlSizeTrigger::_OnTriggerInputChanged } });
+ }
+ if (!_MinWidthProperty)
+ {
+ _MinWidthProperty = DependencyProperty::Register(
+ L"MinWidth",
+ xaml_typename(),
+ xaml_typename(),
+ PropertyMetadata{ box_value(0.0), PropertyChangedCallback{ &ControlSizeTrigger::_OnTriggerInputChanged } });
+ }
+ if (!_MaxWidthProperty)
+ {
+ _MaxWidthProperty = DependencyProperty::Register(
+ L"MaxWidth",
+ xaml_typename(),
+ xaml_typename(),
+ PropertyMetadata{ box_value(std::numeric_limits::infinity()), PropertyChangedCallback{ &ControlSizeTrigger::_OnTriggerInputChanged } });
+ }
+ if (!_MinHeightProperty)
+ {
+ _MinHeightProperty = DependencyProperty::Register(
+ L"MinHeight",
+ xaml_typename(),
+ xaml_typename(),
+ PropertyMetadata{ box_value(0.0), PropertyChangedCallback{ &ControlSizeTrigger::_OnTriggerInputChanged } });
+ }
+ if (!_MaxHeightProperty)
+ {
+ _MaxHeightProperty = DependencyProperty::Register(
+ L"MaxHeight",
+ xaml_typename(),
+ xaml_typename(),
+ PropertyMetadata{ box_value(std::numeric_limits::infinity()), PropertyChangedCallback{ &ControlSizeTrigger::_OnTriggerInputChanged } });
+ }
+ if (!_TargetElementProperty)
+ {
+ _TargetElementProperty = DependencyProperty::Register(
+ L"TargetElement",
+ xaml_typename(),
+ xaml_typename(),
+ PropertyMetadata{ nullptr, PropertyChangedCallback{ &ControlSizeTrigger::_OnTargetElementChanged } });
+ }
+ }
+
+ void ControlSizeTrigger::_OnTriggerInputChanged(const DependencyObject& d, const DependencyPropertyChangedEventArgs& /*e*/)
+ {
+ if (const auto obj{ d.try_as() })
+ {
+ get_self(obj)->_UpdateTrigger();
+ }
+ }
+
+ void ControlSizeTrigger::_OnTargetElementChanged(const DependencyObject& d, const DependencyPropertyChangedEventArgs& e)
+ {
+ const auto obj{ d.try_as() };
+ if (!obj)
+ {
+ return;
+ }
+ const auto oldElement = e.OldValue().try_as();
+ const auto newElement = e.NewValue().try_as();
+ get_self(obj)->_UpdateTargetElement(oldElement, newElement);
+ }
+
+ void ControlSizeTrigger::_UpdateTargetElement(const FrameworkElement& /*oldValue*/, const FrameworkElement& newValue)
+ {
+ // Revoking handles both unhooking the previous element and a null `newValue`.
+ _sizeChangedRevoker.revoke();
+ if (newValue)
+ {
+ _sizeChangedRevoker = newValue.SizeChanged(winrt::auto_revoke, [weakThis = get_weak()](auto&&, auto&&) {
+ if (const auto strongThis = weakThis.get())
+ {
+ strongThis->_UpdateTrigger();
+ }
+ });
+ }
+ _UpdateTrigger();
+ }
+
+ void ControlSizeTrigger::_UpdateTrigger()
+ {
+ const auto target = TargetElement();
+ if (!target || !CanTrigger())
+ {
+ _isActive = false;
+ SetActive(false);
+ return;
+ }
+
+ const auto width = target.ActualWidth();
+ const auto height = target.ActualHeight();
+
+ const bool activate =
+ MinWidth() <= width &&
+ width < MaxWidth() &&
+ MinHeight() <= height &&
+ height < MaxHeight();
+
+ _isActive = activate;
+ SetActive(activate);
+ }
+
+#pragma endregion
+#pragma region TopBottomCornerRadiusFilters
+
+ winrt::Windows::Foundation::IInspectable TopCornerRadiusFilterConverter::Convert(const winrt::Windows::Foundation::IInspectable& value, const Interop::TypeName& /*targetType*/, const winrt::Windows::Foundation::IInspectable& /*parameter*/, const hstring& /*language*/)
+ {
+ if (!value)
+ {
+ return value;
+ }
+ const auto cr = unbox_value_or(value, CornerRadius{ 0, 0, 0, 0 });
+ return box_value(CornerRadius{ cr.TopLeft, cr.TopRight, 0, 0 });
+ }
+
+ winrt::Windows::Foundation::IInspectable TopCornerRadiusFilterConverter::ConvertBack(const winrt::Windows::Foundation::IInspectable& value, const Interop::TypeName& /*targetType*/, const winrt::Windows::Foundation::IInspectable& /*parameter*/, const hstring& /*language*/)
+ {
+ return value;
+ }
+
+ winrt::Windows::Foundation::IInspectable BottomCornerRadiusFilterConverter::Convert(const winrt::Windows::Foundation::IInspectable& value, const Interop::TypeName& /*targetType*/, const winrt::Windows::Foundation::IInspectable& /*parameter*/, const hstring& /*language*/)
+ {
+ if (!value)
+ {
+ return value;
+ }
+ const auto cr = unbox_value_or(value, CornerRadius{ 0, 0, 0, 0 });
+ return box_value(CornerRadius{ 0, 0, cr.BottomRight, cr.BottomLeft });
+ }
+
+ winrt::Windows::Foundation::IInspectable BottomCornerRadiusFilterConverter::ConvertBack(const winrt::Windows::Foundation::IInspectable& value, const Interop::TypeName& /*targetType*/, const winrt::Windows::Foundation::IInspectable& /*parameter*/, const hstring& /*language*/)
+ {
+ return value;
+ }
+
+#pragma endregion
+#pragma region StringDefaultTemplateSelector
+
+ DataTemplate StringDefaultTemplateSelector::SelectTemplateCore(const IInspectable& item, const DependencyObject& /*container*/)
+ {
+ return SelectTemplateCore(item);
+ }
+
+ DataTemplate StringDefaultTemplateSelector::SelectTemplateCore(const IInspectable& item)
+ {
+ if (const auto pv{ item.try_as() }; pv && pv.Type() == PropertyType::String)
+ {
+ return _StringTemplate;
+ }
+ return nullptr;
+ }
+
+#pragma endregion
+#pragma region StyleExtensions
+
+ ResourceDictionary StyleExtensions::_sharedImplicitStylesDictionary{ nullptr };
+
+ // Lazy singleton: loads SettingsControlsImplicitStyles.xaml exactly once
+ // for the process lifetime. We do NOT append this dictionary itself to any
+ // element's MergedDictionaries — that triggers "Element is already the
+ // child of another element" once a second element tries to merge it.
+ // Instead, EnsureImplicitStylesMergedInto copies the dictionary's entries
+ // (Style references) into the target's own Resources. Style instances are
+ // reference types but not UIElements, so sharing them across multiple
+ // elements' Resources collections is safe.
+ ResourceDictionary StyleExtensions::_SharedImplicitStylesDictionary()
+ {
+ if (!_sharedImplicitStylesDictionary)
+ {
+ try
+ {
+ auto dict{ ResourceDictionary{} };
+ dict.Source(winrt::Windows::Foundation::Uri{ L"ms-appx:///Microsoft.Terminal.Settings.Editor/SettingsControlsImplicitStyles.xaml" });
+ _sharedImplicitStylesDictionary = dict;
+ }
+ CATCH_LOG();
+ }
+ return _sharedImplicitStylesDictionary;
+ }
+
+ void StyleExtensions::EnsureImplicitStylesMergedInto(const FrameworkElement& target)
+ {
+ if (!target)
+ {
+ return;
+ }
+
+ try
+ {
+ const auto resources{ target.Resources() };
+ if (!resources)
+ {
+ return;
+ }
+
+ // Idempotency marker: if we've already populated this element's
+ // Resources with the implicit styles, skip. Cheap to check
+ // (one hash lookup), independent of MergedDictionaries.
+ const auto markerKey{ box_value(hstring{ L"__SettingsControls_ImplicitStyles" }) };
+ if (resources.HasKey(markerKey))
+ {
+ return;
+ }
+
+ const auto sharedDict{ _SharedImplicitStylesDictionary() };
+ if (!sharedDict)
+ {
+ return;
+ }
+
+ // Copy each entry (Style or other resource) from the shared loaded
+ // dictionary into the target's Resources. Style instances are
+ // reference types that can safely be shared across multiple
+ // element Resources collections (unlike UIElements, which have a
+ // single-parent constraint). We deliberately do NOT
+ // MergedDictionaries.Append(sharedDict) — that path throws
+ // "Element is already the child of another element" once a second
+ // element tries to merge the same shared dict.
+ for (const auto& kv : sharedDict)
+ {
+ if (!resources.HasKey(kv.Key()))
+ {
+ resources.Insert(kv.Key(), kv.Value());
+ }
+ }
+ resources.Insert(markerKey, box_value(true));
+ }
+ CATCH_LOG();
+ }
+
+#pragma endregion
+}
diff --git a/src/cascadia/TerminalSettingsEditor/SettingsControlsHelpers.h b/src/cascadia/TerminalSettingsEditor/SettingsControlsHelpers.h
new file mode 100644
index 0000000000..2990f6f1c4
--- /dev/null
+++ b/src/cascadia/TerminalSettingsEditor/SettingsControlsHelpers.h
@@ -0,0 +1,100 @@
+/*++
+Copyright (c) Microsoft Corporation
+Licensed under the MIT license.
+
+Module Name:
+- SettingsControlsHelpers
+
+Abstract:
+- Helper types backing the Windows Community Toolkit port of SettingsCard/SettingsExpander.
+ Grouped into a single file so the port boundary is obvious.
+
+Author(s):
+- Carlos Zamora - June 2026
+
+--*/
+
+#pragma once
+
+#include "ControlSizeTrigger.g.h"
+#include "TopCornerRadiusFilterConverter.g.h"
+#include "BottomCornerRadiusFilterConverter.g.h"
+#include "StringDefaultTemplateSelector.g.h"
+#include "StyleExtensions.g.h"
+#include "Utils.h"
+
+namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
+{
+ struct ControlSizeTrigger : ControlSizeTriggerT
+ {
+ public:
+ ControlSizeTrigger();
+
+ bool IsActive() const { return _isActive; }
+
+ DEPENDENCY_PROPERTY(bool, CanTrigger);
+ DEPENDENCY_PROPERTY(double, MinWidth);
+ DEPENDENCY_PROPERTY(double, MaxWidth);
+ DEPENDENCY_PROPERTY(double, MinHeight);
+ DEPENDENCY_PROPERTY(double, MaxHeight);
+ DEPENDENCY_PROPERTY(Windows::UI::Xaml::FrameworkElement, TargetElement);
+
+ private:
+ static void _InitializeProperties();
+ static void _OnTriggerInputChanged(const Windows::UI::Xaml::DependencyObject& d, const Windows::UI::Xaml::DependencyPropertyChangedEventArgs& e);
+ static void _OnTargetElementChanged(const Windows::UI::Xaml::DependencyObject& d, const Windows::UI::Xaml::DependencyPropertyChangedEventArgs& e);
+
+ void _UpdateTargetElement(const Windows::UI::Xaml::FrameworkElement& oldValue, const Windows::UI::Xaml::FrameworkElement& newValue);
+ void _UpdateTrigger();
+
+ Windows::UI::Xaml::FrameworkElement::SizeChanged_revoker _sizeChangedRevoker;
+ bool _isActive{ false };
+ };
+
+ struct TopCornerRadiusFilterConverter : TopCornerRadiusFilterConverterT
+ {
+ TopCornerRadiusFilterConverter() = default;
+
+ Windows::Foundation::IInspectable Convert(const Windows::Foundation::IInspectable& value, const Windows::UI::Xaml::Interop::TypeName& targetType, const Windows::Foundation::IInspectable& parameter, const hstring& language);
+ Windows::Foundation::IInspectable ConvertBack(const Windows::Foundation::IInspectable& value, const Windows::UI::Xaml::Interop::TypeName& targetType, const Windows::Foundation::IInspectable& parameter, const hstring& language);
+ };
+
+ struct BottomCornerRadiusFilterConverter : BottomCornerRadiusFilterConverterT
+ {
+ BottomCornerRadiusFilterConverter() = default;
+
+ Windows::Foundation::IInspectable Convert(const Windows::Foundation::IInspectable& value, const Windows::UI::Xaml::Interop::TypeName& targetType, const Windows::Foundation::IInspectable& parameter, const hstring& language);
+ Windows::Foundation::IInspectable ConvertBack(const Windows::Foundation::IInspectable& value, const Windows::UI::Xaml::Interop::TypeName& targetType, const Windows::Foundation::IInspectable& parameter, const hstring& language);
+ };
+
+ struct StringDefaultTemplateSelector : StringDefaultTemplateSelectorT
+ {
+ StringDefaultTemplateSelector() = default;
+
+ Windows::UI::Xaml::DataTemplate SelectTemplateCore(const winrt::Windows::Foundation::IInspectable& item, const winrt::Windows::UI::Xaml::DependencyObject& container);
+ Windows::UI::Xaml::DataTemplate SelectTemplateCore(const winrt::Windows::Foundation::IInspectable& item);
+
+ WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, StringTemplate, nullptr);
+ };
+
+ struct StyleExtensions
+ {
+ StyleExtensions() = default;
+
+ static void EnsureImplicitStylesMergedInto(const Windows::UI::Xaml::FrameworkElement& target);
+
+ private:
+ static Windows::UI::Xaml::ResourceDictionary _SharedImplicitStylesDictionary();
+
+ static Windows::UI::Xaml::ResourceDictionary _sharedImplicitStylesDictionary;
+ };
+}
+
+namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation
+{
+ BASIC_FACTORY(ControlSizeTrigger);
+ BASIC_FACTORY(TopCornerRadiusFilterConverter);
+ BASIC_FACTORY(BottomCornerRadiusFilterConverter);
+ BASIC_FACTORY(StringDefaultTemplateSelector);
+ BASIC_FACTORY(StyleExtensions);
+}
diff --git a/src/cascadia/TerminalSettingsEditor/SettingsControlsHelpers.idl b/src/cascadia/TerminalSettingsEditor/SettingsControlsHelpers.idl
new file mode 100644
index 0000000000..5aa0306781
--- /dev/null
+++ b/src/cascadia/TerminalSettingsEditor/SettingsControlsHelpers.idl
@@ -0,0 +1,65 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+// Helper types backing the Windows Community Toolkit port of SettingsCard/SettingsExpander.
+// These are grouped together so the port boundary is obvious.
+namespace Microsoft.Terminal.Settings.Editor
+{
+ // A conditional state trigger that activates based on the size of a target
+ // FrameworkElement. Ported from CommunityToolkit.WinUI.ControlSizeTrigger.
+ [default_interface] runtimeclass ControlSizeTrigger : Windows.UI.Xaml.StateTriggerBase
+ {
+ ControlSizeTrigger();
+
+ Boolean CanTrigger;
+ static Windows.UI.Xaml.DependencyProperty CanTriggerProperty { get; };
+
+ Double MinWidth;
+ static Windows.UI.Xaml.DependencyProperty MinWidthProperty { get; };
+
+ Double MaxWidth;
+ static Windows.UI.Xaml.DependencyProperty MaxWidthProperty { get; };
+
+ Double MinHeight;
+ static Windows.UI.Xaml.DependencyProperty MinHeightProperty { get; };
+
+ Double MaxHeight;
+ static Windows.UI.Xaml.DependencyProperty MaxHeightProperty { get; };
+
+ Windows.UI.Xaml.FrameworkElement TargetElement;
+ static Windows.UI.Xaml.DependencyProperty TargetElementProperty { get; };
+
+ Boolean IsActive { get; };
+ }
+
+ // Filter a CornerRadius down to only its top/bottom corners. Used
+ // by the SettingsExpander template so the header and items panel visually
+ // stitch together with rounded outer corners only.
+ [default_interface] runtimeclass TopCornerRadiusFilterConverter : Windows.UI.Xaml.Data.IValueConverter
+ {
+ TopCornerRadiusFilterConverter();
+ }
+
+ [default_interface] runtimeclass BottomCornerRadiusFilterConverter : Windows.UI.Xaml.Data.IValueConverter
+ {
+ BottomCornerRadiusFilterConverter();
+ }
+
+ // Selects a template only when the bound item is a string. Used by
+ // SettingsCard/SettingsExpander to render string Header/Description content.
+ [default_interface] runtimeclass StringDefaultTemplateSelector : Windows.UI.Xaml.Controls.DataTemplateSelector
+ {
+ StringDefaultTemplateSelector();
+
+ Windows.UI.Xaml.DataTemplate StringTemplate;
+ }
+
+ // Injects the project's SettingsControlsImplicitStyles.xaml dictionary into a
+ // SettingsCard/SettingsExpander's Resources so children (e.g. ToggleSwitch)
+ // pick up card-appropriate defaults. Loaded from C++ rather than the WCT
+ // attached-property Setter pattern, which crashes WinUI 2 in this codebase.
+ static runtimeclass StyleExtensions
+ {
+ static void EnsureImplicitStylesMergedInto(Windows.UI.Xaml.FrameworkElement target);
+ }
+}
diff --git a/src/cascadia/TerminalSettingsEditor/SettingsControlsStyle.xaml b/src/cascadia/TerminalSettingsEditor/SettingsControlsStyle.xaml
index a57be63b3b..e2aedc41d7 100644
--- a/src/cascadia/TerminalSettingsEditor/SettingsControlsStyle.xaml
+++ b/src/cascadia/TerminalSettingsEditor/SettingsControlsStyle.xaml
@@ -161,7 +161,6 @@
-->
Show all settings
-
diff --git a/src/cascadia/TerminalSettingsEditor/SettingsExpander.cpp b/src/cascadia/TerminalSettingsEditor/SettingsExpander.cpp
index 1048a66b35..b9b16151d6 100644
--- a/src/cascadia/TerminalSettingsEditor/SettingsExpander.cpp
+++ b/src/cascadia/TerminalSettingsEditor/SettingsExpander.cpp
@@ -6,7 +6,7 @@
#include "SettingsExpander.g.cpp"
#include "SettingsExpanderAutomationPeer.g.cpp"
#include "SettingsExpanderItemStyleSelector.g.cpp"
-#include "StyleExtensions.h"
+#include "SettingsControlsHelpers.h"
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::Foundation::Collections;
diff --git a/src/cascadia/TerminalSettingsEditor/StringDefaultTemplateSelector.cpp b/src/cascadia/TerminalSettingsEditor/StringDefaultTemplateSelector.cpp
deleted file mode 100644
index 4c17b18f2f..0000000000
--- a/src/cascadia/TerminalSettingsEditor/StringDefaultTemplateSelector.cpp
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT license.
-
-#include "pch.h"
-#include "StringDefaultTemplateSelector.h"
-#include "StringDefaultTemplateSelector.g.cpp"
-
-using namespace winrt::Windows::Foundation;
-using namespace winrt::Windows::UI::Xaml;
-
-namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
-{
- DataTemplate StringDefaultTemplateSelector::SelectTemplateCore(const IInspectable& item, const DependencyObject& /*container*/)
- {
- return SelectTemplateCore(item);
- }
-
- DataTemplate StringDefaultTemplateSelector::SelectTemplateCore(const IInspectable& item)
- {
- if (const auto pv{ item.try_as() }; pv && pv.Type() == PropertyType::String)
- {
- return _StringTemplate;
- }
- return nullptr;
- }
-}
diff --git a/src/cascadia/TerminalSettingsEditor/StringDefaultTemplateSelector.h b/src/cascadia/TerminalSettingsEditor/StringDefaultTemplateSelector.h
deleted file mode 100644
index 56b7f4a355..0000000000
--- a/src/cascadia/TerminalSettingsEditor/StringDefaultTemplateSelector.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) Microsoft Corporation
-// Licensed under the MIT license.
-
-#pragma once
-
-#include "StringDefaultTemplateSelector.g.h"
-
-namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
-{
- struct StringDefaultTemplateSelector : StringDefaultTemplateSelectorT
- {
- StringDefaultTemplateSelector() = default;
-
- Windows::UI::Xaml::DataTemplate SelectTemplateCore(const winrt::Windows::Foundation::IInspectable& item, const winrt::Windows::UI::Xaml::DependencyObject& container);
- Windows::UI::Xaml::DataTemplate SelectTemplateCore(const winrt::Windows::Foundation::IInspectable& item);
-
- WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, StringTemplate, nullptr);
- };
-}
-
-namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation
-{
- BASIC_FACTORY(StringDefaultTemplateSelector);
-}
diff --git a/src/cascadia/TerminalSettingsEditor/StringDefaultTemplateSelector.idl b/src/cascadia/TerminalSettingsEditor/StringDefaultTemplateSelector.idl
deleted file mode 100644
index db8562d8ac..0000000000
--- a/src/cascadia/TerminalSettingsEditor/StringDefaultTemplateSelector.idl
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT license.
-
-namespace Microsoft.Terminal.Settings.Editor
-{
- [default_interface] runtimeclass StringDefaultTemplateSelector : Windows.UI.Xaml.Controls.DataTemplateSelector
- {
- StringDefaultTemplateSelector();
-
- Windows.UI.Xaml.DataTemplate StringTemplate;
- }
-}
diff --git a/src/cascadia/TerminalSettingsEditor/StyleExtensions.cpp b/src/cascadia/TerminalSettingsEditor/StyleExtensions.cpp
deleted file mode 100644
index 4a9bb2b876..0000000000
--- a/src/cascadia/TerminalSettingsEditor/StyleExtensions.cpp
+++ /dev/null
@@ -1,179 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT license.
-
-#include "pch.h"
-#include "StyleExtensions.h"
-#include "StyleExtensions.g.cpp"
-
-using namespace winrt::Windows::Foundation;
-using namespace winrt::Windows::Foundation::Collections;
-using namespace winrt::Windows::UI::Xaml;
-
-namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
-{
- DependencyProperty StyleExtensions::_resourcesProperty{ nullptr };
- ResourceDictionary StyleExtensions::_sharedImplicitStylesDictionary{ nullptr };
-
- DependencyProperty StyleExtensions::ResourcesProperty()
- {
- _InitializeProperties();
- return _resourcesProperty;
- }
-
- void StyleExtensions::_InitializeProperties()
- {
- if (!_resourcesProperty)
- {
- _resourcesProperty = DependencyProperty::RegisterAttached(
- L"Resources",
- xaml_typename(),
- xaml_typename(),
- PropertyMetadata{ nullptr, PropertyChangedCallback{ &StyleExtensions::_OnResourcesChanged } });
- }
- }
-
- ResourceDictionary StyleExtensions::GetResources(const DependencyObject& target)
- {
- return target.GetValue(ResourcesProperty()).try_as();
- }
-
- void StyleExtensions::SetResources(const DependencyObject& target, const ResourceDictionary& value)
- {
- target.SetValue(ResourcesProperty(), value);
- }
-
- void StyleExtensions::_OnResourcesChanged(const DependencyObject& d, const DependencyPropertyChangedEventArgs& e)
- {
- const auto frameworkElement{ d.try_as() };
- if (!frameworkElement)
- {
- return;
- }
-
- const auto elementResources{ frameworkElement.Resources() };
- if (!elementResources)
- {
- return;
- }
- const auto mergedDictionaries{ elementResources.MergedDictionaries() };
- if (!mergedDictionaries)
- {
- return;
- }
-
- // Remove the previously-merged dictionary (if any). Resource dictionaries
- // are reference types so IndexOf walks by identity, which is exactly what
- // we want: the same Setter.Value is shared across every element that uses
- // this Style, so the OldValue we see here is the exact instance we
- // appended last time the property changed.
- if (const auto oldDict{ e.OldValue().try_as() })
- {
- uint32_t index{ 0 };
- if (mergedDictionaries.IndexOf(oldDict, index))
- {
- mergedDictionaries.RemoveAt(index);
- }
- }
-
- // Add the new dictionary directly. We deliberately do NOT clone the way
- // the WCT C# port does: ResourceDictionary is sealed (so we can't tag a
- // private subclass like the toolkit), and a deep clone would have to
- // copy the inline dictionary's Source URI — which XAML may leave as a
- // relative string like "CommonResources.xaml" and which the runtime
- // then rejects with "is not a valid absolute URI". Sharing the same
- // dictionary across elements is fine: each element's MergedDictionaries
- // only holds a reference, and implicit styles are designed to be shared.
- if (const auto newDict{ e.NewValue().try_as() })
- {
- mergedDictionaries.Append(newDict);
-
- if (frameworkElement.IsLoaded())
- {
- _ForceControlToReloadThemeResources(frameworkElement);
- }
- }
- }
-
- void StyleExtensions::_ForceControlToReloadThemeResources(const FrameworkElement& element)
- {
- // Toggle RequestedTheme to force the framework to re-resolve all
- // {ThemeResource} bindings under this element. Required when the
- // style is applied to an already-loaded element. Matches the toolkit.
- const auto currentTheme{ element.RequestedTheme() };
- element.RequestedTheme(currentTheme == ElementTheme::Dark ? ElementTheme::Light : ElementTheme::Dark);
- element.RequestedTheme(currentTheme);
- }
-
- // Lazy singleton: loads SettingsControlsImplicitStyles.xaml exactly once
- // for the process lifetime. We do NOT append this dictionary itself to any
- // element's MergedDictionaries — that triggers "Element is already the
- // child of another element" once a second element tries to merge it.
- // Instead, EnsureImplicitStylesMergedInto copies the dictionary's entries
- // (Style references) into the target's own Resources. Style instances are
- // reference types but not UIElements, so sharing them across multiple
- // elements' Resources collections is safe.
- ResourceDictionary StyleExtensions::_SharedImplicitStylesDictionary()
- {
- if (!_sharedImplicitStylesDictionary)
- {
- try
- {
- auto dict{ ResourceDictionary{} };
- dict.Source(winrt::Windows::Foundation::Uri{ L"ms-appx:///Microsoft.Terminal.Settings.Editor/SettingsControlsImplicitStyles.xaml" });
- _sharedImplicitStylesDictionary = dict;
- }
- CATCH_LOG();
- }
- return _sharedImplicitStylesDictionary;
- }
-
- void StyleExtensions::EnsureImplicitStylesMergedInto(const FrameworkElement& target)
- {
- if (!target)
- {
- return;
- }
-
- try
- {
- const auto resources{ target.Resources() };
- if (!resources)
- {
- return;
- }
-
- // Idempotency marker: if we've already populated this element's
- // Resources with the implicit styles, skip. Cheap to check
- // (one hash lookup), independent of MergedDictionaries.
- const auto markerKey{ box_value(hstring{ L"__SettingsControls_ImplicitStyles" }) };
- if (resources.HasKey(markerKey))
- {
- return;
- }
-
- const auto sharedDict{ _SharedImplicitStylesDictionary() };
- if (!sharedDict)
- {
- return;
- }
-
- // Copy each entry (Style or other resource) from the shared loaded
- // dictionary into the target's Resources. Style instances are
- // reference types that can safely be shared across multiple
- // element Resources collections (unlike UIElements, which have a
- // single-parent constraint). We deliberately do NOT
- // MergedDictionaries.Append(sharedDict) — that path throws
- // "Element is already the child of another element" once a second
- // element tries to merge the same shared dict.
- for (const auto& kv : sharedDict)
- {
- if (!resources.HasKey(kv.Key()))
- {
- resources.Insert(kv.Key(), kv.Value());
- }
- }
- resources.Insert(markerKey, box_value(true));
- }
- CATCH_LOG();
- }
-}
diff --git a/src/cascadia/TerminalSettingsEditor/StyleExtensions.h b/src/cascadia/TerminalSettingsEditor/StyleExtensions.h
deleted file mode 100644
index 764d93d7ce..0000000000
--- a/src/cascadia/TerminalSettingsEditor/StyleExtensions.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (c) Microsoft Corporation
-// Licensed under the MIT license.
-
-#pragma once
-
-#include "StyleExtensions.g.h"
-
-namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
-{
- struct StyleExtensions
- {
- StyleExtensions() = default;
-
- static Windows::UI::Xaml::DependencyProperty ResourcesProperty();
-
- static Windows::UI::Xaml::ResourceDictionary GetResources(const Windows::UI::Xaml::DependencyObject& target);
- static void SetResources(const Windows::UI::Xaml::DependencyObject& target, const Windows::UI::Xaml::ResourceDictionary& value);
-
- static void EnsureImplicitStylesMergedInto(const Windows::UI::Xaml::FrameworkElement& target);
-
- private:
- static void _InitializeProperties();
- static void _OnResourcesChanged(const Windows::UI::Xaml::DependencyObject& d, const Windows::UI::Xaml::DependencyPropertyChangedEventArgs& e);
- static void _ForceControlToReloadThemeResources(const Windows::UI::Xaml::FrameworkElement& element);
- static Windows::UI::Xaml::ResourceDictionary _SharedImplicitStylesDictionary();
-
- static Windows::UI::Xaml::DependencyProperty _resourcesProperty;
- static Windows::UI::Xaml::ResourceDictionary _sharedImplicitStylesDictionary;
- };
-}
-
-namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation
-{
- BASIC_FACTORY(StyleExtensions);
-}
diff --git a/src/cascadia/TerminalSettingsEditor/StyleExtensions.idl b/src/cascadia/TerminalSettingsEditor/StyleExtensions.idl
deleted file mode 100644
index 716151816e..0000000000
--- a/src/cascadia/TerminalSettingsEditor/StyleExtensions.idl
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT license.
-
-namespace Microsoft.Terminal.Settings.Editor
-{
- // Attached property that lets a Style merge an extra ResourceDictionary into
- // the target FrameworkElement's Resources.MergedDictionaries. Used by
- // SettingsCard / SettingsExpander to inject right-aligned ToggleSwitch and
- // sized Slider / ComboBox / TextBox defaults so children laid out inside a
- // card look right out of the box. Mirrors the Windows Community Toolkit's
- // CommunityToolkit.WinUI.Controls.StyleExtensions.
- static runtimeclass StyleExtensions
- {
- static Windows.UI.Xaml.DependencyProperty ResourcesProperty { get; };
-
- static Windows.UI.Xaml.ResourceDictionary GetResources(Windows.UI.Xaml.DependencyObject target);
- static void SetResources(Windows.UI.Xaml.DependencyObject target, Windows.UI.Xaml.ResourceDictionary value);
-
- // Idempotently merges the project's SettingsControlsImplicitStyles.xaml
- // dictionary into the target's Resources.MergedDictionaries. Called from
- // SettingsCard / SettingsExpander OnApplyTemplate to give children
- // (ToggleSwitch / Slider / ComboBox / TextBox) sensible Windows 11
- // defaults without each call site setting Style explicitly. Loaded from
- // C++ rather than via the attached DP because the WCT Setter.Value
- // pattern crashes WinUI 2 in this codebase.
- static void EnsureImplicitStylesMergedInto(Windows.UI.Xaml.FrameworkElement target);
- }
-}
diff --git a/tools/GenerateSettingsIndex.ps1 b/tools/GenerateSettingsIndex.ps1
index 136f8e95d8..8e43134f36 100644
--- a/tools/GenerateSettingsIndex.ps1
+++ b/tools/GenerateSettingsIndex.ps1
@@ -210,7 +210,7 @@ foreach ($xamlFile in Get-ChildItem -Path $SourceDir -Filter *.xaml)
}
# Extract Name via GetAttribute to avoid PowerShell's XML integration
- # returning the element name (e.g. "local:SettingContainer") when x:Name is absent.
+ # returning the element name (e.g. "local:SettingsCard") when x:Name is absent.
$name = $settingContainer.GetAttribute("x:Name")
if ([string]::IsNullOrEmpty($name))
{