feat: advanced dialog layout.
This commit is contained in:
@@ -119,6 +119,10 @@ public class DialogDemoViewModel: ObservableObject
|
|||||||
Mode = SelectedMode,
|
Mode = SelectedMode,
|
||||||
Buttons = SelectedButton,
|
Buttons = SelectedButton,
|
||||||
CanClickOnMaskToClose = CanCloseMaskToClose,
|
CanClickOnMaskToClose = CanCloseMaskToClose,
|
||||||
|
HorizontalAnchor = HorizontalPosition.Right,
|
||||||
|
HorizontalOffset = 50,
|
||||||
|
VerticalAnchor = VerticalPosition.Top,
|
||||||
|
VerticalOffset = 50,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
Date = vm.Date;
|
Date = vm.Date;
|
||||||
|
|||||||
@@ -93,7 +93,7 @@
|
|||||||
<converters:ViewLocator />
|
<converters:ViewLocator />
|
||||||
</ContentControl.ContentTemplate>
|
</ContentControl.ContentTemplate>
|
||||||
</ContentControl>
|
</ContentControl>
|
||||||
<u:OverlayDialogHost Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Grid.ColumnSpan="2"/>
|
<u:OverlayDialogHost Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Grid.ColumnSpan="2" SnapThickness="20"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
@@ -46,6 +46,23 @@
|
|||||||
</Border>
|
</Border>
|
||||||
</ControlTemplate>
|
</ControlTemplate>
|
||||||
</Setter>
|
</Setter>
|
||||||
|
<Style Selector="^ /template/ Panel#PART_TitleArea">
|
||||||
|
<Setter Property="ContextFlyout">
|
||||||
|
<MenuFlyout>
|
||||||
|
<MenuItem
|
||||||
|
Command="{Binding $parent[u:DialogControl].CloseDialog}"
|
||||||
|
CommandParameter="{x:Static u:DialogLayerChangeType.BringForward}"
|
||||||
|
Header="{DynamicResource STRING_MENU_DIALOG_CLOSE}">
|
||||||
|
<MenuItem.Icon>
|
||||||
|
<PathIcon
|
||||||
|
Width="12"
|
||||||
|
Height="12"
|
||||||
|
Data="{DynamicResource WindowCloseIconGlyph}" />
|
||||||
|
</MenuItem.Icon>
|
||||||
|
</MenuItem>
|
||||||
|
</MenuFlyout>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
<Style Selector="^:not(:modal) /template/ Panel#PART_TitleArea">
|
<Style Selector="^:not(:modal) /template/ Panel#PART_TitleArea">
|
||||||
<Setter Property="ContextFlyout">
|
<Setter Property="ContextFlyout">
|
||||||
<MenuFlyout>
|
<MenuFlyout>
|
||||||
@@ -93,6 +110,17 @@
|
|||||||
Data="{DynamicResource DialogArrangeSendToBackGlyph}" />
|
Data="{DynamicResource DialogArrangeSendToBackGlyph}" />
|
||||||
</MenuItem.Icon>
|
</MenuItem.Icon>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
<MenuItem
|
||||||
|
Command="{Binding $parent[u:DialogControl].CloseDialog}"
|
||||||
|
CommandParameter="{x:Static u:DialogLayerChangeType.BringForward}"
|
||||||
|
Header="{DynamicResource STRING_MENU_DIALOG_CLOSE}">
|
||||||
|
<MenuItem.Icon>
|
||||||
|
<PathIcon
|
||||||
|
Width="12"
|
||||||
|
Height="12"
|
||||||
|
Data="{DynamicResource WindowCloseIconGlyph}" />
|
||||||
|
</MenuItem.Icon>
|
||||||
|
</MenuItem>
|
||||||
</MenuFlyout>
|
</MenuFlyout>
|
||||||
</Setter>
|
</Setter>
|
||||||
</Style>
|
</Style>
|
||||||
@@ -115,11 +143,13 @@
|
|||||||
Theme="{DynamicResource CardBorder}">
|
Theme="{DynamicResource CardBorder}">
|
||||||
<Border ClipToBounds="True" CornerRadius="{TemplateBinding CornerRadius}">
|
<Border ClipToBounds="True" CornerRadius="{TemplateBinding CornerRadius}">
|
||||||
<Grid RowDefinitions="Auto, *, Auto">
|
<Grid RowDefinitions="Auto, *, Auto">
|
||||||
<ContentPresenter
|
<ScrollViewer Grid.Row="1">
|
||||||
Name="PART_ContentPresenter"
|
<ContentPresenter
|
||||||
Grid.Row="1"
|
Name="PART_ContentPresenter"
|
||||||
Margin="24,8"
|
Grid.Row="1"
|
||||||
Content="{TemplateBinding Content}" />
|
Margin="24,8"
|
||||||
|
Content="{TemplateBinding Content}" />
|
||||||
|
</ScrollViewer>
|
||||||
<Grid Grid.Row="0" ColumnDefinitions="Auto, *, Auto">
|
<Grid Grid.Row="0" ColumnDefinitions="Auto, *, Auto">
|
||||||
<Panel
|
<Panel
|
||||||
Name="{x:Static u:DialogControl.PART_TitleArea}"
|
Name="{x:Static u:DialogControl.PART_TitleArea}"
|
||||||
@@ -304,7 +334,23 @@
|
|||||||
<Setter Property="theme:ClassHelper.Classes" Value="Tertiary" />
|
<Setter Property="theme:ClassHelper.Classes" Value="Tertiary" />
|
||||||
</Style>
|
</Style>
|
||||||
</Style>
|
</Style>
|
||||||
|
<Style Selector="^ /template/ Panel#PART_TitleArea">
|
||||||
|
<Setter Property="ContextFlyout">
|
||||||
|
<MenuFlyout>
|
||||||
|
<MenuItem
|
||||||
|
Command="{Binding $parent[u:DialogControl].CloseDialog}"
|
||||||
|
CommandParameter="{x:Static u:DialogLayerChangeType.BringForward}"
|
||||||
|
Header="{DynamicResource STRING_MENU_DIALOG_CLOSE}">
|
||||||
|
<MenuItem.Icon>
|
||||||
|
<PathIcon
|
||||||
|
Width="12"
|
||||||
|
Height="12"
|
||||||
|
Data="{DynamicResource WindowCloseIconGlyph}" />
|
||||||
|
</MenuItem.Icon>
|
||||||
|
</MenuItem>
|
||||||
|
</MenuFlyout>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
<Style Selector="^:not(:modal) /template/ Panel#PART_TitleArea">
|
<Style Selector="^:not(:modal) /template/ Panel#PART_TitleArea">
|
||||||
<Setter Property="ContextFlyout">
|
<Setter Property="ContextFlyout">
|
||||||
<MenuFlyout>
|
<MenuFlyout>
|
||||||
@@ -352,6 +398,17 @@
|
|||||||
Data="{DynamicResource DialogArrangeSendToBackGlyph}" />
|
Data="{DynamicResource DialogArrangeSendToBackGlyph}" />
|
||||||
</MenuItem.Icon>
|
</MenuItem.Icon>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
<MenuItem
|
||||||
|
Command="{Binding $parent[u:DialogControl].CloseDialog}"
|
||||||
|
CommandParameter="{x:Static u:DialogLayerChangeType.BringForward}"
|
||||||
|
Header="{DynamicResource STRING_MENU_DIALOG_CLOSE}">
|
||||||
|
<MenuItem.Icon>
|
||||||
|
<PathIcon
|
||||||
|
Width="12"
|
||||||
|
Height="12"
|
||||||
|
Data="{DynamicResource WindowCloseIconGlyph}" />
|
||||||
|
</MenuItem.Icon>
|
||||||
|
</MenuItem>
|
||||||
</MenuFlyout>
|
</MenuFlyout>
|
||||||
</Setter>
|
</Setter>
|
||||||
</Style>
|
</Style>
|
||||||
|
|||||||
@@ -81,7 +81,7 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
<StackPanel
|
<StackPanel
|
||||||
Grid.Row="2"
|
Grid.Row="2"
|
||||||
Margin="0,0,24,24"
|
Margin="24,0,24,24"
|
||||||
HorizontalAlignment="Right"
|
HorizontalAlignment="Right"
|
||||||
Orientation="Horizontal">
|
Orientation="Horizontal">
|
||||||
<Button
|
<Button
|
||||||
@@ -244,6 +244,20 @@
|
|||||||
</Border>
|
</Border>
|
||||||
</ControlTemplate>
|
</ControlTemplate>
|
||||||
</Setter>
|
</Setter>
|
||||||
|
<Style Selector="^ /template/ Panel#PART_TitleArea">
|
||||||
|
<Setter Property="ContextFlyout">
|
||||||
|
<MenuFlyout>
|
||||||
|
<MenuItem Command="{Binding $parent[u:DialogControl].CloseDialog}" Header="{DynamicResource STRING_MENU_DIALOG_CLOSE}">
|
||||||
|
<MenuItem.Icon>
|
||||||
|
<PathIcon
|
||||||
|
Width="12"
|
||||||
|
Height="12"
|
||||||
|
Data="{DynamicResource WindowCloseIconGlyph}" />
|
||||||
|
</MenuItem.Icon>
|
||||||
|
</MenuItem>
|
||||||
|
</MenuFlyout>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
<Style Selector="^[MessageIcon=None] /template/ PathIcon#PART_Icon">
|
<Style Selector="^[MessageIcon=None] /template/ PathIcon#PART_Icon">
|
||||||
<Setter Property="IsVisible" Value="False" />
|
<Setter Property="IsVisible" Value="False" />
|
||||||
</Style>
|
</Style>
|
||||||
|
|||||||
@@ -9,4 +9,5 @@
|
|||||||
<x:String x:Key="STRING_MENU_DIALOG_CANCEL">Cancel</x:String>
|
<x:String x:Key="STRING_MENU_DIALOG_CANCEL">Cancel</x:String>
|
||||||
<x:String x:Key="STRING_MENU_DIALOG_YES">Yes</x:String>
|
<x:String x:Key="STRING_MENU_DIALOG_YES">Yes</x:String>
|
||||||
<x:String x:Key="STRING_MENU_DIALOG_NO">No</x:String>
|
<x:String x:Key="STRING_MENU_DIALOG_NO">No</x:String>
|
||||||
|
<x:String x:Key="STRING_MENU_DIALOG_CLOSE">Close</x:String>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
|
|||||||
@@ -9,4 +9,5 @@
|
|||||||
<x:String x:Key="STRING_MENU_DIALOG_CANCEL">取消</x:String>
|
<x:String x:Key="STRING_MENU_DIALOG_CANCEL">取消</x:String>
|
||||||
<x:String x:Key="STRING_MENU_DIALOG_YES">是</x:String>
|
<x:String x:Key="STRING_MENU_DIALOG_YES">是</x:String>
|
||||||
<x:String x:Key="STRING_MENU_DIALOG_NO">否</x:String>
|
<x:String x:Key="STRING_MENU_DIALOG_NO">否</x:String>
|
||||||
|
<x:String x:Key="STRING_MENU_DIALOG_CLOSE">关闭</x:String>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using Avalonia.Controls;
|
|||||||
using Avalonia.Controls.Metadata;
|
using Avalonia.Controls.Metadata;
|
||||||
using Avalonia.Controls.Primitives;
|
using Avalonia.Controls.Primitives;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
|
using Avalonia.Input.GestureRecognizers;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Ursa.Common;
|
using Ursa.Common;
|
||||||
|
|
||||||
@@ -22,8 +23,12 @@ public class DialogControl: ContentControl
|
|||||||
|
|
||||||
internal HorizontalPosition HorizontalAnchor { get; set; }
|
internal HorizontalPosition HorizontalAnchor { get; set; }
|
||||||
internal VerticalPosition VerticalAnchor { get; set; }
|
internal VerticalPosition VerticalAnchor { get; set; }
|
||||||
internal double? InitialHorizontalOffset { get; set; }
|
internal HorizontalPosition ActualHorizontalAnchor { get; set; }
|
||||||
internal double? InitialVerticalOffset { get; set; }
|
internal VerticalPosition ActualVerticalAnchor { get; set; }
|
||||||
|
internal double? HorizontalOffset { get; set; }
|
||||||
|
internal double? VerticalOffset { get; set; }
|
||||||
|
internal double? HorizontalOffsetRatio { get; set; }
|
||||||
|
internal double? VerticalOffsetRatio { get; set; }
|
||||||
internal bool CanClickOnMaskToClose { get; set; }
|
internal bool CanClickOnMaskToClose { get; set; }
|
||||||
|
|
||||||
public event EventHandler<DialogLayerChangeEventArgs>? LayerChanged;
|
public event EventHandler<DialogLayerChangeEventArgs>? LayerChanged;
|
||||||
@@ -55,6 +60,7 @@ public class DialogControl: ContentControl
|
|||||||
|
|
||||||
_titleArea?.RemoveHandler(PointerMovedEvent, OnTitlePointerMove);
|
_titleArea?.RemoveHandler(PointerMovedEvent, OnTitlePointerMove);
|
||||||
_titleArea?.RemoveHandler(PointerPressedEvent, OnTitlePointerPressed);
|
_titleArea?.RemoveHandler(PointerPressedEvent, OnTitlePointerPressed);
|
||||||
|
_titleArea?.RemoveHandler(PointerReleasedEvent, OnTitlePointerRelease);
|
||||||
|
|
||||||
_closeButton = e.NameScope.Find<Button>(PART_CloseButton);
|
_closeButton = e.NameScope.Find<Button>(PART_CloseButton);
|
||||||
_titleArea = e.NameScope.Find<Panel>(PART_TitleArea);
|
_titleArea = e.NameScope.Find<Panel>(PART_TitleArea);
|
||||||
@@ -62,6 +68,7 @@ public class DialogControl: ContentControl
|
|||||||
|
|
||||||
_titleArea?.AddHandler(PointerMovedEvent, OnTitlePointerMove, RoutingStrategies.Bubble);
|
_titleArea?.AddHandler(PointerMovedEvent, OnTitlePointerMove, RoutingStrategies.Bubble);
|
||||||
_titleArea?.AddHandler(PointerPressedEvent, OnTitlePointerPressed, RoutingStrategies.Bubble);
|
_titleArea?.AddHandler(PointerPressedEvent, OnTitlePointerPressed, RoutingStrategies.Bubble);
|
||||||
|
_titleArea?.AddHandler(PointerReleasedEvent, OnTitlePointerRelease, RoutingStrategies.Bubble);
|
||||||
EventHelper.RegisterClickEvent(Close, _closeButton);
|
EventHelper.RegisterClickEvent(Close, _closeButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,11 +82,16 @@ public class DialogControl: ContentControl
|
|||||||
e.Source = this;
|
e.Source = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnTitlePointerRelease(object sender, PointerReleasedEventArgs e)
|
||||||
|
{
|
||||||
|
e.Source = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
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?>();
|
||||||
token?.Register(Close);
|
token?.Register(CloseDialog);
|
||||||
void OnCloseHandler(object sender, object? args)
|
void OnCloseHandler(object sender, object? args)
|
||||||
{
|
{
|
||||||
if (args is T result)
|
if (args is T result)
|
||||||
@@ -137,7 +149,7 @@ public class DialogControl: ContentControl
|
|||||||
PseudoClasses.Set(PC_Modal, modal);
|
PseudoClasses.Set(PC_Modal, modal);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Close()
|
public void CloseDialog()
|
||||||
{
|
{
|
||||||
if (this.DataContext is IDialogContext context)
|
if (this.DataContext is IDialogContext context)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -183,9 +183,11 @@ public static class OverlayDialog
|
|||||||
if (options is null) options = new OverlayDialogOptions();
|
if (options is null) options = new OverlayDialogOptions();
|
||||||
control.HorizontalAnchor = options.HorizontalAnchor;
|
control.HorizontalAnchor = options.HorizontalAnchor;
|
||||||
control.VerticalAnchor = options.VerticalAnchor;
|
control.VerticalAnchor = options.VerticalAnchor;
|
||||||
control.InitialHorizontalOffset =
|
control.ActualHorizontalAnchor = options.HorizontalAnchor;
|
||||||
|
control.ActualVerticalAnchor = options.VerticalAnchor;
|
||||||
|
control.HorizontalOffset =
|
||||||
control.HorizontalAnchor == HorizontalPosition.Center ? null : options.HorizontalOffset;
|
control.HorizontalAnchor == HorizontalPosition.Center ? null : options.HorizontalOffset;
|
||||||
control.InitialVerticalOffset =
|
control.VerticalOffset =
|
||||||
options.VerticalAnchor == VerticalPosition.Center ? null : options.VerticalOffset;
|
options.VerticalAnchor == VerticalPosition.Center ? null : options.VerticalOffset;
|
||||||
control.CanClickOnMaskToClose = options.CanClickOnMaskToClose;
|
control.CanClickOnMaskToClose = options.CanClickOnMaskToClose;
|
||||||
}
|
}
|
||||||
@@ -195,9 +197,11 @@ public static class OverlayDialog
|
|||||||
if (options is null) options = new OverlayDialogOptions();
|
if (options is null) options = new OverlayDialogOptions();
|
||||||
control.HorizontalAnchor = options.HorizontalAnchor;
|
control.HorizontalAnchor = options.HorizontalAnchor;
|
||||||
control.VerticalAnchor = options.VerticalAnchor;
|
control.VerticalAnchor = options.VerticalAnchor;
|
||||||
control.InitialHorizontalOffset =
|
control.ActualHorizontalAnchor = options.HorizontalAnchor;
|
||||||
|
control.ActualVerticalAnchor = options.VerticalAnchor;
|
||||||
|
control.HorizontalOffset =
|
||||||
control.HorizontalAnchor == HorizontalPosition.Center ? null : options.HorizontalOffset;
|
control.HorizontalAnchor == HorizontalPosition.Center ? null : options.HorizontalOffset;
|
||||||
control.InitialVerticalOffset =
|
control.VerticalOffset =
|
||||||
options.VerticalAnchor == VerticalPosition.Center ? null : options.VerticalOffset;
|
options.VerticalAnchor == VerticalPosition.Center ? null : options.VerticalOffset;
|
||||||
control.CanClickOnMaskToClose = options.CanClickOnMaskToClose;
|
control.CanClickOnMaskToClose = options.CanClickOnMaskToClose;
|
||||||
control.Mode = options.Mode;
|
control.Mode = options.Mode;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
|
using Avalonia.Animation;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.Primitives;
|
using Avalonia.Controls.Primitives;
|
||||||
using Avalonia.Controls.Templates;
|
using Avalonia.Controls.Templates;
|
||||||
@@ -21,6 +22,7 @@ public class OverlayDialogHost : Canvas
|
|||||||
|
|
||||||
|
|
||||||
public DataTemplates DialogDataTemplates { get; set; } = new DataTemplates();
|
public DataTemplates DialogDataTemplates { get; set; } = new DataTemplates();
|
||||||
|
public Thickness SnapThickness { get; set; } = new Thickness(0);
|
||||||
|
|
||||||
public static readonly StyledProperty<IBrush?> OverlayMaskBrushProperty =
|
public static readonly StyledProperty<IBrush?> OverlayMaskBrushProperty =
|
||||||
AvaloniaProperty.Register<OverlayDialogHost, IBrush?>(
|
AvaloniaProperty.Register<OverlayDialogHost, IBrush?>(
|
||||||
@@ -56,7 +58,7 @@ public class OverlayDialogHost : Canvas
|
|||||||
{
|
{
|
||||||
int i = _masks.IndexOf(border);
|
int i = _masks.IndexOf(border);
|
||||||
DialogControl dialog = _modalDialogs[i];
|
DialogControl dialog = _modalDialogs[i];
|
||||||
dialog.Close();
|
dialog.CloseDialog();
|
||||||
border.RemoveHandler(PointerReleasedEvent, ClickBorderToCloseDialog);
|
border.RemoveHandler(PointerReleasedEvent, ClickBorderToCloseDialog);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,6 +77,44 @@ public class OverlayDialogHost : Canvas
|
|||||||
_masks[i].Width = this.Bounds.Width;
|
_masks[i].Width = this.Bounds.Width;
|
||||||
_masks[i].Height = this.Bounds.Height;
|
_masks[i].Height = this.Bounds.Height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var oldSize = e.PreviousSize;
|
||||||
|
var newSize = e.NewSize;
|
||||||
|
foreach (var dialog in _dialogs)
|
||||||
|
{
|
||||||
|
ResetDialogPosition(dialog, oldSize, newSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var modalDialog in _modalDialogs)
|
||||||
|
{
|
||||||
|
ResetDialogPosition(modalDialog, oldSize, newSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ResetDialogPosition(DialogControl control, Size oldSize, Size newSize)
|
||||||
|
{
|
||||||
|
var width = newSize.Width - control.Bounds.Width;
|
||||||
|
var height = newSize.Height - control.Bounds.Height;
|
||||||
|
var newLeft = width * control.HorizontalOffsetRatio??0;
|
||||||
|
var newTop = height * control.VerticalOffsetRatio??0;
|
||||||
|
if(control.ActualHorizontalAnchor == HorizontalPosition.Left)
|
||||||
|
{
|
||||||
|
newLeft = 0;
|
||||||
|
}
|
||||||
|
if (control.ActualHorizontalAnchor == HorizontalPosition.Right)
|
||||||
|
{
|
||||||
|
newLeft = newSize.Width - control.Bounds.Width;
|
||||||
|
}
|
||||||
|
if (control.ActualVerticalAnchor == VerticalPosition.Top)
|
||||||
|
{
|
||||||
|
newTop = 0;
|
||||||
|
}
|
||||||
|
if (control.ActualVerticalAnchor == VerticalPosition.Bottom)
|
||||||
|
{
|
||||||
|
newTop = newSize.Height - control.Bounds.Height;
|
||||||
|
}
|
||||||
|
SetLeft(control, Math.Max(0.0, newLeft));
|
||||||
|
SetTop(control, Math.Max(0.0, newTop));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
||||||
@@ -85,7 +125,6 @@ public class OverlayDialogHost : Canvas
|
|||||||
|
|
||||||
protected override void OnPointerMoved(PointerEventArgs e)
|
protected override void OnPointerMoved(PointerEventArgs e)
|
||||||
{
|
{
|
||||||
base.OnPointerMoved(e);
|
|
||||||
if (e.Source is DialogControl item)
|
if (e.Source is DialogControl item)
|
||||||
{
|
{
|
||||||
if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
|
if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
|
||||||
@@ -95,28 +134,35 @@ public class OverlayDialogHost : Canvas
|
|||||||
var top = p.Y - _lastPoint.Y;
|
var top = p.Y - _lastPoint.Y;
|
||||||
left = MathUtilities.Clamp(left, 0, Bounds.Width - item.Bounds.Width);
|
left = MathUtilities.Clamp(left, 0, Bounds.Width - item.Bounds.Width);
|
||||||
top = MathUtilities.Clamp(top, 0, Bounds.Height - item.Bounds.Height);
|
top = MathUtilities.Clamp(top, 0, Bounds.Height - item.Bounds.Height);
|
||||||
Canvas.SetLeft(item, left);
|
SetLeft(item, left);
|
||||||
Canvas.SetTop(item, top);
|
SetTop(item, top);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnPointerPressed(PointerPressedEventArgs e)
|
protected override void OnPointerPressed(PointerPressedEventArgs e)
|
||||||
{
|
{
|
||||||
// base.OnPointerPressed(e);
|
|
||||||
if (e.Source is DialogControl item)
|
if (e.Source is DialogControl item)
|
||||||
{
|
{
|
||||||
_lastPoint = e.GetPosition(item);
|
_lastPoint = e.GetPosition(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnPointerReleased(PointerReleasedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Source is DialogControl item)
|
||||||
|
{
|
||||||
|
AnchorDialog(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal void AddDialog(DialogControl control)
|
internal void AddDialog(DialogControl control)
|
||||||
{
|
{
|
||||||
this.Children.Add(control);
|
this.Children.Add(control);
|
||||||
_dialogs.Add(control);
|
_dialogs.Add(control);
|
||||||
control.Measure(this.Bounds.Size);
|
control.Measure(this.Bounds.Size);
|
||||||
control.Arrange(new Rect(control.DesiredSize));
|
control.Arrange(new Rect(control.DesiredSize));
|
||||||
SetToCenter(control);
|
SetToPosition(control);
|
||||||
control.DialogControlClosing += OnDialogControlClosing;
|
control.DialogControlClosing += OnDialogControlClosing;
|
||||||
control.LayerChanged += OnDialogLayerChanged;
|
control.LayerChanged += OnDialogLayerChanged;
|
||||||
ResetZIndices();
|
ResetZIndices();
|
||||||
@@ -126,7 +172,7 @@ public class OverlayDialogHost : Canvas
|
|||||||
{
|
{
|
||||||
if (sender is DialogControl control)
|
if (sender is DialogControl control)
|
||||||
{
|
{
|
||||||
this.Children.Remove(control);
|
Children.Remove(control);
|
||||||
control.DialogControlClosing -= OnDialogControlClosing;
|
control.DialogControlClosing -= OnDialogControlClosing;
|
||||||
control.LayerChanged -= OnDialogLayerChanged;
|
control.LayerChanged -= OnDialogLayerChanged;
|
||||||
if (_dialogs.Contains(control))
|
if (_dialogs.Contains(control))
|
||||||
@@ -170,7 +216,7 @@ public class OverlayDialogHost : Canvas
|
|||||||
this.Children.Add(control);
|
this.Children.Add(control);
|
||||||
control.Measure(this.Bounds.Size);
|
control.Measure(this.Bounds.Size);
|
||||||
control.Arrange(new Rect(control.DesiredSize));
|
control.Arrange(new Rect(control.DesiredSize));
|
||||||
SetToCenter(control);
|
SetToPosition(control);
|
||||||
control.DialogControlClosing += OnDialogControlClosing;
|
control.DialogControlClosing += OnDialogControlClosing;
|
||||||
control.LayerChanged += OnDialogLayerChanged;
|
control.LayerChanged += OnDialogLayerChanged;
|
||||||
}
|
}
|
||||||
@@ -232,16 +278,105 @@ public class OverlayDialogHost : Canvas
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetToCenter(DialogControl? control)
|
private void SetToPosition(DialogControl? control)
|
||||||
{
|
{
|
||||||
// return;
|
|
||||||
if (control is null) return;
|
if (control is null) return;
|
||||||
double left = (this.Bounds.Width - control.Bounds.Width) / 2;
|
double left = GetLeftPosition(control);
|
||||||
double top = (this.Bounds.Height - control.Bounds.Height) / 2;
|
double top = GetTopPosition(control);
|
||||||
left = MathUtilities.Clamp(left, 0, Bounds.Width);
|
SetLeft(control, left);
|
||||||
top = MathUtilities.Clamp(top, 0, Bounds.Height);
|
SetTop(control, top);
|
||||||
Canvas.SetLeft(control, left);
|
AnchorDialog(control);
|
||||||
Canvas.SetTop(control, top);
|
}
|
||||||
|
|
||||||
|
private void AnchorDialog(DialogControl control)
|
||||||
|
{
|
||||||
|
control.ActualHorizontalAnchor = HorizontalPosition.Center;
|
||||||
|
control.ActualVerticalAnchor = VerticalPosition.Center;
|
||||||
|
double left = GetLeft(control);
|
||||||
|
double top = GetTop(control);
|
||||||
|
double right = Bounds.Width - left - control.Bounds.Width;
|
||||||
|
double bottom = Bounds.Height - top - control.Bounds.Height;
|
||||||
|
if(top < SnapThickness.Top)
|
||||||
|
{
|
||||||
|
SetTop(control, 0);
|
||||||
|
control.ActualVerticalAnchor = VerticalPosition.Top;
|
||||||
|
control.VerticalOffsetRatio = 0;
|
||||||
|
}
|
||||||
|
if(bottom > Bounds.Height - SnapThickness.Bottom)
|
||||||
|
{
|
||||||
|
SetTop(control, Bounds.Height - control.Bounds.Height);
|
||||||
|
control.ActualVerticalAnchor = VerticalPosition.Bottom;
|
||||||
|
control.VerticalOffsetRatio = 1;
|
||||||
|
}
|
||||||
|
if(left < SnapThickness.Left)
|
||||||
|
{
|
||||||
|
SetLeft(control, 0);
|
||||||
|
control.ActualHorizontalAnchor = HorizontalPosition.Left;
|
||||||
|
control.HorizontalOffsetRatio = 0;
|
||||||
|
}
|
||||||
|
if(right > Bounds.Width - SnapThickness.Right)
|
||||||
|
{
|
||||||
|
SetLeft(control, Bounds.Width - control.Bounds.Width);
|
||||||
|
control.ActualHorizontalAnchor = HorizontalPosition.Right;
|
||||||
|
control.HorizontalOffsetRatio = 1;
|
||||||
|
}
|
||||||
|
left = GetLeft(control);
|
||||||
|
top = GetTop(control);
|
||||||
|
right = Bounds.Width - left - control.Bounds.Width;
|
||||||
|
bottom = Bounds.Height - top - control.Bounds.Height;
|
||||||
|
control.HorizontalOffsetRatio = left / (left + right);
|
||||||
|
control.VerticalOffsetRatio = top / (top + bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
private double GetLeftPosition(DialogControl control)
|
||||||
|
{
|
||||||
|
double left = 0;
|
||||||
|
double offset = Math.Max(0, control.HorizontalOffset ?? 0);
|
||||||
|
left = this.Bounds.Width - control.Bounds.Width;
|
||||||
|
if (control.HorizontalAnchor == HorizontalPosition.Center)
|
||||||
|
{
|
||||||
|
left *= 0.5;
|
||||||
|
(double min, double max) = MathUtilities.GetMinMax(0, Bounds.Width * 0.5);
|
||||||
|
left = MathUtilities.Clamp(left, min, max);
|
||||||
|
}
|
||||||
|
else if (control.HorizontalAnchor == HorizontalPosition.Left)
|
||||||
|
{
|
||||||
|
(double min, double max) = MathUtilities.GetMinMax(0, offset);
|
||||||
|
left = MathUtilities.Clamp(left, min, max);
|
||||||
|
}
|
||||||
|
else if (control.HorizontalAnchor == HorizontalPosition.Right)
|
||||||
|
{
|
||||||
|
double leftOffset = Bounds.Width - control.Bounds.Width - offset;
|
||||||
|
leftOffset = Math.Max(0, leftOffset);
|
||||||
|
if(control.HorizontalOffset.HasValue)
|
||||||
|
{
|
||||||
|
left = MathUtilities.Clamp(left, 0, leftOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double GetTopPosition(DialogControl control)
|
||||||
|
{
|
||||||
|
double top = 0;
|
||||||
|
double offset = Math.Max(0, control.VerticalOffset ?? 0);
|
||||||
|
top = this.Bounds.Height - control.Bounds.Height;
|
||||||
|
if (control.VerticalAnchor == VerticalPosition.Center)
|
||||||
|
{
|
||||||
|
top *= 0.5;
|
||||||
|
(double min, double max) = MathUtilities.GetMinMax(0, Bounds.Height * 0.5);
|
||||||
|
top = MathUtilities.Clamp(top, min, max);
|
||||||
|
}
|
||||||
|
else if (control.VerticalAnchor == VerticalPosition.Top)
|
||||||
|
{
|
||||||
|
top = MathUtilities.Clamp(top, 0, offset);
|
||||||
|
}
|
||||||
|
else if (control.VerticalAnchor == VerticalPosition.Bottom)
|
||||||
|
{
|
||||||
|
var topOffset = Math.Max(0, Bounds.Height - control.Bounds.Height - offset);
|
||||||
|
top = MathUtilities.Clamp(top, 0, topOffset);
|
||||||
|
}
|
||||||
|
return top;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal IDataTemplate? GetDataTemplate(object? o)
|
internal IDataTemplate? GetDataTemplate(object? o)
|
||||||
|
|||||||
Reference in New Issue
Block a user