Skip to content

Commit

Permalink
Add a MirroredWhenRightToLeft API to AnimatedIcon (#5023)
Browse files Browse the repository at this point in the history
* Add a MirroredWhenRightToLeft API

* Use RenderTransformOrigin instead of scale transform center

* Add api to AnimatedIconSource, add test page support, and changed the NavigationViewBackButton to mirror.

* add API test
  • Loading branch information
StephenLPeters authored May 21, 2021
1 parent a43a2ab commit f4d781d
Show file tree
Hide file tree
Showing 16 changed files with 184 additions and 22 deletions.
36 changes: 36 additions & 0 deletions dev/AnimatedIcon/AnimatedIcon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ AnimatedIcon::AnimatedIcon()
Loaded({ this, &AnimatedIcon::OnLoaded });

RegisterPropertyChangedCallback(winrt::IconElement::ForegroundProperty(), { this, &AnimatedIcon::OnForegroundPropertyChanged});
RegisterPropertyChangedCallback(winrt::FrameworkElement::FlowDirectionProperty(), { this, &AnimatedIcon::OnFlowDirectionPropertyChanged });
}

void AnimatedIcon::OnApplyTemplate()
Expand Down Expand Up @@ -96,6 +97,7 @@ void AnimatedIcon::OnLoaded(winrt::IInspectable const&, winrt::RoutedEventArgs c
OnFallbackIconSourcePropertyChanged(nullptr);
}


winrt::Size AnimatedIcon::MeasureOverride(winrt::Size const& availableSize)
{
if (auto const visual = m_animatedVisual.get())
Expand Down Expand Up @@ -444,6 +446,33 @@ void AnimatedIcon::OnSourcePropertyChanged(const winrt::DependencyPropertyChange
}
}

void AnimatedIcon::UpdateMirrorTransform()
{
auto const scaleTransform = [this]()
{
if (!m_scaleTransform)
{
// Initialize the scale transform that will be used for mirroring and the
// render transform origin as center in order to have the icon mirrored in place.
winrt::Windows::UI::Xaml::Media::ScaleTransform scaleTransform;

RenderTransform(scaleTransform);
RenderTransformOrigin({ 0.5, 0.5 });
m_scaleTransform.set(scaleTransform);
return scaleTransform;
}
return m_scaleTransform.get();
}();


scaleTransform.ScaleX(FlowDirection() == winrt::FlowDirection::RightToLeft && !MirroredWhenRightToLeft() && m_canDisplayPrimaryContent ? -1.0f : 1.0f);
}

void AnimatedIcon::OnMirroredWhenRightToLeftPropertyChanged(const winrt::DependencyPropertyChangedEventArgs&)
{
UpdateMirrorTransform();
}

bool AnimatedIcon::ConstructAndInsertVisual()
{
auto const visual = [this]()
Expand Down Expand Up @@ -497,6 +526,8 @@ bool AnimatedIcon::ConstructAndInsertVisual()
m_canDisplayPrimaryContent = false;
return false;
}

UpdateMirrorTransform();
}

void AnimatedIcon::OnFallbackIconSourcePropertyChanged(const winrt::DependencyPropertyChangedEventArgs&)
Expand Down Expand Up @@ -535,6 +566,11 @@ void AnimatedIcon::OnForegroundPropertyChanged(const winrt::DependencyObject& se
}
}

void AnimatedIcon::OnFlowDirectionPropertyChanged(const winrt::DependencyObject& sender, const winrt::DependencyProperty& args)
{
UpdateMirrorTransform();
}

