Skip to content

Commit

Permalink
Merge pull request #542 from WCKYWCKF/pr2
Browse files Browse the repository at this point in the history
Fixed: Other windows closing due to error in handling the Drawer close event.
  • Loading branch information
rabbitism authored Jan 16, 2025
2 parents 8651ae3 + 67abe93 commit ea4268e
Show file tree
Hide file tree
Showing 12 changed files with 250 additions and 117 deletions.
77 changes: 6 additions & 71 deletions demo/Sandbox/Views/MainWindow.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,75 +16,10 @@
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
<vm:MainWindowViewModel />
</Design.DataContext>


<Grid ColumnDefinitions="*,*"
RowDefinitions="7*,3*">
<ScrollViewer Grid.Column="0" Grid.Row="0">
<u:Form LabelAlignment="Left" LabelPosition="Left" LabelWidth="*" HorizontalAlignment="Stretch">
<TextBox Name="Title" u:FormItem.Label="Title"></TextBox>
<TextBox Name="SuggestedFileName" u:FormItem.Label="SuggestedFileName"></TextBox>
<TextBox Name="SuggestedStartPath" u:FormItem.Label="SuggestedStartPath"></TextBox>
<TextBox Name="FileFilter" u:FormItem.Label="FileFilter"></TextBox>
<TextBox Name="DefaultFileExtension" u:FormItem.Label="DefaultFileExtension"></TextBox>
<ToggleButton Name="AllowMultiple" Content="AllowMultiple" u:FormItem.NoLabel="True"
HorizontalAlignment="Stretch">
</ToggleButton>
<u:EnumSelector Name="UsePickerType" EnumType="u:UsePickerTypes" u:FormItem.Label="UsePickerType"></u:EnumSelector>
</u:Form>
</ScrollViewer>
<ScrollViewer Grid.Column="0" Grid.Row="1">
<StackPanel Spacing="2">
<HeaderedContentControl Header="Default">
<u:PathPicker Name="PathPicker"
Title="{Binding #Title.Text}"
SuggestedFileName="{Binding #SuggestedFileName.Text}"
SuggestedStartPath="{Binding #SuggestedStartPath.Text}"
FileFilter="{Binding #FileFilter.Text}"
DefaultFileExtension="{Binding #DefaultFileExtension.Text}"
AllowMultiple="{Binding #AllowMultiple.IsChecked}"
UsePickerType="{Binding #UsePickerType.Value}">
</u:PathPicker>
</HeaderedContentControl>
<HeaderedContentControl Header="PathPickerOnlyButton">
<u:PathPicker Name="PathPicker1"
Theme="{DynamicResource PathPickerOnlyButton}"
Title="{Binding #Title.Text}"
SuggestedFileName="{Binding #SuggestedFileName.Text}"
SuggestedStartPath="{Binding #SuggestedStartPath.Text}"
FileFilter="{Binding #FileFilter.Text}"
DefaultFileExtension="{Binding #DefaultFileExtension.Text}"
AllowMultiple="{Binding #AllowMultiple.IsChecked}"
UsePickerType="{Binding #UsePickerType.Value}">
</u:PathPicker>
</HeaderedContentControl>
<HeaderedContentControl Header="PathPickerForList">
<u:PathPicker Name="PathPicker2"
Theme="{DynamicResource PathPickerForList}"
Title="{Binding #Title.Text}"
SuggestedFileName="{Binding #SuggestedFileName.Text}"
SuggestedStartPath="{Binding #SuggestedStartPath.Text}"
FileFilter="{Binding #FileFilter.Text}"
DefaultFileExtension="{Binding #DefaultFileExtension.Text}"
AllowMultiple="{Binding #AllowMultiple.IsChecked}"
UsePickerType="{Binding #UsePickerType.Value}">
</u:PathPicker>
</HeaderedContentControl>
</StackPanel>
</ScrollViewer>
<ScrollViewer Grid.Column="1" Grid.Row="0" Grid.RowSpan="2">
<StackPanel Spacing="1">
<HeaderedContentControl Header="SelectedPath">
<TextBox Name="SelectedPath" u:FormItem.Label="SelectedPath" IsReadOnly="True"
Text="{Binding #PathPicker.SelectedPath}">
</TextBox>
</HeaderedContentControl>
<HeaderedContentControl Header="SelectedPaths">
<ListBox Name="SelectedPaths"
ItemsSource="{Binding #PathPicker.SelectedPaths}">
</ListBox>
</HeaderedContentControl>
</StackPanel>
</ScrollViewer>
</Grid>
<u:UrsaView>
<Panel>
<Button Content="???" Click="Button_OnClick"></Button>
<u:OverlayDialogHost HostId="root"></u:OverlayDialogHost>
</Panel>
</u:UrsaView>
</Window>
7 changes: 7 additions & 0 deletions demo/Sandbox/Views/MainWindow.axaml.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using Avalonia.Controls;
using Avalonia.Interactivity;
using Ursa.Controls;

