Skip to content

Commit

Permalink
Merge pull request #331 from dme-compunet/rtl-layout-compatibility
Browse files Browse the repository at this point in the history
Support for RTL Layout
  • Loading branch information
kikipoulet authored Nov 22, 2024
2 parents 99121b9 + 6c50861 commit 3bd45c2
Show file tree
Hide file tree
Showing 20 changed files with 124 additions and 32 deletions.
5 changes: 5 additions & 0 deletions SukiUI.Demo/App.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
xmlns:avaloniaEdit="https://github.com/avaloniaui/avaloniaedit"
xmlns:common="clr-namespace:SukiUI.Demo.Common"
xmlns:suki="https://github.com/kikipoulet/SukiUI"
RequestedThemeVariant="Default">
Expand Down Expand Up @@ -42,6 +43,9 @@
</Application.Resources>
<Application.Styles>
<FluentTheme></FluentTheme>
<Style Selector="avaloniaEdit|TextEditor">
<Setter Property="FlowDirection" Value="LeftToRight"/>
</Style>
<StyleInclude Source="avares://SukiUI.Dock/Index.axaml" />
<StyleInclude Source="avares://Avalonia.Controls.ColorPicker/Themes/Fluent/Fluent.xaml" />
<StyleInclude Source="avares://AvaloniaEdit/Themes/Fluent/AvaloniaEdit.xaml" />
Expand All @@ -50,6 +54,7 @@
<StyleInclude Source="avares://SukiUI.Demo/Styles/WrapPanelStyles.axaml" />
<StyleInclude Source="avares://SukiUI.Demo/Styles/TextStyles.axaml" />
<StyleInclude Source="avares://SukiUI.Demo/Styles/GlassCardStyles.axaml" />
<StyleInclude Source="avares://SukiUI.Demo/Styles/MaterialIconStyles.axaml" />
<avalonia:MaterialIconStyles />
</Application.Styles>

Expand Down
17 changes: 17 additions & 0 deletions SukiUI.Demo/Styles/MaterialIconStyles.axaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Styles xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:icons="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia">
<Design.PreviewWith>
<Border Padding="20">
<StackPanel FlowDirection="RightToLeft">
<icons:MaterialIcon Kind="Check" />
<icons:MaterialIcon Kind="Check" Classes="Flippable" />
</StackPanel>
</Border>
</Design.PreviewWith>

<Style Selector="icons|MaterialIcon:not(.Flippable)">
<Setter Property="FlowDirection" Value="LeftToRight"/>
</Style>

</Styles>
16 changes: 12 additions & 4 deletions SukiUI.Demo/SukiUIDemoView.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
<Grid ColumnDefinitions="*,20,*">

<suki:GlassCard CornerRadius="15" Padding="15">
<DockPanel FlowDirection="LeftToRight">
<DockPanel>
<Border Background="{DynamicResource SukiPrimaryColor}" Height="35" Padding="0" CornerRadius="100" Width="35">
<avalonia:MaterialIcon Height="20" Width="20" Kind="Wifi" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White"></avalonia:MaterialIcon>
</Border>
Expand All @@ -70,7 +70,7 @@
</DockPanel>
</suki:GlassCard>
<suki:GlassCard Grid.Column="2" CornerRadius="15" Padding="15">
<DockPanel FlowDirection="LeftToRight">
<DockPanel>
<suki:GlassCard Height="35" Padding="0" CornerRadius="100" Width="35">
<avalonia:MaterialIcon Height="20" Width="20" HorizontalAlignment="Center" VerticalAlignment="Center" Kind="Bluetooth" Foreground="{DynamicResource SukiText}"></avalonia:MaterialIcon>
</suki:GlassCard>
Expand All @@ -82,7 +82,7 @@

<suki:GlassCard CornerRadius="15" Padding="15">

<DockPanel FlowDirection="LeftToRight">
<DockPanel>
<TextBlock Text="Volume" Margin="0,0,0,10" FontSize="15"
DockPanel.Dock="Top" FontWeight="DemiBold"
VerticalAlignment="Center" />
Expand All @@ -94,7 +94,7 @@
</suki:GlassCard>