void AnimatedIcon::OnForegroundBrushColorPropertyChanged(const winrt::DependencyObject& sender, const winrt::DependencyProperty& args)
{
TrySetForegroundProperty(sender.GetValue(args).as<winrt::Color>());
Expand Down
8 changes: 6 additions & 2 deletions dev/AnimatedIcon/AnimatedIcon.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ class AnimatedIcon :
winrt::Size MeasureOverride(winrt::Size const& availableSize);
winrt::Size ArrangeOverride(winrt::Size const& finalSize);

void OnSourcePropertyChanged(const winrt::DependencyPropertyChangedEventArgs& args);
void OnFallbackIconSourcePropertyChanged(const winrt::DependencyPropertyChangedEventArgs& args);
void OnSourcePropertyChanged(const winrt::DependencyPropertyChangedEventArgs&);
void OnFallbackIconSourcePropertyChanged(const winrt::DependencyPropertyChangedEventArgs&);
void OnMirroredWhenRightToLeftPropertyChanged(const winrt::DependencyPropertyChangedEventArgs&);
static void OnAnimatedIconStatePropertyChanged(
const winrt::DependencyObject& sender,
const winrt::DependencyPropertyChangedEventArgs& args);
Expand All @@ -55,11 +56,14 @@ class AnimatedIcon :
void TrySetForegroundProperty(winrt::IAnimatedVisualSource2 const& source = nullptr);
void OnAnimationCompleted(winrt::IInspectable const&, winrt::CompositionBatchCompletedEventArgs const&);
void OnForegroundPropertyChanged(const winrt::DependencyObject& sender, const winrt::DependencyProperty& args);
void OnFlowDirectionPropertyChanged(const winrt::DependencyObject& sender, const winrt::DependencyProperty& args);
void OnForegroundBrushColorPropertyChanged(const winrt::DependencyObject& sender, const winrt::DependencyProperty& args);
void SetRootPanelChildToFallbackIcon();
void UpdateMirrorTransform();

tracker_ref<winrt::IAnimatedVisual> m_animatedVisual{ this };
tracker_ref<winrt::Panel> m_rootPanel{ this };
tracker_ref<winrt::Windows::UI::Xaml::Media::ScaleTransform> m_scaleTransform{ this };

winrt::hstring m_currentState{ L"" };
winrt::hstring m_previousState{ L"" };
Expand Down
4 changes: 4 additions & 0 deletions dev/AnimatedIcon/AnimatedIcon.idl
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,17 @@ unsealed runtimeclass AnimatedIcon : Windows.UI.Xaml.Controls.IconElement
[MUX_PROPERTY_CHANGED_CALLBACK(TRUE)]
IconSource FallbackIconSource{ get; set; };

[MUX_PROPERTY_CHANGED_CALLBACK(TRUE)]
Boolean MirroredWhenRightToLeft{ get; set; };

[MUX_PROPERTY_CHANGED_CALLBACK_METHODNAME("OnAnimatedIconStatePropertyChanged")]
static Windows.UI.Xaml.DependencyProperty StateProperty{ get; };
static void SetState(Windows.UI.Xaml.DependencyObject object, String value);
static String GetState(Windows.UI.Xaml.DependencyObject object);

static Windows.UI.Xaml.DependencyProperty SourceProperty{ get; };
static Windows.UI.Xaml.DependencyProperty FallbackIconSourceProperty{ get; };
static Windows.UI.Xaml.DependencyProperty MirroredWhenRightToLeftProperty{ get; };
}

}
16 changes: 1 addition & 15 deletions dev/AnimatedIcon/TestUI/AnimatedIconHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,21 +96,7 @@ private void IconSourceChanged()
{
if (m_iconPresenter != null)
{
AnimatedIcon animatedIcon = new AnimatedIcon();
AnimatedIconSource source = (AnimatedIconSource)IconSource;
if (source.Source != null)
{
animatedIcon.Source = source.Source;
}
if (source.FallbackIconSource != null)
{
animatedIcon.FallbackIconSource = source.FallbackIconSource;
}
if (source.Foreground != null)
{
animatedIcon.Foreground = source.Foreground;
}
m_iconPresenter.Child = animatedIcon;
m_iconPresenter.Child = IconSource.CreateIconElement();
}
}
}
Expand Down
17 changes: 13 additions & 4 deletions dev/AnimatedIcon/TestUI/AnimatedIconPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock HorizontalAlignment="Center" Text="Animation Duration Multiplier" Grid.Row="0"/>
Expand All @@ -168,7 +169,8 @@
</Flyout>
</Button.Flyout>
</Button>
<ScrollViewer Grid.Row="6">
<CheckBox Content="Is LeftToRight" IsChecked="True" Checked="IsLeftToRightChecked" Unchecked="IsLeftToRightUnchecked" HorizontalAlignment="Center" Grid.Row="6"/>
<ScrollViewer Grid.Row="7">
<StackPanel>
<StackPanel Orientation="Horizontal" Windows10FallCreatorsUpdate:Spacing="5">
<StackPanel>
Expand Down Expand Up @@ -441,7 +443,7 @@
<StackPanel>
<local:AnimatedIconHost x:Name="BackIcon_Cut" Title="AnimatedBackVisualSource" Background="DarkSlateGray" Foreground="{Binding ElementName=ForegoundColorPicker, Path=Color, Converter={StaticResource ColorToSolidColorBrushConverter}}">
<local:AnimatedIconHost.IconSource>
<controls:AnimatedIconSource>
<controls:AnimatedIconSource MirroredWhenRightToLeft="True">
<controls:AnimatedIconSource.Source>
<animatedvisuals:AnimatedBackVisualSource/>
</controls:AnimatedIconSource.Source>
Expand All @@ -458,7 +460,7 @@
<StackPanel>
<local:AnimatedIconHost x:Name="BackIcon_Queue" Title="AnimatedBackVisualSource" Background="DarkSlateGray" Foreground="{Binding ElementName=ForegoundColorPicker, Path=Color, Converter={StaticResource ColorToSolidColorBrushConverter}}">
<local:AnimatedIconHost.IconSource>
<controls:AnimatedIconSource>
<controls:AnimatedIconSource MirroredWhenRightToLeft="True">
<controls:AnimatedIconSource.Source>
<animatedvisuals:AnimatedBackVisualSource/>
</controls:AnimatedIconSource.Source>
Expand All @@ -475,7 +477,7 @@
<StackPanel>
<local:AnimatedIconHost x:Name="BackIcon_SpeedUpQueue" Title="AnimatedBackVisualSource" Background="DarkSlateGray" Foreground="{Binding ElementName=ForegoundColorPicker, Path=Color, Converter={StaticResource ColorToSolidColorBrushConverter}}">
<local:AnimatedIconHost.IconSource>
<controls:AnimatedIconSource>
<controls:AnimatedIconSource MirroredWhenRightToLeft="True">
<controls:AnimatedIconSource.Source>
<animatedvisuals:AnimatedBackVisualSource/>
</controls:AnimatedIconSource.Source>
Expand Down Expand Up @@ -590,6 +592,13 @@
</controls:AnimatedIcon.FallbackIconSource>
</controls:AnimatedIcon>
</StackPanel>
<StackPanel Background="DarkGreen">
<controls:AnimatedIcon Height="100" Width="100" Foreground="Pink" MirroredWhenRightToLeft="True">
<controls:AnimatedIcon.Source>
<animatedvisuals:AnimatedBackVisualSource/>
</controls:AnimatedIcon.Source>
</controls:AnimatedIcon>
</StackPanel>
</StackPanel>
</StackPanel>
</ScrollViewer>
Expand Down
10 changes: 10 additions & 0 deletions dev/AnimatedIcon/TestUI/AnimatedIconPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,16 @@ private void SpeedUpSlider_ValueChanged(object sender, RangeBaseValueChangedEven
}
}

