feat: add theme and function.
This commit is contained in:
@@ -1,22 +0,0 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public class BackTopButton: Button
|
||||
{
|
||||
public static readonly StyledProperty<Control> TargetProperty = AvaloniaProperty.Register<BackTopButton, Control>(
|
||||
nameof(Target));
|
||||
|
||||
public Control Target
|
||||
{
|
||||
get => GetValue(TargetProperty);
|
||||
set => SetValue(TargetProperty, value);
|
||||
}
|
||||
|
||||
protected override void OnClick()
|
||||
{
|
||||
base.OnClick();
|
||||
|
||||
}
|
||||
}
|
||||
64
src/Ursa/Controls/BackTop/ScrollTo.cs
Normal file
64
src/Ursa/Controls/BackTop/ScrollTo.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Notifications;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.LogicalTree;
|
||||
using Avalonia.Styling;
|
||||
using Ursa.Common;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public class ScrollTo
|
||||
{
|
||||
public static readonly AttachedProperty<Position> DirectionProperty =
|
||||
AvaloniaProperty.RegisterAttached<ScrollTo, Control, Position>("Direction");
|
||||
|
||||
public static void SetDirection(Control obj, Position value) => obj.SetValue(DirectionProperty, value);
|
||||
public static Position GetDirection(Control obj) => obj.GetValue(DirectionProperty);
|
||||
|
||||
public static readonly AttachedProperty<ControlTheme?> ButtonThemeProperty =
|
||||
AvaloniaProperty.RegisterAttached<ScrollTo, Control, ControlTheme?>("ButtonTheme");
|
||||
|
||||
public static void SetButtonTheme(Control obj, ControlTheme? value) => obj.SetValue(ButtonThemeProperty, value);
|
||||
public static ControlTheme? GetButtonTheme(Control obj) => obj.GetValue(ButtonThemeProperty);
|
||||
|
||||
static ScrollTo()
|
||||
{
|
||||
DirectionProperty.Changed.AddClassHandler<Control, Position>(OnDirectionChanged);
|
||||
ButtonThemeProperty.Changed.AddClassHandler<Control, ControlTheme?>(OnButtonThemeChanged);
|
||||
}
|
||||
|
||||
private static void OnButtonThemeChanged(Control arg1, AvaloniaPropertyChangedEventArgs<ControlTheme?> arg2)
|
||||
{
|
||||
var button = EnsureButtonInAdorner(arg1);
|
||||
if (button is null) return;
|
||||
button.SetCurrentValue(StyledElement.ThemeProperty, arg2.NewValue.Value);
|
||||
}
|
||||
|
||||
private static void OnDirectionChanged(Control control, AvaloniaPropertyChangedEventArgs<Position> args)
|
||||
{
|
||||
var button = EnsureButtonInAdorner(control);
|
||||
if (button is null) return;
|
||||
button.SetCurrentValue(ScrollToButton.DirectionProperty, args.NewValue.Value);
|
||||
}
|
||||
|
||||
private static ScrollToButton? EnsureButtonInAdorner(Control control)
|
||||
{
|
||||
var scroll = control.GetSelfAndLogicalDescendants().OfType<ScrollViewer>().FirstOrDefault();
|
||||
if (scroll is null) return null;
|
||||
var adorner = AdornerLayer.GetAdorner(scroll);
|
||||
if (adorner is not ScrollToButton button)
|
||||
{
|
||||
button = new ScrollToButton();
|
||||
AdornerLayer.SetAdorner(control, button);
|
||||
}
|
||||
button.SetCurrentValue(ScrollToButton.TargetProperty, scroll);
|
||||
button.SetCurrentValue(ScrollToButton.DirectionProperty, GetDirection(control));
|
||||
if ( GetButtonTheme(control) is { } theme)
|
||||
{
|
||||
button.SetCurrentValue(StyledElement.ThemeProperty, theme);
|
||||
}
|
||||
return button;
|
||||
}
|
||||
}
|
||||
116
src/Ursa/Controls/BackTop/ScrollToButton.cs
Normal file
116
src/Ursa/Controls/BackTop/ScrollToButton.cs
Normal file
@@ -0,0 +1,116 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.LogicalTree;
|
||||
using Irihi.Avalonia.Shared.Helpers;
|
||||
using Ursa.Common;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public class ScrollToButton: Button
|
||||
{
|
||||
private ScrollViewer? _scroll;
|
||||
private IDisposable? _disposable;
|
||||
|
||||
public static readonly StyledProperty<Control> TargetProperty = AvaloniaProperty.Register<ScrollToButton, Control>(
|
||||
nameof(Target));
|
||||
|
||||
public Control Target
|
||||
{
|
||||
get => GetValue(TargetProperty);
|
||||
set => SetValue(TargetProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<Position> DirectionProperty = AvaloniaProperty.Register<ScrollToButton, Position>(
|
||||
nameof(Direction));
|
||||
|
||||
public Position Direction
|
||||
{
|
||||
get => GetValue(DirectionProperty);
|
||||
set => SetValue(DirectionProperty, value);
|
||||
}
|
||||
|
||||
static ScrollToButton()
|
||||
{
|
||||
TargetProperty.Changed.AddClassHandler<ScrollToButton, Control>((o,e)=>o.OnTargetChanged(e));
|
||||
DirectionProperty.Changed.AddClassHandler<ScrollToButton, Position>((o,e)=>o.OnDirectionChanged(e));
|
||||
}
|
||||
|
||||
private void OnDirectionChanged(AvaloniaPropertyChangedEventArgs<Position> avaloniaPropertyChangedEventArgs)
|
||||
{
|
||||
if (_scroll is null) return;
|
||||
SetVisibility(avaloniaPropertyChangedEventArgs.NewValue.Value, _scroll.Offset);
|
||||
}
|
||||
|
||||
private void OnTargetChanged(AvaloniaPropertyChangedEventArgs<Control> arg2)
|
||||
{
|
||||
_disposable?.Dispose();
|
||||
if (arg2.NewValue.Value is { } newValue)
|
||||
{
|
||||
var scroll = newValue.GetSelfAndLogicalDescendants().OfType<ScrollViewer>().FirstOrDefault();
|
||||
if (_scroll is not null)
|
||||
{
|
||||
_disposable?.Dispose();
|
||||
}
|
||||
_scroll = scroll;
|
||||
_disposable = ScrollViewer.OffsetProperty.Changed.AddClassHandler<ScrollViewer, Vector>(OnScrollChanged);
|
||||
SetVisibility(Direction, _scroll?.Offset);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnClick()
|
||||
{
|
||||
var vector = Direction switch
|
||||
{
|
||||
Position.Top => new Vector(0, double.NegativeInfinity),
|
||||
Position.Bottom => new Vector(0, double.PositiveInfinity),
|
||||
Position.Left => new Vector(double.NegativeInfinity, 0),
|
||||
Position.Right => new Vector(double.PositiveInfinity, 0),
|
||||
_ => new Vector(0, 0)
|
||||
};
|
||||
_scroll?.SetCurrentValue(ScrollViewer.OffsetProperty, vector);
|
||||
}
|
||||
|
||||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnAttachedToVisualTree(e);
|
||||
var scroll = Target.GetSelfAndLogicalDescendants().OfType<ScrollViewer>().FirstOrDefault();
|
||||
if (_scroll is not null)
|
||||
{
|
||||
_disposable?.Dispose();
|
||||
}
|
||||
_scroll = scroll;
|
||||
_disposable = ScrollViewer.OffsetProperty.Changed.AddClassHandler<ScrollViewer, Vector>(OnScrollChanged);
|
||||
SetVisibility(Direction, _scroll?.Offset);
|
||||
}
|
||||
|
||||
private void OnScrollChanged(ScrollViewer arg1, AvaloniaPropertyChangedEventArgs<Vector> arg2)
|
||||
{
|
||||
if (arg1 != _scroll) return;
|
||||
SetVisibility(Direction, arg2.NewValue.Value);
|
||||
}
|
||||
|
||||
private void SetVisibility(Position direction, Vector? vector)
|
||||
{
|
||||
if (vector is null) return;
|
||||
if (direction == Position.Bottom && vector.Value.Y < 0)
|
||||
{
|
||||
IsVisible = true;
|
||||
}
|
||||
else if (direction == Position.Top && vector.Value.Y > 0)
|
||||
{
|
||||
IsVisible = true;
|
||||
}
|
||||
else if (direction == Position.Left && vector.Value.X < 0)
|
||||
{
|
||||
IsVisible = true;
|
||||
}
|
||||
else if (direction == Position.Right && vector.Value.X > 0)
|
||||
{
|
||||
IsVisible = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
IsVisible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user