feat: support top and bottom icon button.

This commit is contained in:
rabbitism
2024-01-27 15:09:38 +08:00
parent cfbf58e9aa
commit b46eb8c456
5 changed files with 97 additions and 37 deletions

View File

@@ -2,6 +2,7 @@
x:Class="Ursa.Demo.Pages.IconButtonDemo" x:Class="Ursa.Demo.Pages.IconButtonDemo"
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:common="clr-namespace:Ursa.Common;assembly=Ursa"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:u="https://irihi.tech/ursa" xmlns:u="https://irihi.tech/ursa"
@@ -11,18 +12,25 @@
<UserControl.Resources> <UserControl.Resources>
<StreamGeometry x:Key="iconGlyph">M12.0101 1C5.92171 1 1 5.92171 1 12.0101C1 16.8771 4.15354 20.9967 8.5284 22.455C9.07526 22.5644 9.27577 22.218 9.27577 21.9264C9.27577 21.6712 9.25754 20.7962 9.25754 19.8848C6.19514 20.541 5.55714 18.5723 5.55714 18.5723C5.06497 17.2963 4.33583 16.9682 4.33583 16.9682C3.33326 16.2938 4.40874 16.2938 4.40874 16.2938C5.52069 16.3667 6.104 17.4239 6.104 17.4239C7.08834 19.101 8.67423 18.627 9.31223 18.3354C9.40337 17.6245 9.69503 17.1323 10.0049 16.8589C7.56229 16.6037 4.99206 15.6558 4.99206 11.4267C4.99206 10.2237 5.42954 9.23931 6.12223 8.47371C6.01286 8.20028 5.63006 7.07011 6.2316 5.55714C6.2316 5.55714 7.16126 5.26548 9.25754 6.68731C10.1325 6.45034 11.0804 6.32274 12.0101 6.32274C12.9397 6.32274 13.8876 6.45034 14.7626 6.68731C16.8589 5.26548 17.7885 5.55714 17.7885 5.55714C18.3901 7.07011 18.0073 8.20028 17.8979 8.47371C18.6088 9.23931 19.0281 10.2237 19.0281 11.4267C19.0281 15.6558 16.4578 16.5854 13.997 16.8589C14.398 17.2052 14.7443 17.8614 14.7443 18.9004C14.7443 20.377 14.7261 21.5618 14.7261 21.9264C14.7261 22.218 14.9266 22.5644 15.4735 22.455C19.8483 20.9967 23.0019 16.8771 23.0019 12.0101C23.0201 5.92171 18.0802 1 12.0101 1Z</StreamGeometry> <StreamGeometry x:Key="iconGlyph">M12.0101 1C5.92171 1 1 5.92171 1 12.0101C1 16.8771 4.15354 20.9967 8.5284 22.455C9.07526 22.5644 9.27577 22.218 9.27577 21.9264C9.27577 21.6712 9.25754 20.7962 9.25754 19.8848C6.19514 20.541 5.55714 18.5723 5.55714 18.5723C5.06497 17.2963 4.33583 16.9682 4.33583 16.9682C3.33326 16.2938 4.40874 16.2938 4.40874 16.2938C5.52069 16.3667 6.104 17.4239 6.104 17.4239C7.08834 19.101 8.67423 18.627 9.31223 18.3354C9.40337 17.6245 9.69503 17.1323 10.0049 16.8589C7.56229 16.6037 4.99206 15.6558 4.99206 11.4267C4.99206 10.2237 5.42954 9.23931 6.12223 8.47371C6.01286 8.20028 5.63006 7.07011 6.2316 5.55714C6.2316 5.55714 7.16126 5.26548 9.25754 6.68731C10.1325 6.45034 11.0804 6.32274 12.0101 6.32274C12.9397 6.32274 13.8876 6.45034 14.7626 6.68731C16.8589 5.26548 17.7885 5.55714 17.7885 5.55714C18.3901 7.07011 18.0073 8.20028 17.8979 8.47371C18.6088 9.23931 19.0281 10.2237 19.0281 11.4267C19.0281 15.6558 16.4578 16.5854 13.997 16.8589C14.398 17.2052 14.7443 17.8614 14.7443 18.9004C14.7443 20.377 14.7261 21.5618 14.7261 21.9264C14.7261 22.218 14.9266 22.5644 15.4735 22.455C19.8483 20.9967 23.0019 16.8771 23.0019 12.0101C23.0201 5.92171 18.0802 1 12.0101 1Z</StreamGeometry>
</UserControl.Resources> </UserControl.Resources>
<StackPanel HorizontalAlignment="Left"> <StackPanel HorizontalAlignment="Left" Spacing="16">
<ToggleButton Name="loading" Content="Toggle Loading" /> <ToggleSwitch Name="loading" Content="Toggle Loading" />
<u:IconButton Content="Hello World" IsLoading="{Binding #loading.IsChecked}" /> <u:EnumSelector Name="placement" EnumType="{x:Type common:IconPlacement}" />
<u:IconButton Content="GitHub" IsLoading="{Binding #loading.IsChecked}"> <u:IconButton
Content="Hello World"
IconPlacement="{Binding #placement.Value}"
IsLoading="{Binding #loading.IsChecked}" />
<u:IconButton
Content="Hello Panda"
IconPlacement="{Binding #placement.Value}"
IsLoading="{Binding #loading.IsChecked}">
<u:IconButton.Icon> <u:IconButton.Icon>
<PathIcon <TextBlock Text="🐼" HorizontalAlignment="Center" FontSize="40" />
Width="14"
Height="14"
Data="{StaticResource iconGlyph}" />
</u:IconButton.Icon> </u:IconButton.Icon>
</u:IconButton> </u:IconButton>
<u:IconButton Content="GitHub" IsLoading="{Binding #loading.IsChecked}" IconPlacement="Right"> <u:IconButton
Content="GitHub"
IconPlacement="{Binding #placement.Value}"
IsLoading="{Binding #loading.IsChecked}">
<u:IconButton.Icon> <u:IconButton.Icon>
<PathIcon <PathIcon
Width="14" Width="14"
@@ -33,6 +41,7 @@
<u:IconButton <u:IconButton
Width="150" Width="150"
Content="GitHub" Content="GitHub"
IconPlacement="{Binding #placement.Value}"
IsLoading="{Binding #loading.IsChecked}"> IsLoading="{Binding #loading.IsChecked}">
<u:IconButton.Icon> <u:IconButton.Icon>
<PathIcon <PathIcon
@@ -45,6 +54,7 @@
Width="150" Width="150"
Classes="Warning" Classes="Warning"
Content="GitHub" Content="GitHub"
IconPlacement="{Binding #placement.Value}"
IsLoading="{Binding #loading.IsChecked}"> IsLoading="{Binding #loading.IsChecked}">
<u:IconButton.Icon> <u:IconButton.Icon>
<PathIcon <PathIcon
@@ -56,6 +66,7 @@
<u:IconButton <u:IconButton
Width="150" Width="150"
Content="GitHub" Content="GitHub"
IconPlacement="{Binding #placement.Value}"
IsLoading="{Binding #loading.IsChecked}" IsLoading="{Binding #loading.IsChecked}"
Theme="{DynamicResource SolidIconButton}"> Theme="{DynamicResource SolidIconButton}">
<u:IconButton.Icon> <u:IconButton.Icon>
@@ -69,6 +80,7 @@
Width="150" Width="150"
Classes="Warning" Classes="Warning"
Content="GitHub" Content="GitHub"
IconPlacement="{Binding #placement.Value}"
IsLoading="{Binding #loading.IsChecked}" IsLoading="{Binding #loading.IsChecked}"
Theme="{DynamicResource SolidIconButton}"> Theme="{DynamicResource SolidIconButton}">
<u:IconButton.Icon> <u:IconButton.Icon>
@@ -78,30 +90,5 @@
Data="{StaticResource iconGlyph}" /> Data="{StaticResource iconGlyph}" />
</u:IconButton.Icon> </u:IconButton.Icon>
</u:IconButton> </u:IconButton>
<u:IconButton
Width="150"
Content="GitHub"
IsLoading="{Binding #loading.IsChecked}"
Theme="{DynamicResource BorderlessIconButton}">
<u:IconButton.Icon>
<PathIcon
Width="14"
Height="14"
Data="{StaticResource iconGlyph}" />
</u:IconButton.Icon>
</u:IconButton>
<u:IconButton
Width="150"
Classes="Warning"
Content="GitHub"
IsLoading="{Binding #loading.IsChecked}"
Theme="{DynamicResource BorderlessIconButton}">
<u:IconButton.Icon>
<PathIcon
Width="14"
Height="14"
Data="{StaticResource iconGlyph}" />
</u:IconButton.Icon>
</u:IconButton>
</StackPanel> </StackPanel>
</UserControl> </UserControl>