public void IsLeftToRightChecked(object sender, RoutedEventArgs args)
{
this.FlowDirection = FlowDirection.LeftToRight;
}

public void IsLeftToRightUnchecked(object sender, RoutedEventArgs args)
{
this.FlowDirection = FlowDirection.RightToLeft;
}

private void ChangeFallbackGlyphButton_Click(object sender, RoutedEventArgs e)
{
boundFallback.FallbackGlyph = "\uE9AE";
Expand Down
34 changes: 34 additions & 0 deletions dev/Generated/AnimatedIcon.properties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ namespace winrt::Microsoft::UI::Xaml::Controls
#include "AnimatedIcon.g.cpp"

GlobalDependencyProperty AnimatedIconProperties::s_FallbackIconSourceProperty{ nullptr };
GlobalDependencyProperty AnimatedIconProperties::s_MirroredWhenRightToLeftProperty{ nullptr };
GlobalDependencyProperty AnimatedIconProperties::s_SourceProperty{ nullptr };
GlobalDependencyProperty AnimatedIconProperties::s_StateProperty{ nullptr };

Expand All @@ -35,6 +36,17 @@ void AnimatedIconProperties::EnsureProperties()
ValueHelper<winrt::IconSource>::BoxedDefaultValue(),
winrt::PropertyChangedCallback(&OnFallbackIconSourcePropertyChanged));
}
if (!s_MirroredWhenRightToLeftProperty)
{
s_MirroredWhenRightToLeftProperty =
InitializeDependencyProperty(
L"MirroredWhenRightToLeft",
winrt::name_of<bool>(),
winrt::name_of<winrt::AnimatedIcon>(),
false /* isAttached */,
ValueHelper<bool>::BoxedDefaultValue(),
winrt::PropertyChangedCallback(&OnMirroredWhenRightToLeftPropertyChanged));
}
if (!s_SourceProperty)
{
s_SourceProperty =
Expand Down Expand Up @@ -62,6 +74,7 @@ void AnimatedIconProperties::EnsureProperties()
void AnimatedIconProperties::ClearProperties()
{
s_FallbackIconSourceProperty = nullptr;
s_MirroredWhenRightToLeftProperty = nullptr;
s_SourceProperty = nullptr;
s_StateProperty = nullptr;
}
Expand All @@ -74,6 +87,14 @@ void AnimatedIconProperties::OnFallbackIconSourcePropertyChanged(
winrt::get_self<AnimatedIcon>(owner)->OnFallbackIconSourcePropertyChanged(args);
}

void AnimatedIconProperties::OnMirroredWhenRightToLeftPropertyChanged(
winrt::DependencyObject const& sender,
winrt::DependencyPropertyChangedEventArgs const& args)
{
auto owner = sender.as<winrt::AnimatedIcon>();
winrt::get_self<AnimatedIcon>(owner)->OnMirroredWhenRightToLeftPropertyChanged(args);
}

void AnimatedIconProperties::OnSourcePropertyChanged(
winrt::DependencyObject const& sender,
winrt::DependencyPropertyChangedEventArgs const& args)
Expand All @@ -95,6 +116,19 @@ winrt::IconSource AnimatedIconProperties::FallbackIconSource()
return ValueHelper<winrt::IconSource>::CastOrUnbox(static_cast<AnimatedIcon*>(this)->GetValue(s_FallbackIconSourceProperty));
}

