WIP: animation.
This commit is contained in:
@@ -8,6 +8,7 @@ public static class MenuKeys
|
|||||||
public const string MenuKeyButtonGroup = "ButtonGroup";
|
public const string MenuKeyButtonGroup = "ButtonGroup";
|
||||||
public const string MenuKeyDialog = "Dialog";
|
public const string MenuKeyDialog = "Dialog";
|
||||||
public const string MenuKeyDivider = "Divider";
|
public const string MenuKeyDivider = "Divider";
|
||||||
|
public const string MenuKeyDrawer = "Drawer";
|
||||||
public const string MenuKeyDualBadge = "DualBadge";
|
public const string MenuKeyDualBadge = "DualBadge";
|
||||||
public const string MenuKeyEnumSelector = "EnumSelector";
|
public const string MenuKeyEnumSelector = "EnumSelector";
|
||||||
public const string MenuKeyImageViewer = "ImageViewer";
|
public const string MenuKeyImageViewer = "ImageViewer";
|
||||||
|
|||||||
14
demo/Ursa.Demo/Pages/DrawerDemo.axaml
Normal file
14
demo/Ursa.Demo/Pages/DrawerDemo.axaml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="800"
|
||||||
|
xmlns:vm="clr-namespace:Ursa.Demo.ViewModels;assembly=Ursa.Demo"
|
||||||
|
x:DataType="vm:DrawerDemoViewModel"
|
||||||
|
x:CompileBindings="True"
|
||||||
|
d:DesignHeight="450"
|
||||||
|
x:Class="Ursa.Demo.Pages.DrawerDemo">
|
||||||
|
<StackPanel HorizontalAlignment="Left">
|
||||||
|
<Button Content="Call Drawer" Command="{Binding OpenDrawerCommand}"></Button>
|
||||||
|
</StackPanel>
|
||||||
|
</UserControl>
|
||||||
13
demo/Ursa.Demo/Pages/DrawerDemo.axaml.cs
Normal file
13
demo/Ursa.Demo/Pages/DrawerDemo.axaml.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Markup.Xaml;
|
||||||
|
|
||||||
|
namespace Ursa.Demo.Pages;
|
||||||
|
|
||||||
|
public partial class DrawerDemo : UserControl
|
||||||
|
{
|
||||||
|
public DrawerDemo()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
23
demo/Ursa.Demo/ViewModels/DrawerDemoViewModel.cs
Normal file
23
demo/Ursa.Demo/ViewModels/DrawerDemoViewModel.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
using Ursa.Controls;
|
||||||
|
|
||||||
|
namespace Ursa.Demo.ViewModels;
|
||||||
|
|
||||||
|
public class DrawerDemoViewModel: ObservableObject
|
||||||
|
{
|
||||||
|
public ICommand OpenDrawerCommand { get; set; }
|
||||||
|
|
||||||
|
public DrawerDemoViewModel()
|
||||||
|
{
|
||||||
|
OpenDrawerCommand = new AsyncRelayCommand(OpenDrawer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OpenDrawer()
|
||||||
|
{
|
||||||
|
await Drawer.Show<Calendar, string, bool>("Hello World");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,6 +30,7 @@ public class MainViewViewModel : ViewModelBase
|
|||||||
MenuKeys.MenuKeyButtonGroup => new ButtonGroupDemoViewModel(),
|
MenuKeys.MenuKeyButtonGroup => new ButtonGroupDemoViewModel(),
|
||||||
MenuKeys.MenuKeyDialog => new DialogDemoViewModel(),
|
MenuKeys.MenuKeyDialog => new DialogDemoViewModel(),
|
||||||
MenuKeys.MenuKeyDivider => new DividerDemoViewModel(),
|
MenuKeys.MenuKeyDivider => new DividerDemoViewModel(),
|
||||||
|
MenuKeys.MenuKeyDrawer => new DrawerDemoViewModel(),
|
||||||
MenuKeys.MenuKeyDualBadge => new DualBadgeDemoViewModel(),
|
MenuKeys.MenuKeyDualBadge => new DualBadgeDemoViewModel(),
|
||||||
MenuKeys.MenuKeyEnumSelector => new EnumSelectorDemoViewModel(),
|
MenuKeys.MenuKeyEnumSelector => new EnumSelectorDemoViewModel(),
|
||||||
MenuKeys.MenuKeyImageViewer => new ImageViewerDemoViewModel(),
|
MenuKeys.MenuKeyImageViewer => new ImageViewerDemoViewModel(),
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ public class MenuViewModel: ViewModelBase
|
|||||||
new() { MenuHeader = "Button Group", Key = MenuKeys.MenuKeyButtonGroup, Status = "Updated"},
|
new() { MenuHeader = "Button Group", Key = MenuKeys.MenuKeyButtonGroup, Status = "Updated"},
|
||||||
new() { MenuHeader = "Dialog", Key = MenuKeys.MenuKeyDialog },
|
new() { MenuHeader = "Dialog", Key = MenuKeys.MenuKeyDialog },
|
||||||
new() { MenuHeader = "Divider", Key = MenuKeys.MenuKeyDivider },
|
new() { MenuHeader = "Divider", Key = MenuKeys.MenuKeyDivider },
|
||||||
|
new() { MenuHeader = "Drawer", Key = MenuKeys.MenuKeyDrawer },
|
||||||
new() { MenuHeader = "DualBadge", Key = MenuKeys.MenuKeyDualBadge },
|
new() { MenuHeader = "DualBadge", Key = MenuKeys.MenuKeyDualBadge },
|
||||||
new() { MenuHeader = "Enum Selector", Key = MenuKeys.MenuKeyEnumSelector },
|
new() { MenuHeader = "Enum Selector", Key = MenuKeys.MenuKeyEnumSelector },
|
||||||
new() { MenuHeader = "Icon Button", Key = MenuKeys.MenuKeyIconButton },
|
new() { MenuHeader = "Icon Button", Key = MenuKeys.MenuKeyIconButton },
|
||||||
|
|||||||
44
src/Ursa.Themes.Semi/Controls/Drawer.axaml
Normal file
44
src/Ursa.Themes.Semi/Controls/Drawer.axaml
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:u="https://irihi.tech/ursa">
|
||||||
|
<ControlTheme TargetType="u:CustomDrawerControl" x:Key="{x:Type u:CustomDrawerControl}">
|
||||||
|
<Setter Property="VerticalAlignment" Value="Stretch"></Setter>
|
||||||
|
<Setter Property="MinWidth" Value="400"></Setter>
|
||||||
|
<Setter Property="Template">
|
||||||
|
<ControlTemplate TargetType="u:CustomDrawerControl">
|
||||||
|
<Border Margin="8 0 0 0"
|
||||||
|
Padding="0"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
VerticalAlignment="Stretch"
|
||||||
|
Classes="Shadow"
|
||||||
|
ClipToBounds="False"
|
||||||
|
CornerRadius="12 0 0 12"
|
||||||
|
IsHitTestVisible="True"
|
||||||
|
Theme="{DynamicResource CardBorder}">
|
||||||
|
<Border ClipToBounds="True" CornerRadius="12 0 0 12">
|
||||||
|
<Grid RowDefinitions="Auto, *">
|
||||||
|
<ContentPresenter
|
||||||
|
Name="PART_ContentPresenter"
|
||||||
|
Grid.Row="0"
|
||||||
|
Grid.RowSpan="2"
|
||||||
|
Content="{TemplateBinding Content}" />
|
||||||
|
<Grid Grid.Row="0" ColumnDefinitions="*, Auto">
|
||||||
|
<Panel
|
||||||
|
Name="{x:Static u:DialogControl.PART_TitleArea}"
|
||||||
|
Grid.Column="0"
|
||||||
|
Grid.ColumnSpan="2"
|
||||||
|
Background="Transparent" />
|
||||||
|
<Button
|
||||||
|
Name="{x:Static u:MessageBoxWindow.PART_CloseButton}"
|
||||||
|
Grid.Column="1"
|
||||||
|
Margin="0,24,24,0"
|
||||||
|
DockPanel.Dock="Right"
|
||||||
|
Theme="{DynamicResource CloseButton}" />
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
</Border>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter>
|
||||||
|
</ControlTheme>
|
||||||
|
</ResourceDictionary>
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
<ResourceInclude Source="Dialog.axaml" />
|
<ResourceInclude Source="Dialog.axaml" />
|
||||||
<ResourceInclude Source="DialogShared.axaml" />
|
<ResourceInclude Source="DialogShared.axaml" />
|
||||||
<ResourceInclude Source="Divider.axaml" />
|
<ResourceInclude Source="Divider.axaml" />
|
||||||
|
<ResourceInclude Source="Drawer.axaml" />
|
||||||
<ResourceInclude Source="DualBadge.axaml" />
|
<ResourceInclude Source="DualBadge.axaml" />
|
||||||
<ResourceInclude Source="EnumSelector.axaml" />
|
<ResourceInclude Source="EnumSelector.axaml" />
|
||||||
<ResourceInclude Source="IconButton.axaml" />
|
<ResourceInclude Source="IconButton.axaml" />
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ using Ursa.EventArgs;
|
|||||||
|
|
||||||
namespace Ursa.Controls;
|
namespace Ursa.Controls;
|
||||||
|
|
||||||
|
|
||||||
[TemplatePart(PART_OKButton, typeof(Button))]
|
[TemplatePart(PART_OKButton, typeof(Button))]
|
||||||
[TemplatePart(PART_CancelButton, typeof(Button))]
|
[TemplatePart(PART_CancelButton, typeof(Button))]
|
||||||
[TemplatePart(PART_YesButton, typeof(Button))]
|
[TemplatePart(PART_YesButton, typeof(Button))]
|
||||||
|
|||||||
@@ -1,19 +1,22 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Animation;
|
using Avalonia.Animation;
|
||||||
|
using Avalonia.Animation.Easings;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.Primitives;
|
using Avalonia.Controls.Primitives;
|
||||||
using Avalonia.Controls.Templates;
|
using Avalonia.Controls.Templates;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Layout;
|
using Avalonia.Layout;
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
|
using Avalonia.Styling;
|
||||||
using Avalonia.Utilities;
|
using Avalonia.Utilities;
|
||||||
|
using Ursa.EventArgs;
|
||||||
|
|
||||||
namespace Ursa.Controls;
|
namespace Ursa.Controls;
|
||||||
|
|
||||||
public class OverlayDialogHost : Canvas
|
public class OverlayDialogHost : Canvas
|
||||||
{
|
{
|
||||||
private readonly List<DialogControl> _dialogs = new();
|
private readonly List<DialogControl> _dialogs = new();
|
||||||
private readonly List<DialogControl> _modalDialogs = new();
|
private readonly List<Control> _modalDialogs = new();
|
||||||
private readonly List<Border> _masks = new();
|
private readonly List<Border> _masks = new();
|
||||||
|
|
||||||
public string? HostId { get; set; }
|
public string? HostId { get; set; }
|
||||||
@@ -57,9 +60,16 @@ public class OverlayDialogHost : Canvas
|
|||||||
if (sender is Border border)
|
if (sender is Border border)
|
||||||
{
|
{
|
||||||
int i = _masks.IndexOf(border);
|
int i = _masks.IndexOf(border);
|
||||||
DialogControl dialog = _modalDialogs[i];
|
if (_modalDialogs[i] is DialogControl dialog)
|
||||||
dialog.CloseDialog();
|
{
|
||||||
border.RemoveHandler(PointerReleasedEvent, ClickBorderToCloseDialog);
|
dialog?.CloseDialog();
|
||||||
|
border.RemoveHandler(PointerReleasedEvent, ClickBorderToCloseDialog);
|
||||||
|
}
|
||||||
|
else if(_modalDialogs[i] is DrawerControlBase drawer)
|
||||||
|
{
|
||||||
|
drawer.CloseDrawer();
|
||||||
|
border.RemoveHandler(PointerReleasedEvent, ClickBorderToCloseDialog);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +97,11 @@ public class OverlayDialogHost : Canvas
|
|||||||
|
|
||||||
foreach (var modalDialog in _modalDialogs)
|
foreach (var modalDialog in _modalDialogs)
|
||||||
{
|
{
|
||||||
ResetDialogPosition(modalDialog, oldSize, newSize);
|
if (modalDialog is DialogControl c)
|
||||||
|
{
|
||||||
|
ResetDialogPosition(c, oldSize, newSize);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,10 +182,7 @@ public class OverlayDialogHost : Canvas
|
|||||||
ResetZIndices();
|
ResetZIndices();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void AddDrawer(DrawerControlBase control)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnDialogControlClosing(object sender, object? e)
|
private void OnDialogControlClosing(object sender, object? e)
|
||||||
{
|
{
|
||||||
@@ -225,6 +236,84 @@ public class OverlayDialogHost : Canvas
|
|||||||
control.AddHandler(DialogControl.ClosedEvent, OnDialogControlClosing);
|
control.AddHandler(DialogControl.ClosedEvent, OnDialogControlClosing);
|
||||||
control.AddHandler(DialogControl.LayerChangedEvent, OnDialogLayerChanged);
|
control.AddHandler(DialogControl.LayerChangedEvent, OnDialogLayerChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal async void AddDrawer(DrawerControlBase control)
|
||||||
|
{
|
||||||
|
var mask = CreateOverlayMask(false);
|
||||||
|
mask.Opacity = 0;
|
||||||
|
_masks.Add(mask);
|
||||||
|
_modalDialogs.Add(control);
|
||||||
|
// control.SetAsModal(true);
|
||||||
|
for (int i = 0; i < _masks.Count-1; i++)
|
||||||
|
{
|
||||||
|
_masks[i].Opacity = 0.5;
|
||||||
|
}
|
||||||
|
ResetZIndices();
|
||||||
|
this.Children.Add(mask);
|
||||||
|
this.Children.Add(control);
|
||||||
|
control.Measure(this.Bounds.Size);
|
||||||
|
control.Arrange(new Rect(control.DesiredSize));
|
||||||
|
control.Height = this.Bounds.Height;
|
||||||
|
control.AddHandler(DrawerControlBase.ClosedEvent, OnDrawerControlClosing);
|
||||||
|
// SetLeft(control, this.Bounds.Width - control.Bounds.Width);
|
||||||
|
var animation = CreateAnimation(control.Bounds.Width);
|
||||||
|
var animation2 = CreateOpacityAnimation();
|
||||||
|
await Task.WhenAll(animation.RunAsync(control), animation2.RunAsync(mask));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Animation CreateAnimation(double width)
|
||||||
|
{
|
||||||
|
var animation = new Animation();
|
||||||
|
animation.Easing = new CubicEaseOut();
|
||||||
|
animation.FillMode = FillMode.Forward;
|
||||||
|
var keyFrame1 = new KeyFrame(){ Cue = new Cue(0.0) };
|
||||||
|
keyFrame1.Setters.Add(new Setter() { Property = Canvas.LeftProperty, Value = Bounds.Width });
|
||||||
|
var keyFrame2 = new KeyFrame() { Cue = new Cue(1.0) };
|
||||||
|
keyFrame2.Setters.Add(new Setter() { Property = Canvas.LeftProperty, Value = Bounds.Width - width });
|
||||||
|
animation.Children.Add(keyFrame1);
|
||||||
|
animation.Children.Add(keyFrame2);
|
||||||
|
animation.Duration = TimeSpan.FromSeconds(0.3);
|
||||||
|
return animation;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Animation CreateOpacityAnimation()
|
||||||
|
{
|
||||||
|
var animation = new Animation();
|
||||||
|
animation.FillMode = FillMode.Forward;
|
||||||
|
var keyFrame1 = new KeyFrame(){ Cue = new Cue(0.0) };
|
||||||
|
keyFrame1.Setters.Add(new Setter(){ Property = OpacityProperty, Value = 0.0});
|
||||||
|
var keyFrame2 = new KeyFrame() { Cue = new Cue(1.0) };
|
||||||
|
keyFrame2.Setters.Add(new Setter() { Property = OpacityProperty, Value = 1.0 });
|
||||||
|
animation.Children.Add(keyFrame1);
|
||||||
|
animation.Children.Add(keyFrame2);
|
||||||
|
animation.Duration = TimeSpan.FromSeconds(0.3);
|
||||||
|
return animation;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDrawerControlClosing(object sender, ResultEventArgs e)
|
||||||
|
{
|
||||||
|
if (sender is DrawerControlBase control)
|
||||||
|
{
|
||||||
|
Children.Remove(control);
|
||||||
|
control.RemoveHandler(DialogControl.ClosedEvent, OnDialogControlClosing);
|
||||||
|
control.RemoveHandler(DialogControl.LayerChangedEvent, OnDialogLayerChanged);
|
||||||
|
if (_modalDialogs.Contains(control))
|
||||||
|
{
|
||||||
|
_modalDialogs.Remove(control);
|
||||||
|
if (_masks.Count > 0)
|
||||||
|
{
|
||||||
|
var last = _masks.Last();
|
||||||
|
this.Children.Remove(last);
|
||||||
|
_masks.Remove(last);
|
||||||
|
if (_masks.Count > 0)
|
||||||
|
{
|
||||||
|
_masks.Last().IsVisible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ResetZIndices();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Handle dialog layer change event
|
// Handle dialog layer change event
|
||||||
private void OnDialogLayerChanged(object sender, DialogLayerChangeEventArgs e)
|
private void OnDialogLayerChanged(object sender, DialogLayerChangeEventArgs e)
|
||||||
|
|||||||
6
src/Ursa/Controls/Drawer/CustomDrawerControl.cs
Normal file
6
src/Ursa/Controls/Drawer/CustomDrawerControl.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Ursa.Controls;
|
||||||
|
|
||||||
|
public class CustomDrawerControl: DrawerControlBase
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,6 +1,39 @@
|
|||||||
namespace Ursa.Controls;
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Controls.Metadata;
|
||||||
|
using Avalonia.Controls.Primitives;
|
||||||
|
using Avalonia.Interactivity;
|
||||||
|
using Ursa.Common;
|
||||||
|
|
||||||
|
namespace Ursa.Controls;
|
||||||
|
|
||||||
|
[TemplatePart(PART_YesButton, typeof(Button))]
|
||||||
|
[TemplatePart(PART_NoButton, typeof(Button))]
|
||||||
|
[TemplatePart(PART_OKButton, typeof(Button))]
|
||||||
|
[TemplatePart(PART_CancelButton, typeof(Button))]
|
||||||
public class DefaultDrawerControl: DrawerControlBase
|
public class DefaultDrawerControl: DrawerControlBase
|
||||||
{
|
{
|
||||||
|
public const string PART_YesButton = "PART_YesButton";
|
||||||
|
public const string PART_NoButton = "PART_NoButton";
|
||||||
|
public const string PART_OKButton = "PART_OKButton";
|
||||||
|
public const string PART_CancelButton = "PART_CancelButton";
|
||||||
|
|
||||||
|
private Button? _yesButton;
|
||||||
|
private Button? _noButton;
|
||||||
|
private Button? _okButton;
|
||||||
|
private Button? _cancelButton;
|
||||||
|
|
||||||
|
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnApplyTemplate(e);
|
||||||
|
EventHelper.UnregisterClickEvent(OnDefaultButtonClick, _yesButton, _noButton, _okButton, _cancelButton);
|
||||||
|
_yesButton = e.NameScope.Find<Button>(PART_YesButton);
|
||||||
|
_noButton = e.NameScope.Find<Button>(PART_NoButton);
|
||||||
|
_okButton = e.NameScope.Find<Button>(PART_OKButton);
|
||||||
|
_cancelButton = e.NameScope.Find<Button>(PART_CancelButton);
|
||||||
|
EventHelper.RegisterClickEvent(OnDefaultButtonClick, _yesButton, _noButton, _okButton, _cancelButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDefaultButtonClick(object? sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,21 @@
|
|||||||
namespace Ursa.Controls;
|
using Avalonia.Controls;
|
||||||
|
using Ursa.Common;
|
||||||
|
|
||||||
|
namespace Ursa.Controls;
|
||||||
|
|
||||||
public static class Drawer
|
public static class Drawer
|
||||||
{
|
{
|
||||||
public static Task<TResult?> ShowDialogAsync<TView, TViewModel, TResult>(TViewModel viewModel)
|
public static Task<TResult?> Show<TView, TViewModel, TResult>(TViewModel vm, Position position = Position.Right)
|
||||||
|
where TView: Control, new()
|
||||||
{
|
{
|
||||||
var host = OverlayDialogManager.GetHost(null);
|
var host = OverlayDialogManager.GetHost(null);
|
||||||
if (host is null) return Task.FromResult(default(TResult));
|
if (host is null) return Task.FromResult(default(TResult));
|
||||||
var dialog = new DefaultDrawerControl();
|
var dialog = new CustomDrawerControl()
|
||||||
|
{
|
||||||
|
Content = new TView(),
|
||||||
|
DataContext = vm,
|
||||||
|
Position = position,
|
||||||
|
};
|
||||||
host.AddDrawer(dialog);
|
host.AddDrawer(dialog);
|
||||||
return dialog.ShowAsync<TResult>();
|
return dialog.ShowAsync<TResult>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Controls.Metadata;
|
||||||
|
using Avalonia.Controls.Primitives;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using Ursa.Common;
|
using Ursa.Common;
|
||||||
@@ -7,10 +9,15 @@ using Ursa.EventArgs;
|
|||||||
|
|
||||||
namespace Ursa.Controls;
|
namespace Ursa.Controls;
|
||||||
|
|
||||||
|
[TemplatePart(PART_CloseButton, typeof(Button))]
|
||||||
public abstract class DrawerControlBase: ContentControl
|
public abstract class DrawerControlBase: ContentControl
|
||||||
{
|
{
|
||||||
|
public const string PART_CloseButton = "PART_CloseButton";
|
||||||
|
|
||||||
internal bool CanClickOnMaskToClose { get; set; }
|
internal bool CanClickOnMaskToClose { get; set; }
|
||||||
|
internal bool ShowCloseButton { get; set; }
|
||||||
|
|
||||||
|
protected internal Button? _closeButton;
|
||||||
|
|
||||||
public static readonly StyledProperty<Position> PositionProperty = AvaloniaProperty.Register<DrawerControlBase, Position>(
|
public static readonly StyledProperty<Position> PositionProperty = AvaloniaProperty.Register<DrawerControlBase, Position>(
|
||||||
nameof(Position));
|
nameof(Position));
|
||||||
@@ -43,7 +50,7 @@ public abstract class DrawerControlBase: ContentControl
|
|||||||
public static readonly RoutedEvent<ResultEventArgs> ClosedEvent = RoutedEvent.Register<DrawerControlBase, ResultEventArgs>(
|
public static readonly RoutedEvent<ResultEventArgs> ClosedEvent = RoutedEvent.Register<DrawerControlBase, ResultEventArgs>(
|
||||||
nameof(Closed), RoutingStrategies.Bubble);
|
nameof(Closed), RoutingStrategies.Bubble);
|
||||||
|
|
||||||
public event EventHandler<ResultEventArgs> Closed
|
public event EventHandler<ResultEventArgs>? Closed
|
||||||
{
|
{
|
||||||
add => AddHandler(ClosedEvent, value);
|
add => AddHandler(ClosedEvent, value);
|
||||||
remove => RemoveHandler(ClosedEvent, value);
|
remove => RemoveHandler(ClosedEvent, value);
|
||||||
@@ -54,6 +61,14 @@ public abstract class DrawerControlBase: ContentControl
|
|||||||
DataContextProperty.Changed.AddClassHandler<DrawerControlBase, object?>((o, e) => o.OnDataContextChange(e));
|
DataContextProperty.Changed.AddClassHandler<DrawerControlBase, object?>((o, e) => o.OnDataContextChange(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnApplyTemplate(e);
|
||||||
|
EventHelper.UnregisterClickEvent(OnCloseButtonClick, _closeButton);
|
||||||
|
_closeButton = e.NameScope.Find<Button>(PART_CloseButton);
|
||||||
|
EventHelper.RegisterClickEvent(OnCloseButtonClick, _closeButton);
|
||||||
|
}
|
||||||
|
|
||||||
private void OnDataContextChange(AvaloniaPropertyChangedEventArgs<object?> args)
|
private void OnDataContextChange(AvaloniaPropertyChangedEventArgs<object?> args)
|
||||||
{
|
{
|
||||||
if(args.OldValue.Value is IDialogContext oldContext)
|
if(args.OldValue.Value is IDialogContext oldContext)
|
||||||
@@ -71,6 +86,8 @@ public abstract class DrawerControlBase: ContentControl
|
|||||||
RaiseEvent(new ResultEventArgs(ClosedEvent, e));
|
RaiseEvent(new ResultEventArgs(ClosedEvent, e));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnCloseButtonClick(object sender, RoutedEventArgs e) => CloseDrawer();
|
||||||
|
|
||||||
public Task<T?> ShowAsync<T>(CancellationToken? token = default)
|
public Task<T?> ShowAsync<T>(CancellationToken? token = default)
|
||||||
{
|
{
|
||||||
var tcs = new TaskCompletionSource<T?>();
|
var tcs = new TaskCompletionSource<T?>();
|
||||||
@@ -97,6 +114,13 @@ public abstract class DrawerControlBase: ContentControl
|
|||||||
|
|
||||||
internal virtual void CloseDrawer()
|
internal virtual void CloseDrawer()
|
||||||
{
|
{
|
||||||
RaiseEvent(new ResultEventArgs(ClosedEvent, null));
|
if (DataContext is IDialogContext context)
|
||||||
|
{
|
||||||
|
context.Close();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RaiseEvent(new ResultEventArgs(ClosedEvent, null));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
8
src/Ursa/Controls/Layout/DefaultDialogLayout.cs
Normal file
8
src/Ursa/Controls/Layout/DefaultDialogLayout.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Avalonia.Controls.Primitives;
|
||||||
|
|
||||||
|
namespace Ursa.Controls.Layout;
|
||||||
|
|
||||||
|
public class DefaultDialogLayout: TemplatedControl
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user