View File

@@ -1,8 +1,10 @@
<ResourceDictionary <ResourceDictionary
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="clr-namespace:Ursa.Themes.Semi.Converters"
xmlns:u="https://irihi.tech/ursa"> xmlns:u="https://irihi.tech/ursa">
<!-- Add Resources Here --> <!-- Add Resources Here -->
<converters:BooleansToOpacityConverter x:Key="OpacityConverter" />
<ControlTheme x:Key="{x:Type u:IconButton}" TargetType="u:IconButton"> <ControlTheme x:Key="{x:Type u:IconButton}" TargetType="u:IconButton">
<Setter Property="Background" Value="{DynamicResource ButtonDefaultBackground}" /> <Setter Property="Background" Value="{DynamicResource ButtonDefaultBackground}" />
<Setter Property="Foreground" Value="{DynamicResource ButtonDefaultPrimaryForeground}" /> <Setter Property="Foreground" Value="{DynamicResource ButtonDefaultPrimaryForeground}" />
@@ -32,7 +34,8 @@
<Grid <Grid
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
ColumnDefinitions="Auto, Auto"> ColumnDefinitions="Auto, Auto"
RowDefinitions="Auto, Auto">
<Panel <Panel
Name="PART_IconRoot" Name="PART_IconRoot"
Grid.Column="0" Grid.Column="0"
@@ -49,7 +52,7 @@
<ContentPresenter <ContentPresenter
Content="{TemplateBinding Icon}" Content="{TemplateBinding Icon}"
ContentTemplate="{TemplateBinding IconTemplate}" ContentTemplate="{TemplateBinding IconTemplate}"
IsVisible="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=!IsLoading}" /> Opacity="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=!IsLoading, Converter={StaticResource OpacityConverter}}" />
<u:LoadingIcon <u:LoadingIcon
Classes="Small" Classes="Small"
Foreground="{TemplateBinding Foreground}" Foreground="{TemplateBinding Foreground}"
@@ -58,6 +61,8 @@
<ContentPresenter <ContentPresenter
Name="PART_ContentPresenter" Name="PART_ContentPresenter"
Grid.Column="1" Grid.Column="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{TemplateBinding Content}" /> Content="{TemplateBinding Content}" />
</Grid> </Grid>
</Border> </Border>
@@ -106,10 +111,48 @@
<Style Selector="^:right"> <Style Selector="^:right">
<Style Selector="^ /template/ Panel#PART_IconRoot"> <Style Selector="^ /template/ Panel#PART_IconRoot">
<Setter Property="Grid.Column" Value="1" /> <Setter Property="Grid.Column" Value="1" />
<Setter Property="Grid.Row" Value="0" />
<Setter Property="Margin" Value="8 0 0 0" /> <Setter Property="Margin" Value="8 0 0 0" />
</Style> </Style>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter"> <Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Grid.Column" Value="0" /> <Setter Property="Grid.Column" Value="0" />
<Setter Property="Grid.Row" Value="0" />
</Style>
</Style>
<Style Selector="^:left">
<Style Selector="^ /template/ Panel#PART_IconRoot">
<Setter Property="Grid.Column" Value="0" />
<Setter Property="Grid.Row" Value="0" />
<Setter Property="Margin" Value="0 0 8 0" />
</Style>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Grid.Column" Value="1" />
<Setter Property="Grid.Row" Value="0" />
</Style>
</Style>
<Style Selector="^:top">
<Style Selector="^ /template/ Panel#PART_IconRoot">
<Setter Property="Grid.Column" Value="0" />
<Setter Property="Grid.Row" Value="0" />
<Setter Property="Margin" Value="0 0 0 4" />
</Style>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Grid.Column" Value="0" />
<Setter Property="Grid.Row" Value="1" />
</Style>
</Style>
<Style Selector="^:bottom">
<Style Selector="^ /template/ Panel#PART_IconRoot">
<Setter Property="Grid.Column" Value="0" />
<Setter Property="Grid.Row" Value="1" />
<Setter Property="Margin" Value="0 4 0 0" />
</Style>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Grid.Column" Value="0" />
<Setter Property="Grid.Row" Value="0" />
</Style> </Style>
</Style> </Style>

View File

@@ -0,0 +1,21 @@
using System.Globalization;
using Avalonia.Data.Converters;
namespace Ursa.Themes.Semi.Converters;
public class BooleansToOpacityConverter: IValueConverter
{
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value is bool b)
{
return b? 1.0: 0.0;
}
return 1;
}
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

View File

@@ -3,5 +3,7 @@
public enum IconPlacement public enum IconPlacement
{ {
Left, Left,
Top,
Right, Right,
Bottom,
} }

View File

@@ -3,14 +3,18 @@ using Avalonia.Controls;
using Avalonia.Controls.Metadata; using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives; using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates; using Avalonia.Controls.Templates;
using Avalonia.Layout;
using Ursa.Common; using Ursa.Common;
namespace Ursa.Controls; namespace Ursa.Controls;
[PseudoClasses(PC_Right)] [PseudoClasses(PC_Right, PC_Left, PC_Top, PC_Bottom)]
public class IconButton: Button public class IconButton: Button
{ {
public const string PC_Right = ":right"; public const string PC_Right = ":right";
public const string PC_Left = ":left";
public const string PC_Top = ":top";
public const string PC_Bottom = ":bottom";
public static readonly StyledProperty<object?> IconProperty = AvaloniaProperty.Register<IconButton, object?>( public static readonly StyledProperty<object?> IconProperty = AvaloniaProperty.Register<IconButton, object?>(
nameof(Icon)); nameof(Icon));
@@ -64,6 +68,9 @@ public class IconButton: Button
private void SetPlacement(IconPlacement placement) private void SetPlacement(IconPlacement placement)
{ {
PseudoClasses.Set(PC_Left, placement == IconPlacement.Left);
PseudoClasses.Set(PC_Right, placement == IconPlacement.Right); PseudoClasses.Set(PC_Right, placement == IconPlacement.Right);
PseudoClasses.Set(PC_Top, placement == IconPlacement.Top);
PseudoClasses.Set(PC_Bottom, placement == IconPlacement.Bottom);
} }
} }