From 8e9ec700b2da48038317652f33f784c57f0fc949 Mon Sep 17 00:00:00 2001 From: daniel mayost Date: Mon, 21 Mar 2022 10:32:07 +0200 Subject: [PATCH] fix ComboBox and start working Popup --- src/Avalonia.Controls/ComboBox.cs | 19 +++++++++ src/Avalonia.Controls/Control.cs | 40 +++++++++---------- src/Avalonia.Controls/MenuItem.cs | 31 ++++++++++++++ src/Avalonia.Controls/TopLevel.cs | 4 ++ .../Controls/MenuItem.xaml | 2 +- src/Avalonia.Visuals/Visual.cs | 2 +- src/Avalonia.Visuals/VisualTree/IVisual.cs | 2 +- 7 files changed, 76 insertions(+), 24 deletions(-) diff --git a/src/Avalonia.Controls/ComboBox.cs b/src/Avalonia.Controls/ComboBox.cs index c5410ae9b0..f209a07a31 100644 --- a/src/Avalonia.Controls/ComboBox.cs +++ b/src/Avalonia.Controls/ComboBox.cs @@ -13,6 +13,7 @@ using Avalonia.Interactivity; using Avalonia.Layout; using Avalonia.Media; using Avalonia.VisualTree; +using Avalonia.LogicalTree; namespace Avalonia.Controls { @@ -182,6 +183,24 @@ namespace Avalonia.Controls this.UpdateSelectionBoxItem(SelectedItem); } + // Because the SelectedItem isn't connected to the visual tree + public override void InvalidateFlowDirection() + { + if (SelectedItem is Control selectedControl) + { + selectedControl.InvalidateFlowDirection(); + foreach (var logical in selectedControl.GetLogicalDescendants()) + { + if (logical is Control childControl) + { + childControl.InvalidateFlowDirection(); + } + } + } + + base.InvalidateFlowDirection(); + } + /// protected override void OnKeyDown(KeyEventArgs e) { diff --git a/src/Avalonia.Controls/Control.cs b/src/Avalonia.Controls/Control.cs index 852b6e2580..70ba24c5bd 100644 --- a/src/Avalonia.Controls/Control.cs +++ b/src/Avalonia.Controls/Control.cs @@ -190,6 +190,7 @@ namespace Avalonia.Controls { base.OnAttachedToVisualTreeCore(e); + InvalidateFlowDirection(); InitializeIfNeeded(); } @@ -317,25 +318,29 @@ namespace Avalonia.Controls if (change.Property == FlowDirectionProperty) { // A change in value inherited should be prevented from calling this method - // Because it will be handled from here by NotifyDescendantFlowDirection + // because it will be handled from here if (GetBaseValue(FlowDirectionProperty, change.Priority).HasValue) { InvalidateFlowDirection(); - NotifyDescendantFlowDirection(); + + foreach (var visual in this.GetVisualDescendants()) + { + if (visual is Control child) + { + child.InvalidateFlowDirection(); + } + } InvalidateVisual(); } } } - protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) - { - base.OnAttachedToVisualTree(e); - - InvalidateFlowDirection(); - } - - private void InvalidateFlowDirection() + /// + /// Computes the value according to the + /// + /// + public virtual void InvalidateFlowDirection() { bool parentShouldPresentedMirrored = false; bool thisShouldPresentedMirrored = ShouldPresentedMirrored(); @@ -345,23 +350,16 @@ namespace Avalonia.Controls { parentShouldPresentedMirrored = parent.ShouldPresentedMirrored(); } + else if (this.Parent is Control logicalParent) + { + parentShouldPresentedMirrored = logicalParent.ShouldPresentedMirrored(); + } bool shouldApplyMirrorTransform = thisShouldPresentedMirrored != parentShouldPresentedMirrored; IsMirrorTransform = shouldApplyMirrorTransform; } - private void NotifyDescendantFlowDirection() - { - foreach (var visual in this.GetVisualDescendants()) - { - if (visual is Control child) - { - child.InvalidateFlowDirection(); - } - } - } - /// /// Determines whether the element should be presented mirrored, this /// method related to FlowDirection system and returns true if FlowDirection diff --git a/src/Avalonia.Controls/MenuItem.cs b/src/Avalonia.Controls/MenuItem.cs index 34215e9713..b35fe818aa 100644 --- a/src/Avalonia.Controls/MenuItem.cs +++ b/src/Avalonia.Controls/MenuItem.cs @@ -14,6 +14,8 @@ using Avalonia.Input; using Avalonia.Interactivity; using Avalonia.LogicalTree; using Avalonia.VisualTree; +using Avalonia.Media; +using Avalonia.Controls.Primitives.PopupPositioning; namespace Avalonia.Controls { @@ -409,6 +411,33 @@ namespace Avalonia.Controls } } + public override void InvalidateFlowDirection() + { + if (_popup != null && Parent is Menu) + { + var popupAnchor = FlowDirection == FlowDirection.LeftToRight ? + PopupAnchor.BottomLeft : PopupAnchor.BottomRight; + + var popupGravity = FlowDirection == FlowDirection.LeftToRight ? + PopupGravity.BottomRight : PopupGravity.BottomLeft; + + var placement = FlowDirection == FlowDirection.LeftToRight ? + PlacementMode.Right : PlacementMode.Left; + + _popup.PlacementAnchor = popupAnchor; + _popup.PlacementGravity = popupGravity; + } + else if (_popup != null) + { + var placement = FlowDirection == FlowDirection.LeftToRight ? + PlacementMode.Right : PlacementMode.Left; + + _popup.PlacementMode = placement; + } + + base.InvalidateFlowDirection(); + } + /// /// Called when the is clicked. /// @@ -493,6 +522,8 @@ namespace Avalonia.Controls _popup.Opened += PopupOpened; _popup.Closed += PopupClosed; } + + InvalidateFlowDirection(); } protected override AutomationPeer OnCreateAutomationPeer() diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index 71b8c09e28..f1b311dc52 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -530,6 +530,10 @@ namespace Avalonia.Controls ITextInputMethodImpl? ITextInputMethodRoot.InputMethod => (PlatformImpl as ITopLevelImplWithTextInputMethod)?.TextInputMethod; + public override void InvalidateFlowDirection() + { + } + protected override bool ShouldPresentedMirrored() => false; } } diff --git a/src/Avalonia.Themes.Fluent/Controls/MenuItem.xaml b/src/Avalonia.Themes.Fluent/Controls/MenuItem.xaml index 831537f578..45949fee92 100644 --- a/src/Avalonia.Themes.Fluent/Controls/MenuItem.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/MenuItem.xaml @@ -111,7 +111,6 @@ @@ -160,6 +159,7 @@ - /// Gets or sets a value indicating whether this control presented as mirror. + /// Gets or sets a value indicating whether to apply mirror transform on this control. /// public bool IsMirrorTransform { diff --git a/src/Avalonia.Visuals/VisualTree/IVisual.cs b/src/Avalonia.Visuals/VisualTree/IVisual.cs index 95fe665e89..58c6cfa0e1 100644 --- a/src/Avalonia.Visuals/VisualTree/IVisual.cs +++ b/src/Avalonia.Visuals/VisualTree/IVisual.cs @@ -76,7 +76,7 @@ namespace Avalonia.VisualTree IBrush? OpacityMask { get; set; } /// - /// Gets a value indicating whether this control presented as mirror. + /// Gets a value indicating whether to apply mirror transform on this control. /// bool IsMirrorTransform { get; }