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;
}
}