From 63f1aa8cd6c0b98d9eeb44abf51af04ce4210987 Mon Sep 17 00:00:00 2001 From: robloo Date: Mon, 24 Jan 2022 14:22:48 -0500 Subject: [PATCH] Add Fluent v1 default style for SplitButton --- .../SplitButton/SplitButton.cs | 141 ++++--- .../Accents/FluentControlResourcesDark.xaml | 27 ++ .../Accents/FluentControlResourcesLight.xaml | 27 ++ .../Controls/FluentControls.xaml | 1 + .../Controls/SplitButton.xaml | 370 ++++++++++++++++++ 5 files changed, 520 insertions(+), 46 deletions(-) create mode 100644 src/Avalonia.Themes.Fluent/Controls/SplitButton.xaml diff --git a/src/Avalonia.Controls/SplitButton/SplitButton.cs b/src/Avalonia.Controls/SplitButton/SplitButton.cs index d3450b332f..4af8b44629 100644 --- a/src/Avalonia.Controls/SplitButton/SplitButton.cs +++ b/src/Avalonia.Controls/SplitButton/SplitButton.cs @@ -1,6 +1,7 @@ using System; using System.Reactive.Disposables; using System.Windows.Input; +using Avalonia.Controls.Metadata; using Avalonia.Controls.Primitives; using Avalonia.Input; using Avalonia.Interactivity; @@ -12,6 +13,7 @@ namespace Avalonia.Controls /// A button with primary and secondary parts that can each be invoked separately. /// The primary part behaves like a button and the secondary part opens a flyout. /// + //[PseudoClasses(":pressed")] public class SplitButton : ContentControl, ICommandSource { /// @@ -141,109 +143,156 @@ namespace Avalonia.Controls /// private void UpdatePseudoClasses() { - /* - // place the secondary button - if (m_lastPointerDeviceType == winrt::PointerDeviceType::Touch || m_isKeyDown) + bool internalIsChecked = false; + + string pcNormal = ":normal"; + string pcDisabled = ":disabled"; + + string pcSecondaryButtonRight = ":secondaryButtonRight"; + string pcSecondaryButtonSpan = ":secondaryButtonSpan"; + + string pcCheckedFlyoutOpen = ":checkedFlyoutOpen"; + string pcFlyoutOpen = ":flyoutOpen"; + + string pcCheckedTouchPressed = ":checkedTouchPressed"; + string pcChecked = ":checked"; + string pcCheckedPrimaryPressed = ":checkedPrimaryPressed"; + string pcCheckedPrimaryPointerOver = ":checkedPrimaryPointerOver"; + string pcCheckedSecondaryPressed = ":checkedSecondaryPressed"; + string pcCheckedSecondaryPointerOver = ":checkedSecondaryPointerOver"; + + string pcTouchPressed = ":touchPressed"; + string pcPrimaryPressed = ":primaryPressed"; + string pcPrimaryPointerOver = ":primaryPointerOver"; + string pcSecondaryPressed = ":secondaryPressed"; + string pcSecondaryPointerOver = ":secondaryPointerOver"; + + // Place the secondary button + // These are mutually exclusive PseudoClasses handled separately from SetExclusivePseudoClass(). + // They must be applied in addition to the others. + if (_lastPointerType == PointerType.Touch || _isKeyDown) { - winrt::VisualStateManager::GoToState(*this, L"SecondaryButtonSpan", useTransitions); + PseudoClasses.Set(pcSecondaryButtonSpan, true); + PseudoClasses.Set(pcSecondaryButtonRight, false); } else { - winrt::VisualStateManager::GoToState(*this, L"SecondaryButtonRight", useTransitions); + PseudoClasses.Set(pcSecondaryButtonSpan, false); + PseudoClasses.Set(pcSecondaryButtonRight, true); } - // change visual state - auto primaryButton = m_primaryButton.get(); - auto secondaryButton = m_secondaryButton.get(); - - if (!IsEnabled()) + // Change the visual state + if (!IsEnabled) { - winrt::VisualStateManager::GoToState(*this, L"Disabled", useTransitions); + SetExclusivePseudoClass(pcDisabled); } - else if (primaryButton && secondaryButton) + else if (_primaryButton != null && _secondaryButton != null) { - if (m_isFlyoutOpen) + if (_isFlyoutOpen) { - if (InternalIsChecked()) + if (internalIsChecked) { - winrt::VisualStateManager::GoToState(*this, L"CheckedFlyoutOpen", useTransitions); + SetExclusivePseudoClass(pcCheckedFlyoutOpen); } else { - winrt::VisualStateManager::GoToState(*this, L"FlyoutOpen", useTransitions); + SetExclusivePseudoClass(pcFlyoutOpen); } } // SplitButton and ToggleSplitButton share a template -- this section is driving the checked states for ToggleSplitButton. - else if (InternalIsChecked()) + else if (internalIsChecked) { - if (m_lastPointerDeviceType == winrt::PointerDeviceType::Touch || m_isKeyDown) + if (_lastPointerType == PointerType.Touch || _isKeyDown) { - if (primaryButton.IsPressed() || secondaryButton.IsPressed() || m_isKeyDown) + if (_primaryButton.IsPressed || _secondaryButton.IsPressed || _isKeyDown) { - winrt::VisualStateManager::GoToState(*this, L"CheckedTouchPressed", useTransitions); + SetExclusivePseudoClass(pcCheckedTouchPressed); } else { - winrt::VisualStateManager::GoToState(*this, L"Checked", useTransitions); + SetExclusivePseudoClass(pcChecked); } } - else if (primaryButton.IsPressed()) + else if (_primaryButton.IsPressed) { - winrt::VisualStateManager::GoToState(*this, L"CheckedPrimaryPressed", useTransitions); + SetExclusivePseudoClass(pcCheckedPrimaryPressed); } - else if (primaryButton.IsPointerOver()) + else if (_primaryButton.IsPointerOver) { - winrt::VisualStateManager::GoToState(*this, L"CheckedPrimaryPointerOver", useTransitions); + SetExclusivePseudoClass(pcCheckedPrimaryPointerOver); } - else if (secondaryButton.IsPressed()) + else if (_secondaryButton.IsPressed) { - winrt::VisualStateManager::GoToState(*this, L"CheckedSecondaryPressed", useTransitions); + SetExclusivePseudoClass(pcCheckedSecondaryPressed); } - else if (secondaryButton.IsPointerOver()) + else if (_secondaryButton.IsPointerOver) { - winrt::VisualStateManager::GoToState(*this, L"CheckedSecondaryPointerOver", useTransitions); + SetExclusivePseudoClass(pcCheckedSecondaryPointerOver); } else { - winrt::VisualStateManager::GoToState(*this, L"Checked", useTransitions); + SetExclusivePseudoClass(pcChecked); } } else { - if (m_lastPointerDeviceType == winrt::PointerDeviceType::Touch || m_isKeyDown) + if (_lastPointerType == PointerType.Touch || _isKeyDown) { - if (primaryButton.IsPressed() || secondaryButton.IsPressed() || m_isKeyDown) + if (_primaryButton.IsPressed || _secondaryButton.IsPressed || _isKeyDown) { - winrt::VisualStateManager::GoToState(*this, L"TouchPressed", useTransitions); + SetExclusivePseudoClass(pcTouchPressed); } else { - winrt::VisualStateManager::GoToState(*this, L"Normal", useTransitions); + SetExclusivePseudoClass(pcNormal); } } - else if (primaryButton.IsPressed()) + else if (_primaryButton.IsPressed) { - winrt::VisualStateManager::GoToState(*this, L"PrimaryPressed", useTransitions); + SetExclusivePseudoClass(pcPrimaryPressed); } - else if (primaryButton.IsPointerOver()) + else if (_primaryButton.IsPointerOver) { - winrt::VisualStateManager::GoToState(*this, L"PrimaryPointerOver", useTransitions); + SetExclusivePseudoClass(pcPrimaryPointerOver); } - else if (secondaryButton.IsPressed()) + else if (_secondaryButton.IsPressed) { - winrt::VisualStateManager::GoToState(*this, L"SecondaryPressed", useTransitions); + SetExclusivePseudoClass(pcSecondaryPressed); } - else if (secondaryButton.IsPointerOver()) + else if (_secondaryButton.IsPointerOver) { - winrt::VisualStateManager::GoToState(*this, L"SecondaryPointerOver", useTransitions); + SetExclusivePseudoClass(pcSecondaryPointerOver); } else { - winrt::VisualStateManager::GoToState(*this, L"Normal", useTransitions); + SetExclusivePseudoClass(pcNormal); } } } - */ + + // Local function to enable the specified PseudoClass and disable all others + // This more closely matches the VisualStateManager of WinUI where the default style originated + void SetExclusivePseudoClass(string pseudoClass = "") + { + PseudoClasses.Set(pcNormal, pseudoClass == pcNormal); + PseudoClasses.Set(pcDisabled, pseudoClass == pcDisabled); + + PseudoClasses.Set(pcCheckedFlyoutOpen, pseudoClass == pcCheckedFlyoutOpen); + PseudoClasses.Set(pcFlyoutOpen, pseudoClass == pcFlyoutOpen); + + PseudoClasses.Set(pcCheckedTouchPressed, pseudoClass == pcCheckedTouchPressed); + PseudoClasses.Set(pcChecked, pseudoClass == pcChecked); + PseudoClasses.Set(pcCheckedPrimaryPressed, pseudoClass == pcCheckedPrimaryPressed); + PseudoClasses.Set(pcCheckedPrimaryPointerOver, pseudoClass == pcCheckedPrimaryPointerOver); + PseudoClasses.Set(pcCheckedSecondaryPressed, pseudoClass == pcCheckedSecondaryPressed); + PseudoClasses.Set(pcCheckedSecondaryPointerOver, pseudoClass == pcCheckedSecondaryPointerOver); + + PseudoClasses.Set(pcTouchPressed, pseudoClass == pcTouchPressed); + PseudoClasses.Set(pcPrimaryPressed, pseudoClass == pcPrimaryPressed); + PseudoClasses.Set(pcPrimaryPointerOver, pseudoClass == pcPrimaryPointerOver); + PseudoClasses.Set(pcSecondaryPressed, pseudoClass == pcSecondaryPressed); + PseudoClasses.Set(pcSecondaryPointerOver, pseudoClass == pcSecondaryPointerOver); + } } /// @@ -342,8 +391,8 @@ namespace Avalonia.Controls UnregisterEvents(); UnregisterFlyoutEvents(Flyout); - _primaryButton = e.NameScope.Find + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +