diff --git a/idl/AngelUmbrella.idl b/idl/AngelUmbrella.idl index c6f975f..0437e82 100644 --- a/idl/AngelUmbrella.idl +++ b/idl/AngelUmbrella.idl @@ -208,6 +208,19 @@ namespace Mntone.AngelUmbrella [noexcept] static Microsoft.UI.Xaml.DependencyProperty TargetElementProperty { get; }; } + [interface_name("IControlWidthTrigger", C5562E80-F6FF-4870-902C-2628222E8AF5)] + [static_name("IControlWidthTriggerStatics", 9A821004-971E-445A-B6E5-8A92D032B537)] + runtimeclass ControlWidthTrigger : Microsoft.UI.Xaml.StateTriggerBase + { + ControlWidthTrigger(); + + Double MinWidth; + Microsoft.UI.Xaml.FrameworkElement TargetElement; + + [noexcept] static Microsoft.UI.Xaml.DependencyProperty MinWidthProperty { get; }; + [noexcept] static Microsoft.UI.Xaml.DependencyProperty TargetElementProperty { get; }; + } + } } diff --git a/samples/ControlSizeTriggerPage.xaml b/samples/ControlSizeTriggerPage.xaml index 7723de3..8fb3ef6 100644 --- a/samples/ControlSizeTriggerPage.xaml +++ b/samples/ControlSizeTriggerPage.xaml @@ -7,6 +7,11 @@ mc:Ignorable="d"> + + + + + @@ -25,10 +30,43 @@ Value="Orange" /> + + + + + + + + + + + + + + + + + + + + + + + @@ -36,10 +74,28 @@ - + + + + + + + + + + + diff --git a/samples/SettingsWindow.xaml b/samples/SettingsWindow.xaml index a9fdcbc..92fc250 100644 --- a/samples/SettingsWindow.xaml +++ b/samples/SettingsWindow.xaml @@ -32,6 +32,7 @@ 0 0,48,0,0 + 0,0,0,0 + @@ -212,6 +213,8 @@ + + diff --git a/src/Triggers/ControlWidthTrigger.cpp b/src/Triggers/ControlWidthTrigger.cpp new file mode 100644 index 0000000..aea685f --- /dev/null +++ b/src/Triggers/ControlWidthTrigger.cpp @@ -0,0 +1,65 @@ +#include "pch.h" +#include "ControlWidthTrigger.h" + +namespace winrt { + using namespace ::winrt::Windows::Foundation; + + using namespace ::winrt::Microsoft::UI::Xaml; + using namespace ::winrt::Microsoft::UI::Xaml::Controls; + + using namespace ::winrt::Mntone::AngelUmbrella::Triggers; +} + +using namespace winrt::Mntone::AngelUmbrella::Triggers::implementation; + +ControlWidthTrigger::ControlWidthTrigger(): width_(0.f) { + props_.DelayInitIfNeeded(); +} + +void ControlWidthTrigger::UpdateTrigger(double minWidth) const { + bool active { false }; + if (TargetElement()) { + if (minWidth >= 0.0) { + active = width_ >= minWidth; + } + } + SetActive(active); +} + +void ControlWidthTrigger::OnTargetElementSizeChanged(IInspectable const& /*sender*/, SizeChangedEventArgs const& args) { + Size newSize { args.NewSize() }; + + double minWidth { MinWidth() }; + if (minWidth >= 0.0) { + if (width_ != newSize.Width) { + width_ = newSize.Width; + UpdateTrigger(minWidth); + } + } +} + +void ControlWidthTrigger::OnMinWidthChanged(double newValue) const { + UpdateTrigger(newValue); +} + +void ControlWidthTrigger::OnTargetElementChanged(Microsoft::UI::Xaml::FrameworkElement const& newValue) { + revoker_.revoke(); + + UpdateTrigger(MinWidth()); + + if (newValue) { + revoker_ = newValue.SizeChanged(auto_revoke, SizeChangedEventHandler(this, &ControlWidthTrigger::OnTargetElementSizeChanged)); + } +} + +void ControlWidthTrigger::OnMinWidthChangedStatic(DependencyObject const& sender, DependencyPropertyChangedEventArgs const& args) { + double oldValue { args.OldValue().as() }; + double newValue { args.NewValue().as() }; + if (oldValue >= 0.0 || newValue >= 0.0) { + get_self(sender.as())->OnMinWidthChanged(newValue); + } +} + +void ControlWidthTrigger::OnTargetElementChangedStatic(DependencyObject const& sender, DependencyPropertyChangedEventArgs const& args) { + get_self(sender.as())->OnTargetElementChanged(args.NewValue().as()); +} diff --git a/src/Triggers/ControlWidthTrigger.h b/src/Triggers/ControlWidthTrigger.h new file mode 100644 index 0000000..ea56f6f --- /dev/null +++ b/src/Triggers/ControlWidthTrigger.h @@ -0,0 +1,52 @@ +#pragma once +#include "Triggers/ControlWidthTrigger.g.h" + +namespace winrt::Mntone::AngelUmbrella::Triggers::implementation { + + struct ControlWidthTrigger: ControlWidthTriggerT { + ControlWidthTrigger(); + + private: + inline void UpdateTrigger(double minWidth) const; + + private: + void OnTargetElementSizeChanged(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::SizeChangedEventArgs const& args); + + inline void OnMinWidthChanged(double newValue) const; + inline void OnTargetElementChanged(Microsoft::UI::Xaml::FrameworkElement const& newValue); + + static void OnMinWidthChangedStatic(Microsoft::UI::Xaml::DependencyObject const& sender, Microsoft::UI::Xaml::DependencyPropertyChangedEventArgs const& args); + static void OnTargetElementChangedStatic(Microsoft::UI::Xaml::DependencyObject const& sender, Microsoft::UI::Xaml::DependencyPropertyChangedEventArgs const& args); + + public: // - Properties + inline double MinWidth() const { return GetValue(props_.MinWidth).as(); } + inline void MinWidth(double value) const { SetValue(props_.MinWidth, box_value(value)); } + + inline Microsoft::UI::Xaml::FrameworkElement TargetElement() const { return GetValue(props_.TargetElement).as(); } + inline void TargetElement(Microsoft::UI::Xaml::FrameworkElement const& value) const { SetValue(props_.TargetElement, value); } + + inline static Microsoft::UI::Xaml::DependencyProperty MinWidthProperty() noexcept { return props_.MinWidth; } + inline static Microsoft::UI::Xaml::DependencyProperty TargetElementProperty() noexcept { return props_.TargetElement; } + + private: // - Variables + float width_; + Microsoft::UI::Xaml::FrameworkElement::SizeChanged_revoker revoker_; + + struct DependencyProperties final { + void DelayInitIfNeeded(); + + bool initialized_ { false }; + Microsoft::UI::Xaml::DependencyProperty MinWidth { nullptr }; + Microsoft::UI::Xaml::DependencyProperty TargetElement { nullptr }; + }; + static DependencyProperties props_; + }; + +} + +namespace winrt::Mntone::AngelUmbrella::Triggers::factory_implementation { + + struct ControlWidthTrigger: ControlWidthTriggerT { + }; + +} diff --git a/src/Triggers/ControlWidthTrigger.properties.cpp b/src/Triggers/ControlWidthTrigger.properties.cpp new file mode 100644 index 0000000..edfab6b --- /dev/null +++ b/src/Triggers/ControlWidthTrigger.properties.cpp @@ -0,0 +1,38 @@ +#include "pch.h" +#include "ControlWidthTrigger.h" +#if __has_include("Triggers/ControlWidthTrigger.g.cpp") +#include "Triggers/ControlWidthTrigger.g.cpp" +#endif + +#define DELAY_INIT_DP // Delay Init +#include "Helpers/DependencyPropertyHelper.h" + +namespace projection { // Need to build + using namespace ::winrt::Mntone::AngelUmbrella::Triggers; +} + +using namespace ::winrt::Mntone::AngelUmbrella::Triggers::implementation; + +ControlWidthTrigger::DependencyProperties ControlWidthTrigger::props_; + +void ControlWidthTrigger::DependencyProperties::DelayInitIfNeeded() { + if (initialized_) return; + + DEFINE_PARENT_TYPENAME(ControlWidthTrigger); + + DEFINE_DP_METADATA( + MinWidth, + double, + ControlWidthTrigger, + PropertyMetadata( + box_value(-1.0), + &ControlWidthTrigger::OnMinWidthChangedStatic)); + + DEFINE_DP_CALLBACK( + TargetElement, + Microsoft::UI::Xaml::FrameworkElement, + ControlWidthTrigger, + &ControlWidthTrigger::OnTargetElementChangedStatic); + + initialized_ = true; +}