diff --git a/samples/ControlCatalog/MainView.xaml b/samples/ControlCatalog/MainView.xaml index facce2aa82..35fe45a25f 100644 --- a/samples/ControlCatalog/MainView.xaml +++ b/samples/ControlCatalog/MainView.xaml @@ -187,6 +187,14 @@ Mica + + + LeftToRight + RightToLeft + + diff --git a/samples/ControlCatalog/MainView.xaml.cs b/samples/ControlCatalog/MainView.xaml.cs index 79cf07c8d9..e8ea39abbb 100644 --- a/samples/ControlCatalog/MainView.xaml.cs +++ b/samples/ControlCatalog/MainView.xaml.cs @@ -76,6 +76,15 @@ namespace ControlCatalog } }; + var flowDirections = this.Find("FlowDirection"); + flowDirections.SelectionChanged += (sender, e) => + { + if (flowDirections.SelectedItem is FlowDirection flowDirection) + { + this.FlowDirection = flowDirection; + } + }; + var decorations = this.Find("Decorations"); decorations.SelectionChanged += (sender, e) => { diff --git a/src/Avalonia.Controls/Control.cs b/src/Avalonia.Controls/Control.cs index cec662aad8..265f46be5e 100644 --- a/src/Avalonia.Controls/Control.cs +++ b/src/Avalonia.Controls/Control.cs @@ -309,5 +309,79 @@ namespace Avalonia.Controls } } } + + static Control() + { + AffectsArrange(FlowDirectionProperty); + } + + private bool _mirrorApplied; + + protected virtual bool ShouldBeMirroredIfRightToLeft() + { + if (Parent is Control parent) + { + return parent.ShouldBeMirroredIfRightToLeft(); + } + else + { + return true; + } + } + + protected override void ArrangeCore(Rect finalRect) + { + base.ArrangeCore(finalRect); + + FlowDirection parentFD = FlowDirection.LeftToRight; + FlowDirection thisFD = FlowDirection; + bool shouldBeMirroredIfRightToLeft = ShouldBeMirroredIfRightToLeft(); + + if (Parent is Control control) + { + parentFD = control.FlowDirection; + } + + bool shouldMirror; + if (shouldBeMirroredIfRightToLeft) + { + shouldMirror = ShuoldApplyMirrorTransform(parentFD, thisFD); + if (this is PopupRoot && thisFD == FlowDirection.RightToLeft) + { + shouldMirror = true; + } + } + else + { + shouldMirror = ShuoldApplyMirrorTransform(parentFD, FlowDirection.LeftToRight); + } + + if (shouldMirror) + { + ApplyMirrorTransform(); + } + else + { + //RenderTransform = null; + } + } + + private void ApplyMirrorTransform() + { + if (_mirrorApplied) + { + return; + } + + var transform = new MatrixTransform(new Avalonia.Matrix(-1, 0, 0, 1, 0.0, 0.0)); + RenderTransform = transform; + _mirrorApplied = true; + } + + internal static bool ShuoldApplyMirrorTransform(FlowDirection parentFD, FlowDirection thisFD) + { + return ((parentFD == FlowDirection.LeftToRight && thisFD == FlowDirection.RightToLeft) || + (parentFD == FlowDirection.RightToLeft && thisFD == FlowDirection.LeftToRight)); + } } } diff --git a/src/Avalonia.Controls/TextBlock.cs b/src/Avalonia.Controls/TextBlock.cs index 09f22612de..d29f094c38 100644 --- a/src/Avalonia.Controls/TextBlock.cs +++ b/src/Avalonia.Controls/TextBlock.cs @@ -612,5 +612,7 @@ namespace Avalonia.Controls { InvalidateTextLayout(); } + + protected override bool ShouldBeMirroredIfRightToLeft() => false; } } diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index 4d71717776..76f7a185fe 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -1504,5 +1504,7 @@ namespace Avalonia.Controls } } } + + protected override bool ShouldBeMirroredIfRightToLeft() => false; } }