<suki:GlassCard CornerRadius="15" Padding="15">
<DockPanel FlowDirection="LeftToRight">
<DockPanel>
<ToggleSwitch VerticalAlignment="Center" DockPanel.Dock="Right" IsChecked="True" />
<TextBlock DockPanel.Dock="Bottom" Text="Disable notifications." Margin="0,8,0,0"
Foreground="{DynamicResource SukiLowText}"
Expand Down Expand Up @@ -138,6 +138,14 @@
Kind="{Binding TitleBarVisible, Converter={x:Static converters:BoolToIconConverters.Visibility}}" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Command="{Binding ToggleRightToLeftCommand}"
Header="Right To Left"
ToolTip.Tip="Toggles the right to left.">
<MenuItem.Icon>
<avalonia:MaterialIcon
Kind="SwapHorizontal" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Fullscreen"
PointerPressed="MakeFullScreenPressed"
ToolTip.Tip="Makes the app fullscreen." />
Expand Down
5 changes: 4 additions & 1 deletion SukiUI.Demo/SukiUIDemoViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,10 @@ private void ToggleTitleBar()
.WithContent($"Window title bar has been {(TitleBarVisible ? "shown" : "hidden")}.")
.Queue();
}


[RelayCommand]
private void ToggleRightToLeft() => _theme.IsRightToLeft = !_theme.IsRightToLeft;

[RelayCommand]
private static void OpenUrl(string url) => UrlUtilities.OpenUrl(url);

Expand Down
1 change: 1 addition & 0 deletions SukiUI/Controls/CodeView.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ public CodeView()
new PathIcon()
{
Data = Icons.ChevronRight,
Classes = { "Flippable" },
Foreground =
new Avalonia.Media.SolidColorBrush(
(Avalonia.Media.Color)Application.Current.FindRequiredResource("SukiText")),
Expand Down
2 changes: 1 addition & 1 deletion SukiUI/Controls/Stepper.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ private void AddStep(object step, int index, Grid grid, int stepCount)
};

