Skip to content

Commit

Permalink
Adds ControlWidthTrigger.
Browse files Browse the repository at this point in the history
  • Loading branch information
mntone committed Jan 26, 2023
1 parent 5586ad3 commit e1d3db1
Show file tree
Hide file tree
Showing 7 changed files with 232 additions and 4 deletions.
13 changes: 13 additions & 0 deletions idl/AngelUmbrella.idl
Original file line number Diff line number Diff line change
Expand Up @@ -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; };
}

}

}
64 changes: 60 additions & 4 deletions samples/ControlSizeTriggerPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
mc:Ignorable="d">

<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>

<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="LayoutVisualStates">
<VisualState x:Name="WideLayout">
Expand All @@ -25,21 +30,72 @@
Value="Orange" />
<Setter Target="ContentElement.FontSize"
Value="24" />
<Setter Target="ContentElement.FontWeight"
Value="Bold" />
<Setter Target="ContentElement.Foreground"
Value="White" />
<Setter Target="ContentElement.Text"
Value="Less than 641" />
<Setter Target="DescriptionElement.Foreground"
Value="White" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>

<VisualStateGroup x:Name="LayoutVisualStates2">
<VisualState x:Name="WideLayout2">
<VisualState.StateTriggers>
<angel:ControlWidthTrigger TargetElement="{x:Bind TargetElement}"
MinWidth="601" />
</VisualState.StateTriggers>
</VisualState>
<VisualState x:Name="NarrowLayout2">
<VisualState.StateTriggers>
<angel:ControlWidthTrigger TargetElement="{x:Bind TargetElement}"
MinWidth="0" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="TargetElement2.Background"
Value="DarkGreen" />
<Setter Target="ContentElement2.FontSize"
Value="24" />
<Setter Target="ContentElement2.FontWeight"
Value="Bold" />
<Setter Target="ContentElement2.Foreground"
Value="White" />
<Setter Target="ContentElement2.Text"
Value="Less than 601" />
<Setter Target="DescriptionElement2.Foreground"
Value="White" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>

<Border x:Name="TargetElement"
Background="AntiqueWhite">
<TextBlock x:Name="ContentElement"
HorizontalAlignment="Center"
Text="Equal to or Greater than 641"
VerticalAlignment="Center" />
<StackPanel VerticalAlignment="Center">
<TextBlock x:Name="ContentElement"
HorizontalAlignment="Center"
Text="Equal to or Greater than 641"
VerticalAlignment="Center" />
<TextBlock x:Name="DescriptionElement"
HorizontalAlignment="Center"
Text="(ControlSizeTrigger)" />
</StackPanel>
</Border>

<Border x:Name="TargetElement2"
Grid.Row="1"
Background="Aquamarine">
<StackPanel VerticalAlignment="Center">
<TextBlock x:Name="ContentElement2"
HorizontalAlignment="Center"
Text="Equal to or Greater than 601" />
<TextBlock x:Name="DescriptionElement2"
HorizontalAlignment="Center"
Text="(ControlWidthTrigger - width only)" />
</StackPanel>
</Border>
</Grid>
</Page>
1 change: 1 addition & 0 deletions samples/SettingsWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
<NavigationView.Resources>
<Thickness x:Key="NavigationViewContentGridBorderThickness">0</Thickness>
<Thickness x:Key="NavigationViewContentMargin">0,48,0,0</Thickness>
<CornerRadius x:Key="NavigationViewContentGridCornerRadius">0,0,0,0</CornerRadius>
<SolidColorBrush x:Key="NavigationViewContentBackground"
Color="Transparent" />
<SolidColorBrush x:Key="NavigationViewContentGridBorderBrush"
Expand Down
3 changes: 3 additions & 0 deletions src/AngelUmbrella.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@
<ClInclude Include="Helpers\XamlHelpers.h" />
<ClInclude Include="Navigation\NavigationProperties.h" />
<ClInclude Include="Triggers\ControlSizeTrigger.h" />
<ClInclude Include="Triggers\ControlWidthTrigger.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp">
Expand Down Expand Up @@ -212,6 +213,8 @@
<ClCompile Include="Navigation\NavigationProperties.cpp" />
<ClCompile Include="Triggers\ControlSizeTrigger.cpp" />
<ClCompile Include="Triggers\ControlSizeTrigger.properties.cpp" />
<ClCompile Include="Triggers\ControlWidthTrigger.cpp" />
<ClCompile Include="Triggers\ControlWidthTrigger.properties.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
Expand Down
65 changes: 65 additions & 0 deletions src/Triggers/ControlWidthTrigger.cpp
Original file line number Diff line number Diff line change
@@ -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>() };
double newValue { args.NewValue().as<double>() };
if (oldValue >= 0.0 || newValue >= 0.0) {
get_self<ControlWidthTrigger>(sender.as<winrt::ControlWidthTrigger>())->OnMinWidthChanged(newValue);
}
}

void ControlWidthTrigger::OnTargetElementChangedStatic(DependencyObject const& sender, DependencyPropertyChangedEventArgs const& args) {
get_self<ControlWidthTrigger>(sender.as<winrt::ControlWidthTrigger>())->OnTargetElementChanged(args.NewValue().as<FrameworkElement>());
}
52 changes: 52 additions & 0 deletions src/Triggers/ControlWidthTrigger.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#pragma once
#include "Triggers/ControlWidthTrigger.g.h"

namespace winrt::Mntone::AngelUmbrella::Triggers::implementation {

struct ControlWidthTrigger: ControlWidthTriggerT<ControlWidthTrigger> {
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<double>(); }
inline void MinWidth(double value) const { SetValue(props_.MinWidth, box_value(value)); }

inline Microsoft::UI::Xaml::FrameworkElement TargetElement() const { return GetValue(props_.TargetElement).as<Microsoft::UI::Xaml::FrameworkElement>(); }
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<ControlWidthTrigger, implementation::ControlWidthTrigger> {
};

}
38 changes: 38 additions & 0 deletions src/Triggers/ControlWidthTrigger.properties.cpp
Original file line number Diff line number Diff line change
@@ -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;
}

0 comments on commit e1d3db1

Please sign in to comment.