diff --git a/dev/Generated/ProgressBarTemplateSettings.properties.cpp b/dev/Generated/ProgressBarTemplateSettings.properties.cpp index d717c57171..8f0cec59ea 100644 --- a/dev/Generated/ProgressBarTemplateSettings.properties.cpp +++ b/dev/Generated/ProgressBarTemplateSettings.properties.cpp @@ -10,6 +10,8 @@ CppWinRTActivatableClassWithDPFactory(ProgressBarTemplateSettings) GlobalDependencyProperty ProgressBarTemplateSettingsProperties::s_ClipRectProperty{ nullptr }; GlobalDependencyProperty ProgressBarTemplateSettingsProperties::s_ContainerAnimationEndPositionProperty{ nullptr }; +GlobalDependencyProperty ProgressBarTemplateSettingsProperties::s_ContainerAnimationStartPositionProperty{ nullptr }; +GlobalDependencyProperty ProgressBarTemplateSettingsProperties::s_IndicatorLengthDeltaProperty{ nullptr }; ProgressBarTemplateSettingsProperties::ProgressBarTemplateSettingsProperties() { @@ -40,12 +42,36 @@ void ProgressBarTemplateSettingsProperties::EnsureProperties() ValueHelper::BoxedDefaultValue(), nullptr); } + if (!s_ContainerAnimationStartPositionProperty) + { + s_ContainerAnimationStartPositionProperty = + InitializeDependencyProperty( + L"ContainerAnimationStartPosition", + winrt::name_of(), + winrt::name_of(), + false /* isAttached */, + ValueHelper::BoxedDefaultValue(), + nullptr); + } + if (!s_IndicatorLengthDeltaProperty) + { + s_IndicatorLengthDeltaProperty = + InitializeDependencyProperty( + L"IndicatorLengthDelta", + winrt::name_of(), + winrt::name_of(), + false /* isAttached */, + ValueHelper::BoxedDefaultValue(), + nullptr); + } } void ProgressBarTemplateSettingsProperties::ClearProperties() { s_ClipRectProperty = nullptr; s_ContainerAnimationEndPositionProperty = nullptr; + s_ContainerAnimationStartPositionProperty = nullptr; + s_IndicatorLengthDeltaProperty = nullptr; } void ProgressBarTemplateSettingsProperties::ClipRect(winrt::RectangleGeometry const& value) @@ -67,3 +93,23 @@ double ProgressBarTemplateSettingsProperties::ContainerAnimationEndPosition() { return ValueHelper::CastOrUnbox(static_cast(this)->GetValue(s_ContainerAnimationEndPositionProperty)); } + +void ProgressBarTemplateSettingsProperties::ContainerAnimationStartPosition(double value) +{ + static_cast(this)->SetValue(s_ContainerAnimationStartPositionProperty, ValueHelper::BoxValueIfNecessary(value)); +} + +double ProgressBarTemplateSettingsProperties::ContainerAnimationStartPosition() +{ + return ValueHelper::CastOrUnbox(static_cast(this)->GetValue(s_ContainerAnimationStartPositionProperty)); +} + +void ProgressBarTemplateSettingsProperties::IndicatorLengthDelta(double value) +{ + static_cast(this)->SetValue(s_IndicatorLengthDeltaProperty, ValueHelper::BoxValueIfNecessary(value)); +} + +double ProgressBarTemplateSettingsProperties::IndicatorLengthDelta() +{ + return ValueHelper::CastOrUnbox(static_cast(this)->GetValue(s_IndicatorLengthDeltaProperty)); +} diff --git a/dev/Generated/ProgressBarTemplateSettings.properties.h b/dev/Generated/ProgressBarTemplateSettings.properties.h index 38b1dbdefa..c12af124d2 100644 --- a/dev/Generated/ProgressBarTemplateSettings.properties.h +++ b/dev/Generated/ProgressBarTemplateSettings.properties.h @@ -15,11 +15,21 @@ class ProgressBarTemplateSettingsProperties void ContainerAnimationEndPosition(double value); double ContainerAnimationEndPosition(); + void ContainerAnimationStartPosition(double value); + double ContainerAnimationStartPosition(); + + void IndicatorLengthDelta(double value); + double IndicatorLengthDelta(); + static winrt::DependencyProperty ClipRectProperty() { return s_ClipRectProperty; } static winrt::DependencyProperty ContainerAnimationEndPositionProperty() { return s_ContainerAnimationEndPositionProperty; } + static winrt::DependencyProperty ContainerAnimationStartPositionProperty() { return s_ContainerAnimationStartPositionProperty; } + static winrt::DependencyProperty IndicatorLengthDeltaProperty() { return s_IndicatorLengthDeltaProperty; } static GlobalDependencyProperty s_ClipRectProperty; static GlobalDependencyProperty s_ContainerAnimationEndPositionProperty; + static GlobalDependencyProperty s_ContainerAnimationStartPositionProperty; + static GlobalDependencyProperty s_IndicatorLengthDeltaProperty; static void EnsureProperties(); static void ClearProperties(); diff --git a/dev/ProgressBar/ProgressBar.cpp b/dev/ProgressBar/ProgressBar.cpp index 3a05aac5d8..0efce82cb6 100644 --- a/dev/ProgressBar/ProgressBar.cpp +++ b/dev/ProgressBar/ProgressBar.cpp @@ -40,24 +40,20 @@ void ProgressBar::OnApplyTemplate() void ProgressBar::OnSizeChanged(const winrt::IInspectable&, const winrt::IInspectable&) { SetProgressBarIndicatorWidth(); - if (m_shouldUpdateWidthBasedTemplateSettings) - { - UpdateWidthBasedTemplateSettings(); - } + UpdateWidthBasedTemplateSettings(); } void ProgressBar::OnRangeBasePropertyChanged(const winrt::DependencyObject& sender, const winrt::DependencyProperty& args) { // NOTE: This hits when the Value property changes, because we called RegisterPropertyChangedCallback. - SetProgressBarIndicatorWidth(); } void ProgressBar::OnIsIndeterminatePropertyChanged(const winrt::DependencyPropertyChangedEventArgs& args) { // NOTE: This hits when IsIndeterminate changes because we set MUX_PROPERTY_CHANGED_CALLBACK to true in the idl. - - UpdateStates(); + SetProgressBarIndicatorWidth(); + UpdateStates(); } void ProgressBar::OnShowPausedPropertyChanged(const winrt::DependencyPropertyChangedEventArgs& args) @@ -73,6 +69,7 @@ void ProgressBar::OnShowErrorPropertyChanged(const winrt::DependencyPropertyChan void ProgressBar::UpdateStates() { m_shouldUpdateWidthBasedTemplateSettings = false; + if (ShowError()) { winrt::VisualStateManager::GoToState(*this, s_ErrorStateName, true); @@ -93,32 +90,47 @@ void ProgressBar::UpdateStates() } else if (!IsIndeterminate()) { - SetProgressBarIndicatorWidth(); winrt::VisualStateManager::GoToState(*this, s_DeterminateStateName, true); } } void ProgressBar::SetProgressBarIndicatorWidth() { + const auto templateSettings = winrt::get_self<::ProgressBarTemplateSettings>(TemplateSettings()); + if (auto&& progressBar = m_layoutRoot.get()) { if (auto&& progressBarIndicator = m_progressBarIndicator.get()) { const double progressBarWidth = progressBar.ActualWidth(); + const double prevIndicatorWidth = progressBarIndicator.ActualWidth(); const double maximum = Maximum(); const double minimum = Minimum(); const auto padding = Padding(); - if (std::abs(maximum - minimum) > DBL_EPSILON) + // Adds "Updating" state in between to trigger RepositionThemeAnimation Visual Transition + // in ProgressBar.xaml when reverting back to previous state + winrt::VisualStateManager::GoToState(*this, s_UpdatingStateName, true); + + if (IsIndeterminate()) + { + progressBarIndicator.Width(progressBarWidth * 0.4); + } + else if (std::abs(maximum - minimum) > DBL_EPSILON) { const double maxIndicatorWidth = progressBarWidth - (padding.Left + padding.Right); const double increment = maxIndicatorWidth / (maximum - minimum); - progressBarIndicator.Width(increment * (Value() - minimum)); + const double indicatorWidth = increment * (Value() - minimum); + const double widthDelta = indicatorWidth - prevIndicatorWidth; + templateSettings->IndicatorLengthDelta(-widthDelta); + progressBarIndicator.Width(indicatorWidth); } else { progressBarIndicator.Width(0); // Error } + + UpdateStates(); // Reverts back to previous state } } } @@ -129,7 +141,7 @@ void ProgressBar::UpdateWidthBasedTemplateSettings() if (auto&& progressBarIndicator = m_progressBarIndicator.get()) { - auto const [width, height] = [progressBar = m_layoutRoot.get()]() + const auto [width, height] = [progressBar = m_layoutRoot.get()]() { if (progressBar) { @@ -140,8 +152,9 @@ void ProgressBar::UpdateWidthBasedTemplateSettings() return std::make_tuple(0.0f, 0.0f); }(); - progressBarIndicator.Width(width / 3); + const double indicatorWidthMultiplier = -0.4; + templateSettings->ContainerAnimationStartPosition(width * indicatorWidthMultiplier); templateSettings->ContainerAnimationEndPosition(width); const auto rectangle = [width, height, padding = Padding()]() diff --git a/dev/ProgressBar/ProgressBar.h b/dev/ProgressBar/ProgressBar.h index 870e7e62bd..387e3dfd16 100644 --- a/dev/ProgressBar/ProgressBar.h +++ b/dev/ProgressBar/ProgressBar.h @@ -49,4 +49,5 @@ class ProgressBar : static constexpr wstring_view s_PausedStateName{ L"Paused" }; static constexpr wstring_view s_IndeterminateStateName{ L"Indeterminate" }; static constexpr wstring_view s_DeterminateStateName{ L"Determinate" }; + static constexpr wstring_view s_UpdatingStateName{ L"Updating" }; }; diff --git a/dev/ProgressBar/ProgressBar.idl b/dev/ProgressBar/ProgressBar.idl index 0f4438bd03..8405a7f038 100644 --- a/dev/ProgressBar/ProgressBar.idl +++ b/dev/ProgressBar/ProgressBar.idl @@ -7,9 +7,15 @@ unsealed runtimeclass ProgressBarTemplateSettings : Windows.UI.Xaml.DependencyOb { ProgressBarTemplateSettings(); + Double ContainerAnimationStartPosition; + static Windows.UI.Xaml.DependencyProperty ContainerAnimationStartPositionProperty{ get; }; + Double ContainerAnimationEndPosition; static Windows.UI.Xaml.DependencyProperty ContainerAnimationEndPositionProperty{ get; }; + Double IndicatorLengthDelta; + static Windows.UI.Xaml.DependencyProperty IndicatorLengthDeltaProperty{ get; }; + Windows.UI.Xaml.Media.RectangleGeometry ClipRect; static Windows.UI.Xaml.DependencyProperty ClipRectProperty{ get; }; } diff --git a/dev/ProgressBar/ProgressBar.xaml b/dev/ProgressBar/ProgressBar.xaml index b74593db37..051263d088 100644 --- a/dev/ProgressBar/ProgressBar.xaml +++ b/dev/ProgressBar/ProgressBar.xaml @@ -26,6 +26,11 @@ + + + + + + - +