namespace Sandbox.Views;

Expand All @@ -8,4 +10,9 @@ public MainWindow()
{
InitializeComponent();
}

private async void Button_OnClick(object? sender, RoutedEventArgs e)
{
var res = await OverlayDialog.ShowModal(new TextBlock() { Text = "sdfksjdl" }, "root");
}
}
15 changes: 15 additions & 0 deletions demo/Sandbox/Views/PW.axaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<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"
xmlns:u="https://irihi.tech/ursa"
MinHeight="200"
MinWidth="500"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Sandbox.Views.PW">
<Panel>
<Button Content="???" Click="Button_OnClick"></Button>
<Button Content="close" VerticalAlignment="Bottom" Click="Close"></Button>
<u:OverlayDialogHost x:Name="_overlayDialogHost" ></u:OverlayDialogHost>
</Panel>
</UserControl>
42 changes: 42 additions & 0 deletions demo/Sandbox/Views/PW.axaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System;
using System.IO;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Irihi.Avalonia.Shared.Contracts;
using Sandbox.ViewModels;
using Ursa.Controls;

namespace Sandbox.Views;

public partial class PW : UserControl
{
public PW()
{
InitializeComponent();
_overlayDialogHost.HostId = _hostid;
}

private string _hostid = Path.GetRandomFileName();

private async void Button_OnClick(object? sender, RoutedEventArgs e)
{
Drawer.ShowCustom(new PW(), new TestVM(), _hostid);
}

private void Close(object? sender, RoutedEventArgs e)
{
(DataContext as TestVM)?.Close();
}
}

public class TestVM : ViewModelBase, IDialogContext
{
public void Close()
{
RequestClose?.Invoke(this, 12456789);
}

public event EventHandler<object?>? RequestClose;
}
22 changes: 0 additions & 22 deletions src/Ursa/Controls/Drawer/DrawerControlBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,6 @@ public bool IsOpen
internal bool? IsCloseButtonVisible { get; set; }

protected internal bool CanLightDismiss { get; set; }

static DrawerControlBase()
{
DataContextProperty.Changed.AddClassHandler<DrawerControlBase, object?>((o, e) => o.OnDataContextChange(e));
}

protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
Expand All @@ -63,23 +58,6 @@ protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
Button.ClickEvent.AddHandler(OnCloseButtonClick, _closeButton);
}

private void OnDataContextChange(AvaloniaPropertyChangedEventArgs<object?> args)
{
if(args.OldValue.Value is IDialogContext oldContext)
{
oldContext.RequestClose -= OnContextRequestClose;
}
if(args.NewValue.Value is IDialogContext newContext)
{
newContext.RequestClose += OnContextRequestClose;
}
}

private void OnContextRequestClose(object? sender, object? e)
{
RaiseEvent(new ResultEventArgs(ClosedEvent, e));
}

private void OnCloseButtonClick(object? sender, RoutedEventArgs e) => Close();

public override void Close()
Expand Down
7 changes: 6 additions & 1 deletion src/Ursa/Controls/OverlayShared/OverlayDialogHost.Dialog.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using Avalonia;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.VisualTree;
using Irihi.Avalonia.Shared.Contracts;
using Irihi.Avalonia.Shared.Helpers;
using Irihi.Avalonia.Shared.Shapes;
using Ursa.Controls.OverlayShared;
Expand Down Expand Up @@ -63,6 +65,8 @@ internal void AddDialog(DialogControlBase control)
private async void OnDialogControlClosing(object? sender, object? e)
{
if (sender is not DialogControlBase control) return;
if (control.IsShowAsync is false && e is RoutedEventArgs args)
args.Handled = true;
var layer = _layers.FirstOrDefault(a => a.Element == control);
if (layer is null) return;
_layers.Remove(layer);
Expand Down Expand Up @@ -116,11 +120,12 @@ internal void AddModalDialog(DialogControlBase control)
if (!IsAnimationDisabled) MaskAppearAnimation.RunAsync(mask);

var element = control.GetVisualDescendants().OfType<InputElement>()
.FirstOrDefault(FocusHelper.GetDialogFocusHint);
.FirstOrDefault(FocusHelper.GetDialogFocusHint);
if (element is null)
{
element = control.GetVisualDescendants().OfType<InputElement>().FirstOrDefault(a => a.Focusable);
}

element?.Focus();
_modalCount++;
IsInModalStatus = _modalCount > 0;
Expand Down
44 changes: 28 additions & 16 deletions src/Ursa/Controls/OverlayShared/OverlayDialogHost.Drawer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Avalonia.Input;
using Avalonia.Styling;
using Avalonia.VisualTree;
using Irihi.Avalonia.Shared.Contracts;
using Irihi.Avalonia.Shared.Shapes;
using Ursa.Common;
using Ursa.Controls.OverlayShared;
Expand All @@ -22,9 +23,10 @@ internal async void AddDrawer(DrawerControlBase control)
{
mask = CreateOverlayMask(false, true);
}

_layers.Add(new DialogPair(mask, control));
ResetZIndices();
if(mask is not null)this.Children.Add(mask);
if (mask is not null) this.Children.Add(mask);
this.Children.Add(control);
control.Measure(this.Bounds.Size);
control.Arrange(new Rect(control.DesiredSize));
Expand All @@ -47,7 +49,7 @@ internal async void AddDrawer(DrawerControlBase control)
}
}
}

