diff --git a/components/CanvasView/src/Dependencies.props b/components/CanvasView/src/Dependencies.props index ee01b275e..3470b688b 100644 --- a/components/CanvasView/src/Dependencies.props +++ b/components/CanvasView/src/Dependencies.props @@ -9,23 +9,13 @@ For UWP / WinAppSDK / Uno packages, place the package references here. --> - - - - + + + + - - - - - - - - - - - - - - + + + + diff --git a/components/SegmentedControl/src/Dependencies.props b/components/SegmentedControl/src/Dependencies.props index ee01b275e..3470b688b 100644 --- a/components/SegmentedControl/src/Dependencies.props +++ b/components/SegmentedControl/src/Dependencies.props @@ -9,23 +9,13 @@ For UWP / WinAppSDK / Uno packages, place the package references here. --> - - - - + + + + - - - - - - - - - - - - - - + + + + diff --git a/components/SettingsControls/src/Dependencies.props b/components/SettingsControls/src/Dependencies.props index cff9d9612..3470b688b 100644 --- a/components/SettingsControls/src/Dependencies.props +++ b/components/SettingsControls/src/Dependencies.props @@ -9,23 +9,13 @@ For UWP / WinAppSDK / Uno packages, place the package references here. --> - - - - - - - - - + + + + - - - - - - - - + + + diff --git a/components/SizerBase/src/CommunityToolkit.Labs.WinUI.SizerBase.csproj b/components/SizerBase/src/CommunityToolkit.Labs.WinUI.SizerBase.csproj index 2c050a007..d80f15f1f 100644 --- a/components/SizerBase/src/CommunityToolkit.Labs.WinUI.SizerBase.csproj +++ b/components/SizerBase/src/CommunityToolkit.Labs.WinUI.SizerBase.csproj @@ -2,7 +2,7 @@ SizerBase This package contains SizerBase. - 0.0.4 + 0.0.5 CommunityToolkit.Labs.WinUI.SizerBaseRns diff --git a/components/SizerBase/src/ContentSizer/ContentSizer.Events.cs b/components/SizerBase/src/ContentSizer/ContentSizer.Events.cs index 3e9b8f567..bf5439f7b 100644 --- a/components/SizerBase/src/ContentSizer/ContentSizer.Events.cs +++ b/components/SizerBase/src/ContentSizer/ContentSizer.Events.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using CommunityToolkit.Labs.WinUI.SizerBaseLocal; +using CommunityToolkit.WinUI; namespace CommunityToolkit.Labs.WinUI; diff --git a/components/SizerBase/src/Dependencies.props b/components/SizerBase/src/Dependencies.props index e622e1df4..3470b688b 100644 --- a/components/SizerBase/src/Dependencies.props +++ b/components/SizerBase/src/Dependencies.props @@ -9,23 +9,13 @@ For UWP / WinAppSDK / Uno packages, place the package references here. --> - - - - + + + + - - - - - - - - - - - - - - + + + + diff --git a/components/SizerBase/src/SizerBase.Events.cs b/components/SizerBase/src/SizerBase.Events.cs index c3b2c52c0..3a87f62e2 100644 --- a/components/SizerBase/src/SizerBase.Events.cs +++ b/components/SizerBase/src/SizerBase.Events.cs @@ -72,7 +72,7 @@ protected override void OnManipulationStarting(ManipulationStartingRoutedEventAr /// protected override void OnManipulationDelta(ManipulationDeltaRoutedEventArgs e) { - // We use Trancate here to provide 'snapping' points with the DragIncrement property + // We use Truncate here to provide 'snapping' points with the DragIncrement property // It works for both our negative and positive values, as otherwise we'd need to use // Ceiling when negative and Floor when positive to maintain the correct behavior. var horizontalChange = @@ -117,7 +117,7 @@ private void SizerBase_PointerReleased(object sender, PointerRoutedEventArgs e) if (IsEnabled) { - VisualStateManager.GoToState(this, _pointerEntered ? "PointerOver" : "Normal", true); + VisualStateManager.GoToState(this, _pointerEntered ? PointerOverState : NormalState, true); } } @@ -127,7 +127,7 @@ private void SizerBase_PointerPressed(object sender, PointerRoutedEventArgs e) if (IsEnabled) { - VisualStateManager.GoToState(this, "Pressed", true); + VisualStateManager.GoToState(this, PointerOverState, true); } } @@ -137,7 +137,7 @@ private void SizerBase_PointerExited(object sender, PointerRoutedEventArgs e) if (!_pressed && !_dragging && IsEnabled) { - VisualStateManager.GoToState(this, "Normal", true); + VisualStateManager.GoToState(this, NormalState, true); } } @@ -147,7 +147,7 @@ private void SizerBase_PointerEntered(object sender, PointerRoutedEventArgs e) if (!_pressed && !_dragging && IsEnabled) { - VisualStateManager.GoToState(this, "PointerOver", true); + VisualStateManager.GoToState(this, PointerOverState, true); } } @@ -155,24 +155,24 @@ private void SizerBase_ManipulationCompleted(object sender, ManipulationComplete { _dragging = false; _pressed = false; - VisualStateManager.GoToState(this, _pointerEntered ? "PointerOver" : "Normal", true); + VisualStateManager.GoToState(this, _pointerEntered ? PointerOverState : NormalState, true); } private void SizerBase_ManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e) { _dragging = true; - VisualStateManager.GoToState(this, "Pressed", true); + VisualStateManager.GoToState(this, PressedState, true); } private void SizerBase_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e) { if (!IsEnabled) { - VisualStateManager.GoToState(this, "Disabled", true); + VisualStateManager.GoToState(this, DisabledState, true); } else { - VisualStateManager.GoToState(this, _pointerEntered ? "PointerOver" : "Normal", true); + VisualStateManager.GoToState(this, _pointerEntered ? PointerOverState : NormalState, true); } } } diff --git a/components/SizerBase/src/SizerBase.Properties.cs b/components/SizerBase/src/SizerBase.Properties.cs index 650e6477a..dec692218 100644 --- a/components/SizerBase/src/SizerBase.Properties.cs +++ b/components/SizerBase/src/SizerBase.Properties.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using CommunityToolkit.WinUI; + #if !WINAPPSDK using CursorEnum = Windows.UI.Core.CoreCursorType; #else @@ -17,7 +19,7 @@ namespace CommunityToolkit.Labs.WinUI; public partial class SizerBase : Control { /// - /// Gets or sets the cursor to use when hovering over the gripper bar. If left as null, the control will manage the cursor automatically based on the property value. + /// Gets or sets the cursor to use when hovering over the gripper bar. If left as null, the control will manage the cursor automatically based on the property value (default). /// public CursorEnum Cursor { @@ -32,13 +34,13 @@ public CursorEnum Cursor DependencyProperty.Register(nameof(Cursor), typeof(CursorEnum), typeof(SizerBase), new PropertyMetadata(null, OnOrientationPropertyChanged)); /// - /// Gets or sets the incremental amount of change for draging with the mouse or touch of a sizer control. Effectively a snapping increment for changes. The default is 1. + /// Gets or sets the incremental amount of change for dragging with the mouse or touch of a sizer control. Effectively a snapping increment for changes. The default is 1. /// /// /// For instance, if the DragIncrement is set to 16. Then when a component is resized with the sizer, it will only increase or decrease in size in that increment. I.e. -16, 0, 16, 32, 48, etc... /// /// - /// This value is indepedent of the property. If you need to provide consistent snapping when moving regardless of input device, set these properties to the same value. + /// This value is independent of the property. If you need to provide consistent snapping when moving regardless of input device, set these properties to the same value. /// public double DragIncrement { @@ -88,41 +90,69 @@ public Orientation Orientation public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register(nameof(Orientation), typeof(Orientation), typeof(SizerBase), new PropertyMetadata(Orientation.Vertical, OnOrientationPropertyChanged)); + /// + /// Gets or sets if the Thumb is visible. If not visible, only the background and cursor will be shown on MouseOver or Pressed states. + /// + public bool IsThumbVisible + { + get { return (bool)GetValue(IsThumbVisibleProperty); } + set { SetValue(IsThumbVisibleProperty, value); } + } + + /// + /// Identifies the dependency property. + /// + public static readonly DependencyProperty IsThumbVisibleProperty = + DependencyProperty.Register(nameof(IsThumbVisible), typeof(bool), typeof(SizerBase), new PropertyMetadata(true, OnIsThumbVisiblePropertyChanged)); + + private static void OnOrientationPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is SizerBase gripper) { - CursorEnum cursorToUse = gripper.Orientation == Orientation.Vertical ? CursorEnum.SizeWestEast : CursorEnum.SizeNorthSouth; + VisualStateManager.GoToState(gripper, gripper.Orientation == Orientation.Vertical ? VerticalState : HorizontalState, true); + + CursorEnum cursorByOrientation = gripper.Orientation == Orientation.Vertical ? CursorEnum.SizeWestEast : CursorEnum.SizeNorthSouth; // See if there's been a cursor override, otherwise we'll pick var cursor = gripper.ReadLocalValue(CursorProperty); if (cursor == DependencyProperty.UnsetValue || cursor == null) { - cursor = cursorToUse; - - // On UWP, we use the extension in XAML to control this behavior, - // so we'll update it here (and maintain binding). - // We'll keep it in-sync to maintain behavior for WinUI 3 as well. - gripper.SetValue(CursorProperty, cursor); + cursor = cursorByOrientation; + } - // We return here, as the Cursor will trigger this function again anyway to set for WinUI 3 - return; +#if !WINAPPSDK + // On UWP, we use our XAML extension to control this behavior, + // so we'll update it here (and maintain any cursor override). + if (cursor is CursorEnum cursorValue) + { + FrameworkElementExtensions.SetCursor(gripper, cursorValue); } + return; +#endif + // TODO: [UNO] Only supported on certain platforms // See ProtectedCursor here: https://github.com/unoplatform/uno/blob/3fe3862b270b99dbec4d830b547942af61b1a1d9/src/Uno.UI/UI/Xaml/UIElement.cs#L1015-L1023 #if WINAPPSDK && !HAS_UNO // Need to wait until we're at least applying template step of loading before setting Cursor // See https://github.com/microsoft/microsoft-ui-xaml/issues/7062 - if (gripper._applyingTemplate && - cursor is CursorEnum cursorToSet && + if (gripper._appliedTemplate && + cursor is CursorEnum cursorValue && (gripper.ProtectedCursor == null || (gripper.ProtectedCursor is InputSystemCursor current && - current.CursorShape != cursorToSet))) + current.CursorShape != cursorValue))) { - gripper.ProtectedCursor = InputSystemCursor.Create(cursorToSet); + gripper.ProtectedCursor = InputSystemCursor.Create(cursorValue); } #endif } } + private static void OnIsThumbVisiblePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + if (d is SizerBase gripper) + { + VisualStateManager.GoToState(gripper, gripper.IsThumbVisible ? VisibleState : CollapsedState, true); + } + } } diff --git a/components/SizerBase/src/SizerBase.cs b/components/SizerBase/src/SizerBase.cs index 10a5ea6b8..391f0dfc9 100644 --- a/components/SizerBase/src/SizerBase.cs +++ b/components/SizerBase/src/SizerBase.cs @@ -9,8 +9,28 @@ namespace CommunityToolkit.Labs.WinUI; /// /// Base class for splitting/resizing type controls like and . Acts similar to an enlarged type control, but with keyboard support. Subclasses should override the various abstract methods here to implement their behavior. /// + +[TemplateVisualState(Name = NormalState, GroupName = CommonStates)] +[TemplateVisualState(Name = PointerOverState, GroupName = CommonStates)] +[TemplateVisualState(Name = PressedState, GroupName = CommonStates)] +[TemplateVisualState(Name = DisabledState, GroupName = CommonStates)] +[TemplateVisualState(Name = HorizontalState, GroupName = OrientationStates)] +[TemplateVisualState(Name = VerticalState, GroupName = OrientationStates)] +[TemplateVisualState(Name = VisibleState, GroupName = ThumbVisibilityStates)] +[TemplateVisualState(Name = CollapsedState, GroupName = ThumbVisibilityStates)] public abstract partial class SizerBase : Control { + internal const string CommonStates = "CommonStates"; + internal const string NormalState = "Normal"; + internal const string PointerOverState = "PointerOver"; + internal const string PressedState = "Pressed"; + internal const string DisabledState = "Disabled"; + internal const string OrientationStates = "OrientationStates"; + internal const string HorizontalState = "Horizontal"; + internal const string VerticalState = "Vertical"; + internal const string ThumbVisibilityStates = "ThumbVisibilityStates"; + internal const string VisibleState = "Visible"; + internal const string CollapsedState = "Collapsed"; /// /// Called when the control has been initialized. /// @@ -21,7 +41,7 @@ protected virtual void OnLoaded(RoutedEventArgs e) /// /// Called when the control starts to be dragged by the user. - /// Implementor should record current state of manipulated target at this point in time. + /// Implementer should record current state of manipulated target at this point in time. /// They will receive the cumulative change in or /// based on the property. /// @@ -42,7 +62,7 @@ protected virtual void OnLoaded(RoutedEventArgs e) /// manipulation. This method will be used regardless of input device. It will already /// be adjusted for RightToLeft of the containing /// layout/settings. It will also already account for any settings such as - /// or . The implementor + /// or . The implementer /// just needs to use the provided value to manipulate their baseline stored /// in to provide the desired change. /// @@ -57,7 +77,7 @@ protected virtual void OnLoaded(RoutedEventArgs e) /// The value provided here is the cumulative change from the beginning of the /// manipulation. This method will be used regardless of input device. It will also /// already account for any settings such as or - /// . The implementor just needs + /// . The implementer just needs /// to use the provided value to manipulate their baseline stored /// in to provide the desired change. /// @@ -83,7 +103,7 @@ protected override AutomationPeer OnCreateAutomationPeer() // On Uno the ProtectedCursor isn't supported yet, so we don't need this value. #if WINAPPSDK && !HAS_UNO // Used to track when we're in the OnApplyTemplateStep to change ProtectedCursor value. - private bool _applyingTemplate = false; + private bool _appliedTemplate = false; #endif /// @@ -115,10 +135,13 @@ protected override void OnApplyTemplate() SizerBase_IsEnabledChanged(this, null!); #if WINAPPSDK && !HAS_UNO // On WinAppSDK, we'll trigger this to setup the initial ProtectedCursor value. - _applyingTemplate = true; + _appliedTemplate = true; #endif - // On UWP, we'll check the current Orientation and set the Cursor property to use here still. + // Ensure we have the proper cursor value setup, as we can only set now for WinUI 3 OnOrientationPropertyChanged(this, null!); + + // Ensure we set the Thumb visiblity + OnIsThumbVisiblePropertyChanged(this, null!); } private void SizerBase_Loaded(object sender, RoutedEventArgs e) diff --git a/components/SizerBase/src/SizerBase.xaml b/components/SizerBase/src/SizerBase.xaml index 58f991fc3..9f6f35b89 100644 --- a/components/SizerBase/src/SizerBase.xaml +++ b/components/SizerBase/src/SizerBase.xaml @@ -1,36 +1,50 @@  + xmlns:controls="using:CommunityToolkit.Labs.WinUI"> - - - + + + + + + + + + + + + - - - + + + + + - - - - + 24 + 4 + 2 + 4