void AnimatedIconProperties::MirroredWhenRightToLeft(bool value)
{
[[gsl::suppress(con)]]
{
static_cast<AnimatedIcon*>(this)->SetValue(s_MirroredWhenRightToLeftProperty, ValueHelper<bool>::BoxValueIfNecessary(value));
}
}

bool AnimatedIconProperties::MirroredWhenRightToLeft()
{
return ValueHelper<bool>::CastOrUnbox(static_cast<AnimatedIcon*>(this)->GetValue(s_MirroredWhenRightToLeftProperty));
}

void AnimatedIconProperties::Source(winrt::IAnimatedVisualSource2 const& value)
{
[[gsl::suppress(con)]]
Expand Down
9 changes: 9 additions & 0 deletions dev/Generated/AnimatedIcon.properties.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,22 @@ class AnimatedIconProperties
void FallbackIconSource(winrt::IconSource const& value);
winrt::IconSource FallbackIconSource();

void MirroredWhenRightToLeft(bool value);
bool MirroredWhenRightToLeft();

void Source(winrt::IAnimatedVisualSource2 const& value);
winrt::IAnimatedVisualSource2 Source();

static void SetState(winrt::DependencyObject const& target, winrt::hstring const& value);
static winrt::hstring GetState(winrt::DependencyObject const& target);

static winrt::DependencyProperty FallbackIconSourceProperty() { return s_FallbackIconSourceProperty; }
static winrt::DependencyProperty MirroredWhenRightToLeftProperty() { return s_MirroredWhenRightToLeftProperty; }
static winrt::DependencyProperty SourceProperty() { return s_SourceProperty; }
static winrt::DependencyProperty StateProperty() { return s_StateProperty; }

static GlobalDependencyProperty s_FallbackIconSourceProperty;
static GlobalDependencyProperty s_MirroredWhenRightToLeftProperty;
static GlobalDependencyProperty s_SourceProperty;
static GlobalDependencyProperty s_StateProperty;

Expand All @@ -33,6 +38,10 @@ class AnimatedIconProperties
winrt::DependencyObject const& sender,
winrt::DependencyPropertyChangedEventArgs const& args);