internal async void AddModalDrawer(DrawerControlBase control)
{
PureRectangle mask = CreateOverlayMask(true, control.CanLightDismiss);
Expand All @@ -72,26 +74,28 @@ internal async void AddModalDrawer(DrawerControlBase control)
}

var element = control.GetVisualDescendants().OfType<InputElement>()
.FirstOrDefault(FocusHelper.GetDialogFocusHint);
.FirstOrDefault(FocusHelper.GetDialogFocusHint);
if (element is null)
{
element = control.GetVisualDescendants().OfType<InputElement>().FirstOrDefault(a => a.Focusable);
}

element?.Focus();
}

private void SetDrawerPosition(DrawerControlBase control)
{
if(control.Position is Position.Left or Position.Right)
if (control.Position is Position.Left or Position.Right)
{
control.Height = this.Bounds.Height;
}
if(control.Position is Position.Top or Position.Bottom)

if (control.Position is Position.Top or Position.Bottom)
{
control.Width = this.Bounds.Width;
}
}

private static void ResetDrawerPosition(DrawerControlBase control, Size newSize)
{
if (control.Position == Position.Right)
Expand All @@ -112,7 +116,7 @@ private static void ResetDrawerPosition(DrawerControlBase control, Size newSize)
else
{
control.Width = newSize.Width;
SetTop(control, newSize.Height-control.Bounds.Height);
SetTop(control, newSize.Height - control.Bounds.Height);
}
}

Expand All @@ -132,26 +136,28 @@ private Animation CreateAnimation(Size elementBounds, Position position, bool ap
source = appear ? Bounds.Width : Bounds.Width - elementBounds.Width;
target = appear ? Bounds.Width - elementBounds.Width : Bounds.Width;
}

if (position == Position.Top)
{
source = appear ? -elementBounds.Height : 0;
target = appear ? 0 : -elementBounds.Height;
}

if (position == Position.Bottom)
{
source = appear ? Bounds.Height : Bounds.Height - elementBounds.Height;
target = appear ? Bounds.Height - elementBounds.Height : Bounds.Height;
}

var targetProperty = position==Position.Left || position==Position.Right ? Canvas.LeftProperty : Canvas.TopProperty;

var targetProperty = position == Position.Left || position == Position.Right
? Canvas.LeftProperty
: Canvas.TopProperty;
var animation = new Animation
{
Easing = new CubicEaseOut(),
FillMode = FillMode.Forward
};
var keyFrame1 = new KeyFrame(){ Cue = new Cue(0.0) };
var keyFrame1 = new KeyFrame() { Cue = new Cue(0.0) };
keyFrame1.Setters.Add(new Setter()
{ Property = targetProperty, Value = source });
var keyFrame2 = new KeyFrame() { Cue = new Cue(1.0) };
Expand All @@ -162,16 +168,19 @@ private Animation CreateAnimation(Size elementBounds, Position position, bool ap
animation.Duration = TimeSpan.FromSeconds(0.3);
return animation;
}

private async void OnDrawerControlClosing(object? sender, ResultEventArgs e)
{
if (sender is DrawerControlBase control)
{
if (control.IsShowAsync is false)
e.Handled = true;

var layer = _layers.FirstOrDefault(a => a.Element == control);
if(layer is null) return;
if (layer is null) return;
_layers.Remove(layer);
control.RemoveHandler(OverlayFeedbackElement.ClosedEvent, OnDialogControlClosing);
control.RemoveHandler(DialogControlBase.LayerChangedEvent, OnDialogLayerChanged);
control.RemoveHandler(DialogControlBase.LayerChangedEvent, OnDialogLayerChanged);
if (layer.Mask is not null)
{
_modalCount--;
Expand All @@ -181,8 +190,10 @@ private async void OnDrawerControlClosing(object? sender, ResultEventArgs e)
if (!IsAnimationDisabled)
{
var disappearAnimation = CreateAnimation(control.Bounds.Size, control.Position, false);
await Task.WhenAll(disappearAnimation.RunAsync(control), MaskDisappearAnimation.RunAsync(layer.Mask));
await Task.WhenAll(disappearAnimation.RunAsync(control),
MaskDisappearAnimation.RunAsync(layer.Mask));
}

Children.Remove(layer.Mask);
}
else
Expand All @@ -193,6 +204,7 @@ private async void OnDrawerControlClosing(object? sender, ResultEventArgs e)
await disappearAnimation.RunAsync(control);
}
}

Children.Remove(control);
ResetZIndices();
}
Expand Down
Loading

0 comments on commit ea4268e

Please sign in to comment.