var icon = new PathIcon
{ Height = 10, Width = 10, Data = Icons.ChevronRight, Margin = new Thickness(0, 0, 20, 0) };
{ Height = 10, Width = 10, Data = Icons.ChevronRight, Margin = new Thickness(0, 0, 20, 0), Classes = { "Flippable" } };
if (index == stepCount - 1)
{
icon.IsVisible = false;
Expand Down
1 change: 1 addition & 0 deletions SukiUI/Controls/SukiSideMenu.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
IsVisible="{TemplateBinding SidebarToggleEnabled}">
<Panel>
<PathIcon Name="PART_ExpandIcon"
Classes="Flippable"
Width="12"
Height="12"
Data="{x:Static content:Icons.ChevronLeft}"
Expand Down
3 changes: 2 additions & 1 deletion SukiUI/Controls/SukiStackPage.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,8 @@ private void AddChevron()
Width = 15,
Margin = new Thickness(15, -3, 15, 0),
HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center,
VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center
VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center,
Classes = { "Flippable" }
};
_disposables.Push(pathIcon.Bind(ForegroundProperty, ColorResource));
_stackHeaders!.Children.Add(pathIcon);
Expand Down
32 changes: 16 additions & 16 deletions SukiUI/Controls/SukiWindow.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<Setter Property="ExtendClientAreaTitleBarHeightHint" Value="-1" />
<Setter Property="ExtendClientAreaToDecorationsHint" Value="True" />
<Setter Property="TextElement.Foreground" Value="{DynamicResource SukiText}" />
<Setter Property="FlowDirection" Value="{DynamicResource FlowDirectionPrimary}" />
<Setter Property="Template">
<ControlTemplate>
<Border Margin="{TemplateBinding Margin}"
Expand Down Expand Up @@ -62,7 +63,6 @@
<DockPanel Margin="12,9" LastChildFill="True">
<StackPanel VerticalAlignment="Center"
DockPanel.Dock="Right"
FlowDirection="RightToLeft"
Orientation="Horizontal"
Spacing="7">
<StackPanel.Styles>
Expand All @@ -71,14 +71,13 @@
<Setter Property="Width" Value="10" />
</Style>
</StackPanel.Styles>
<Button Name="PART_CloseButton" Classes="Basic Rounded WindowControlsButton Close">
<PathIcon Data="{x:Static icons:Icons.WindowClose}" />
</Button>
<Button Name="PART_MaximizeButton"
Classes="Basic Rounded WindowControlsButton"
IsVisible="{TemplateBinding CanMaximize}">
<PathIcon x:Name="MaximizeIcon" Data="{x:Static icons:Icons.WindowMaximize}" />
</Button>
<ItemsControl ItemsSource="{TemplateBinding RightWindowTitleBarControls}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel FlowDirection="{DynamicResource FlowDirectionOpposite}" Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<Button Name="PART_MinimizeButton"
VerticalContentAlignment="Bottom"
Classes="Basic Rounded WindowControlsButton"
Expand All @@ -87,13 +86,14 @@
VerticalAlignment="Bottom"
Data="{x:Static icons:Icons.WindowMinimize}" />
</Button>
<ItemsControl ItemsSource="{TemplateBinding RightWindowTitleBarControls}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel FlowDirection="RightToLeft" Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<Button Name="PART_MaximizeButton"
Classes="Basic Rounded WindowControlsButton"
IsVisible="{TemplateBinding CanMaximize}">
<PathIcon x:Name="MaximizeIcon" Data="{x:Static icons:Icons.WindowMaximize}" />
</Button>
<Button Name="PART_CloseButton" Classes="Basic Rounded WindowControlsButton Close">
<PathIcon Data="{x:Static icons:Icons.WindowClose}" />
</Button>
</StackPanel>
<StackPanel VerticalAlignment="Center"
IsHitTestVisible="False"
Expand Down
9 changes: 6 additions & 3 deletions SukiUI/Controls/SukiWindow.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -302,12 +302,15 @@ private void EnableWindowsSnapLayout(Button maximize)
var point = new PixelPoint(
(short)(ToInt32(lParam) & 0xffff),
(short)(ToInt32(lParam) >> 16));
var buttonLeftTop = maximize.PointToScreen(new Point(0, 0));
var desiredSize = maximize.DesiredSize;
var buttonLeftTop = maximize.PointToScreen(FlowDirection == FlowDirection.LeftToRight
? new Point(desiredSize.Width, 0)
: new Point(0, 0));
var x = (buttonLeftTop.X - point.X) / RenderScaling;
var y = (point.Y - buttonLeftTop.Y) / RenderScaling;
if (new Rect(0, 0,
maximize.DesiredSize.Width,
maximize.DesiredSize.Height)
desiredSize.Width,
desiredSize.Height)
.Contains(new Point(x, y)))
{
setter?.SetValue(maximize, true);
Expand Down
4 changes: 2 additions & 2 deletions SukiUI/Theme/Calendar/CalendarItem.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@
<Button Name="PART_PreviousButton"
Grid.Column="2"
Classes="NavButton Basic">
<PathIcon Classes="Primary" Data="{x:Static content:Icons.ChevronLeft}" />
<PathIcon Classes="Primary Flippable" Data="{x:Static content:Icons.ChevronLeft}" />
</Button>

<Button Name="PART_NextButton"
Grid.Column="3"
Classes="NavButton Basic">
<PathIcon Classes="Primary" Data="{x:Static content:Icons.ChevronRight}" />
<PathIcon Classes="Primary Flippable" Data="{x:Static content:Icons.ChevronRight}" />
</Button>
</Grid>

Expand Down
1 change: 1 addition & 0 deletions SukiUI/Theme/CheckBoxStyles.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
Margin="1,1,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FlowDirection="LeftToRight"
Data="M 1145.607177734375,430 C1145.607177734375,430 1141.449951171875,435.0772705078125 1141.449951171875,435.0772705078125 1141.449951171875,435.0772705078125 1139.232177734375,433.0999755859375 1139.232177734375,433.0999755859375 1139.232177734375,433.0999755859375 1138,434.5538330078125 1138,434.5538330078125 1138,434.5538330078125 1141.482177734375,438 1141.482177734375,438 1141.482177734375,438 1141.96875,437.9375 1141.96875,437.9375 1141.96875,437.9375 1147,431.34619140625 1147,431.34619140625 1147,431.34619140625 1145.607177734375,430 1145.607177734375,430 z"
Fill="White"
Stretch="Uniform" >
Expand Down
2 changes: 2 additions & 0 deletions SukiUI/Theme/Index.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
<StyleInclude Source="avares://SukiUI/Theme/ScrollViewerStyles.axaml" />
<StyleInclude Source="avares://SukiUI/Theme/ButtonLoadingStyles.axaml" />

<StyleInclude Source="avares://SukiUI/Theme/PathIconStyles.axaml" />

<Styles.Resources>
<ResourceDictionary>

Expand Down
31 changes: 31 additions & 0 deletions SukiUI/Theme/Index.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ public partial class SukiTheme : Styles
AvaloniaProperty.Register<SukiTheme, SukiColor>(nameof(Color), defaultBindingMode: BindingMode.OneTime,
defaultValue: SukiColor.Blue);

public static readonly StyledProperty<bool> IsRightToLeftProperty =
AvaloniaProperty.Register<SukiTheme, bool>(nameof(IsRightToLeft), defaultBindingMode: BindingMode.OneTime,
defaultValue: false);

/// <summary>
/// Used to assign the ColorTheme at launch,
/// </summary>
Expand All @@ -32,6 +36,12 @@ public SukiColor ThemeColor
}
}