static void OnMirroredWhenRightToLeftPropertyChanged(
winrt::DependencyObject const& sender,
winrt::DependencyPropertyChangedEventArgs const& args);

static void OnSourcePropertyChanged(
winrt::DependencyObject const& sender,
winrt::DependencyPropertyChangedEventArgs const& args);
Expand Down
34 changes: 34 additions & 0 deletions dev/Generated/AnimatedIconSource.properties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ namespace winrt::Microsoft::UI::Xaml::Controls
#include "AnimatedIconSource.g.cpp"

GlobalDependencyProperty AnimatedIconSourceProperties::s_FallbackIconSourceProperty{ nullptr };
GlobalDependencyProperty AnimatedIconSourceProperties::s_MirroredWhenRightToLeftProperty{ nullptr };
GlobalDependencyProperty AnimatedIconSourceProperties::s_SourceProperty{ nullptr };

AnimatedIconSourceProperties::AnimatedIconSourceProperties()
Expand All @@ -35,6 +36,17 @@ void AnimatedIconSourceProperties::EnsureProperties()
ValueHelper<winrt::IconSource>::BoxedDefaultValue(),
winrt::PropertyChangedCallback(&OnFallbackIconSourcePropertyChanged));
}
if (!s_MirroredWhenRightToLeftProperty)
{
s_MirroredWhenRightToLeftProperty =
InitializeDependencyProperty(
L"MirroredWhenRightToLeft",
winrt::name_of<bool>(),
winrt::name_of<winrt::AnimatedIconSource>(),
false /* isAttached */,
ValueHelper<bool>::BoxedDefaultValue(),
winrt::PropertyChangedCallback(&OnMirroredWhenRightToLeftPropertyChanged));
}
if (!s_SourceProperty)
{
s_SourceProperty =
Expand All @@ -51,6 +63,7 @@ void AnimatedIconSourceProperties::EnsureProperties()
void AnimatedIconSourceProperties::ClearProperties()
{
s_FallbackIconSourceProperty = nullptr;
s_MirroredWhenRightToLeftProperty = nullptr;
s_SourceProperty = nullptr;
IconSource::ClearProperties();
}
Expand All @@ -63,6 +76,14 @@ void AnimatedIconSourceProperties::OnFallbackIconSourcePropertyChanged(
winrt::get_self<AnimatedIconSource>(owner)->OnPropertyChanged(args);
}

void AnimatedIconSourceProperties::OnMirroredWhenRightToLeftPropertyChanged(
winrt::DependencyObject const& sender,
winrt::DependencyPropertyChangedEventArgs const& args)
{
auto owner = sender.as<winrt::AnimatedIconSource>();
winrt::get_self<AnimatedIconSource>(owner)->OnPropertyChanged(args);
}

void AnimatedIconSourceProperties::OnSourcePropertyChanged(
winrt::DependencyObject const& sender,
winrt::DependencyPropertyChangedEventArgs const& args)
Expand All @@ -84,6 +105,19 @@ winrt::IconSource AnimatedIconSourceProperties::FallbackIconSource()
return ValueHelper<winrt::IconSource>::CastOrUnbox(static_cast<AnimatedIconSource*>(this)->GetValue(s_FallbackIconSourceProperty));
}

void AnimatedIconSourceProperties::MirroredWhenRightToLeft(bool value)
{
[[gsl::suppress(con)]]
{
static_cast<AnimatedIconSource*>(this)->SetValue(s_MirroredWhenRightToLeftProperty, ValueHelper<bool>::BoxValueIfNecessary(value));
}
}

bool AnimatedIconSourceProperties::MirroredWhenRightToLeft()
{
return ValueHelper<bool>::CastOrUnbox(static_cast<AnimatedIconSource*>(this)->GetValue(s_MirroredWhenRightToLeftProperty));
}

void AnimatedIconSourceProperties::Source(winrt::IAnimatedVisualSource2 const& value)
{
[[gsl::suppress(con)]]
Expand Down
Loading

0 comments on commit f4d781d

Please sign in to comment.