public bool IsRightToLeft
{
get => GetValue(IsRightToLeftProperty);
set => SetValue(IsRightToLeftProperty, value);
}

/// <summary>
/// Called whenever the application's <see cref="SukiColorTheme"/> is changed.
/// Useful where controls cannot use "DynamicResource"
Expand Down Expand Up @@ -74,6 +84,18 @@ public SukiTheme()
_app.ActualThemeVariantChanged += (_, e) => OnBaseThemeChanged?.Invoke(_app.ActualThemeVariant);
foreach (var theme in DefaultColorThemes)
AddColorTheme(theme.Value);

UpdateFlowDirectionResources(IsRightToLeft);
}

protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
if (change.Property == IsRightToLeftProperty)
{
UpdateFlowDirectionResources(change.GetNewValue<bool>());
}

base.OnPropertyChanged(change);
}

/// <summary>
Expand Down Expand Up @@ -152,6 +174,15 @@ public void SwitchBaseTheme()
Application.Current.RequestedThemeVariant = newBase;
}

private void UpdateFlowDirectionResources(bool rightToLeft)
{
var primary = rightToLeft ? FlowDirection.RightToLeft : FlowDirection.LeftToRight;
var opposite = rightToLeft ? FlowDirection.LeftToRight : FlowDirection.RightToLeft;

Resources["FlowDirectionPrimary"] = primary;
Resources["FlowDirectionOpposite"] = opposite;
}

/// <summary>
/// Initializes the color theme resources whenever the property is changed.
/// In an ideal world people wouldn't use the property
Expand Down
3 changes: 2 additions & 1 deletion SukiUI/Theme/ManagedFileChooserConverters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ public class TextToPathConverter : IValueConverter
var p = new PathIcon
{
Height = 6, Margin = new Thickness(12, 4, 12, 2), Width = 5, Data = Icons.ChevronRight,
IsVisible = i != pathes.Length - 1, VerticalAlignment = VerticalAlignment.Center
IsVisible = i != pathes.Length - 1, VerticalAlignment = VerticalAlignment.Center,
Classes = { "Flippable" }
};

p[!TemplatedControl.ForegroundProperty] = new DynamicResourceExtension("SukiLowText");
Expand Down
5 changes: 5 additions & 0 deletions SukiUI/Theme/MenuItem.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
DockPanel.Dock="Left"
Fill="{DynamicResource SukiLightBorderBrush}" />
<PathIcon Name="PART_RightArrow"
Classes="Flippable"
Width="8"
Height="8"
Margin="5,0,10,0"
Expand Down Expand Up @@ -149,6 +150,10 @@
</ControlTemplate>
</Setter>
</Style>

<Style Selector="^[FlowDirection=RightToLeft] /template/ Popup#PART_Popup">
<Setter Property="HorizontalOffset" Value="25"/>
</Style>
</ControlTheme>
<ControlTheme x:Key="{x:Type MenuItem}"
BasedOn="{StaticResource SukiMenuItemStyle}"
Expand Down
Loading

0 comments on commit 3bd45c2

Please sign in to comment.