Merge pull request #412 from irihitech/dialogresizer
Introduce Resize feature to Dialog and Drawer.
This commit is contained in:
@@ -50,6 +50,7 @@
|
||||
IsChecked="{Binding IsCloseButtonVisible}"
|
||||
IsThreeState="True" />
|
||||
<CheckBox u:FormItem.Label="CanDragMove" IsChecked="{Binding CanDragMove}" />
|
||||
<CheckBox u:FormItem.Label="CanResize" IsChecked="{Binding CanResize}" />
|
||||
<Button
|
||||
HorizontalAlignment="Left"
|
||||
u:FormItem.NoLabel="True"
|
||||
@@ -85,6 +86,7 @@
|
||||
IsThreeState="True" />
|
||||
<CheckBox u:FormItem.Label="Modal" IsChecked="{Binding IsModal}" />
|
||||
<CheckBox u:FormItem.Label="CanDragMove" IsChecked="{Binding CanDragMove}" />
|
||||
<CheckBox u:FormItem.Label="CanResize" IsChecked="{Binding CanResize}" />
|
||||
<Button
|
||||
HorizontalAlignment="Left"
|
||||
u:FormItem.NoLabel="True"
|
||||
@@ -120,6 +122,7 @@
|
||||
<CheckBox u:FormItem.Label="Can DragMove" IsChecked="{Binding CanDragMove}" />
|
||||
<CheckBox u:FormItem.Label="Can LightDismiss" IsChecked="{Binding CanLightDismiss}" />
|
||||
<CheckBox u:FormItem.Label="FullScreen" IsChecked="{Binding FullScreen}" />
|
||||
<CheckBox u:FormItem.Label="CanResize" IsChecked="{Binding CanResize}" />
|
||||
<ToggleSwitch
|
||||
u:FormItem.Label="Global/Local OverlayHost"
|
||||
IsChecked="{Binding IsLocal}"
|
||||
@@ -150,6 +153,7 @@
|
||||
<CheckBox u:FormItem.Label="Can DragMove" IsChecked="{Binding CanDragMove}" />
|
||||
<CheckBox u:FormItem.Label="Can LightDismiss" IsChecked="{Binding CanLightDismiss}" />
|
||||
<CheckBox u:FormItem.Label="FullScreen" IsChecked="{Binding FullScreen}" />
|
||||
<CheckBox u:FormItem.Label="CanResize" IsChecked="{Binding CanResize}" />
|
||||
<ToggleSwitch
|
||||
u:FormItem.Label="Global/Local OverlayHost"
|
||||
IsChecked="{Binding IsLocal}"
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
<CheckBox u:FormItem.Label="Is Modal" IsChecked="{Binding IsModal}"/>
|
||||
<CheckBox u:FormItem.Label="Is Close Button Visible" IsChecked="{Binding IsCloseButtonVisible}" IsThreeState="True"/>
|
||||
<CheckBox u:FormItem.Label="Custom Dialog" IsChecked="{Binding Custom}"/>
|
||||
<CheckBox u:FormItem.Label="CanResize" IsChecked="{Binding CanResize}" />
|
||||
<ToggleSwitch
|
||||
u:FormItem.Label="Global/Local OverlayHost"
|
||||
IsChecked="{Binding IsLocal}"
|
||||
|
||||
@@ -32,6 +32,7 @@ public partial class DefaultWindowDialogDemoViewModel: ObservableObject
|
||||
[ObservableProperty] private bool _showInTaskBar;
|
||||
[ObservableProperty] private bool? _isCloseButtonVisible;
|
||||
[ObservableProperty] private bool _canDragMove;
|
||||
[ObservableProperty] private bool _canResize;
|
||||
|
||||
public ICommand ShowDialogCommand { get; }
|
||||
|
||||
@@ -55,6 +56,7 @@ public partial class DefaultWindowDialogDemoViewModel: ObservableObject
|
||||
IsCloseButtonVisible = IsCloseButtonVisible,
|
||||
StartupLocation = Location,
|
||||
CanDragMove = CanDragMove,
|
||||
CanResize = CanResize,
|
||||
};
|
||||
if (X.HasValue && Y.HasValue)
|
||||
{
|
||||
@@ -74,6 +76,7 @@ public partial class CustomWindowDialogDemoViewModel: ObservableObject
|
||||
[ObservableProperty] private bool? _isCloseButtonVisible;
|
||||
[ObservableProperty] private bool _isModal;
|
||||
[ObservableProperty] private bool _canDragMove;
|
||||
[ObservableProperty] private bool _canResize;
|
||||
|
||||
public ICommand ShowDialogCommand { get; }
|
||||
|
||||
@@ -94,6 +97,7 @@ public partial class CustomWindowDialogDemoViewModel: ObservableObject
|
||||
IsCloseButtonVisible = IsCloseButtonVisible,
|
||||
StartupLocation = Location,
|
||||
CanDragMove = CanDragMove,
|
||||
CanResize = CanResize,
|
||||
};
|
||||
if (X.HasValue && Y.HasValue)
|
||||
{
|
||||
@@ -128,6 +132,7 @@ public partial class DefaultOverlayDialogDemoViewModel : ObservableObject
|
||||
[ObservableProperty] private bool? _isCloseButtonVisible;
|
||||
[ObservableProperty] private bool _isModal;
|
||||
[ObservableProperty] private bool _isLocal;
|
||||
[ObservableProperty] private bool _canResize;
|
||||
|
||||
public ICommand ShowDialogCommand { get; }
|
||||
|
||||
@@ -157,6 +162,7 @@ public partial class DefaultOverlayDialogDemoViewModel : ObservableObject
|
||||
CanLightDismiss = CanLightDismiss,
|
||||
CanDragMove = CanDragMove,
|
||||
IsCloseButtonVisible = IsCloseButtonVisible,
|
||||
CanResize = CanResize,
|
||||
};
|
||||
string? dialogHostId = IsLocal ? DialogDemoViewModel.LocalHost : null;
|
||||
if (IsModal)
|
||||
@@ -183,6 +189,7 @@ public partial class CustomOverlayDialogDemoViewModel: ObservableObject
|
||||
[ObservableProperty] private bool? _isCloseButtonVisible;
|
||||
[ObservableProperty] private bool _isModal;
|
||||
[ObservableProperty] private bool _isLocal;
|
||||
[ObservableProperty] private bool _canResize;
|
||||
|
||||
public ICommand ShowDialogCommand { get; }
|
||||
|
||||
@@ -208,6 +215,7 @@ public partial class CustomOverlayDialogDemoViewModel: ObservableObject
|
||||
CanLightDismiss = CanLightDismiss,
|
||||
CanDragMove = CanDragMove,
|
||||
IsCloseButtonVisible = IsCloseButtonVisible,
|
||||
CanResize = CanResize,
|
||||
};
|
||||
var dialogHostId = IsLocal ? DialogDemoViewModel.LocalHost : null;
|
||||
if (IsModal)
|
||||
|
||||
@@ -24,6 +24,7 @@ public partial class DrawerDemoViewModel : ObservableObject
|
||||
|
||||
[ObservableProperty] private bool _custom;
|
||||
[ObservableProperty] private bool _isLocal;
|
||||
[ObservableProperty] private bool _canResize;
|
||||
|
||||
public DrawerDemoViewModel()
|
||||
{
|
||||
@@ -42,6 +43,7 @@ public partial class DrawerDemoViewModel : ObservableObject
|
||||
CanLightDismiss = CanLightDismiss,
|
||||
IsCloseButtonVisible = IsCloseButtonVisible,
|
||||
Title = Title,
|
||||
CanResize = CanResize,
|
||||
};
|
||||
var hostId = IsLocal ? "LocalHost" : null;
|
||||
if (Custom)
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
x:CompileBindings="True"
|
||||
IsFullScreenButtonVisible="{OnPlatform True,macOS=False}"
|
||||
IsFullScreenButtonVisible="{OnPlatform True, macOS=False}"
|
||||
IsManagedResizerVisible="{OnPlatform False, Linux=True}"
|
||||
x:DataType="viewModels:MainWindowViewModel"
|
||||
Icon="/Assets/Ursa.ico"
|
||||
mc:Ignorable="d">
|
||||
|
||||
@@ -7,68 +7,72 @@
|
||||
<ControlTheme x:Key="{x:Type u:OverlayDialogHost}" TargetType="u:OverlayDialogHost">
|
||||
<Setter Property="OverlayMaskBrush" Value="{DynamicResource OverlayDialogMaskBrush}" />
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:CustomDialogControl}" TargetType="u:CustomDialogControl">
|
||||
<Setter Property="MinWidth" Value="{DynamicResource DialogMinWidth}"/>
|
||||
<Setter Property="MinHeight" Value="{DynamicResource DialogMinHeight}"/>
|
||||
<Setter Property="CornerRadius" Value="{DynamicResource DialogCornerRadius}" />
|
||||
<Setter Property="Transitions">
|
||||
<Transitions>
|
||||
<TransformOperationsTransition Duration="0.2" Property="RenderTransform"/>
|
||||
<TransformOperationsTransition Property="RenderTransform" Duration="0.2" />
|
||||
</Transitions>
|
||||
</Setter>
|
||||
<Setter Property="RenderTransform" Value="scale(1.0)"></Setter>
|
||||
<Setter Property="RenderTransform" Value="scale(1.0)" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:CustomDialogControl">
|
||||
<Border
|
||||
Name="PART_Border"
|
||||
Focusable="True"
|
||||
Padding="0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Classes="Shadow"
|
||||
ClipToBounds="False"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
IsHitTestVisible="True"
|
||||
Theme="{DynamicResource CardBorder}">
|
||||
<Border ClipToBounds="True" CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<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:DialogControlBase.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 OverlayCloseButton}" />
|
||||
<Panel>
|
||||
<Border
|
||||
Name="PART_Border"
|
||||
Padding="0"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalAlignment}"
|
||||
Classes="Shadow"
|
||||
ClipToBounds="False"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
Focusable="True"
|
||||
IsHitTestVisible="True"
|
||||
Theme="{DynamicResource CardBorder}">
|
||||
<Border ClipToBounds="True" CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<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:DialogControlBase.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 OverlayCloseButton}" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Border>
|
||||
</Border>
|
||||
<u:DialogResizer IsVisible="{TemplateBinding CanResize}" Margin="{Binding #PART_Border.Margin}" />
|
||||
</Panel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^:full-screen">
|
||||
<Setter Property="CornerRadius" Value="0"/>
|
||||
<Setter Property="CornerRadius" Value="0" />
|
||||
<Style Selector="^ /template/ Border#PART_Border">
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
||||
<Setter Property="VerticalAlignment" Value="Stretch"/>
|
||||
<Setter Property="Theme" Value="{x:Null}"/>
|
||||
<Setter Property="Margin" Value="0"/>
|
||||
<Setter Property="Background" Value="{DynamicResource BorderCardBackground}"></Setter>
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
||||
<Setter Property="VerticalAlignment" Value="Stretch" />
|
||||
<Setter Property="Theme" Value="{x:Null}" />
|
||||
<Setter Property="Margin" Value="0" />
|
||||
<Setter Property="Background" Value="{DynamicResource BorderCardBackground}" />
|
||||
</Style>
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Panel#PART_TitleArea">
|
||||
<Setter Property="ContextFlyout">
|
||||
<MenuFlyout>
|
||||
<MenuItem
|
||||
Command="{Binding $parent[u:DialogControlBase].Close}"
|
||||
Header="{DynamicResource STRING_MENU_DIALOG_CLOSE}">
|
||||
<MenuItem Command="{Binding $parent[u:DialogControlBase].Close}" Header="{DynamicResource STRING_MENU_DIALOG_CLOSE}">
|
||||
<MenuItem.Icon>
|
||||
<PathIcon
|
||||
Width="12"
|
||||
@@ -126,9 +130,7 @@
|
||||
Data="{DynamicResource DialogArrangeSendToBackGlyph}" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
Command="{Binding $parent[u:DialogControlBase].Close}"
|
||||
Header="{DynamicResource STRING_MENU_DIALOG_CLOSE}">
|
||||
<MenuItem Command="{Binding $parent[u:DialogControlBase].Close}" Header="{DynamicResource STRING_MENU_DIALOG_CLOSE}">
|
||||
<MenuItem.Icon>
|
||||
<PathIcon
|
||||
Width="12"
|
||||
@@ -142,111 +144,115 @@
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:DefaultDialogControl}" TargetType="u:DefaultDialogControl">
|
||||
<Setter Property="MinWidth" Value="{DynamicResource DialogMinWidth}"/>
|
||||
<Setter Property="MinHeight" Value="{DynamicResource DialogMinHeight}"/>
|
||||
<Setter Property="CornerRadius" Value="{DynamicResource DialogCornerRadius}" />
|
||||
<Setter Property="Transitions">
|
||||
<Transitions>
|
||||
<TransformOperationsTransition Duration="0.2" Property="RenderTransform"/>
|
||||
<TransformOperationsTransition Property="RenderTransform" Duration="0.2" />
|
||||
</Transitions>
|
||||
</Setter>
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:DefaultDialogControl">
|
||||
<Border
|
||||
Name="PART_Border"
|
||||
Padding="0"
|
||||
Focusable="True"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalAlignment}"
|
||||
BoxShadow="0 0 8 0 #1A000000"
|
||||
Classes="Shadow"
|
||||
ClipToBounds="False"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
IsHitTestVisible="True"
|
||||
Theme="{DynamicResource CardBorder}">
|
||||
<Border ClipToBounds="True" CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<Grid RowDefinitions="Auto, *, Auto">
|
||||
<ScrollViewer Grid.Row="1">
|
||||
<ContentPresenter
|
||||
Name="PART_ContentPresenter"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Margin="24,8"
|
||||
Content="{TemplateBinding Content}" />
|
||||
</ScrollViewer>
|
||||
<Grid Grid.Row="0" ColumnDefinitions="Auto, *, Auto">
|
||||
<Panel
|
||||
Name="{x:Static u:DialogControlBase.PART_TitleArea}"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="3"
|
||||
Background="Transparent" />
|
||||
<PathIcon
|
||||
Name="PART_Icon"
|
||||
Grid.Column="0"
|
||||
Width="16"
|
||||
Height="16"
|
||||
Margin="24,24,8,0"
|
||||
VerticalAlignment="Center" />
|
||||
<TextBlock
|
||||
Name="PART_Title"
|
||||
Grid.Column="1"
|
||||
Margin="0,24,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="16"
|
||||
FontWeight="{DynamicResource TextBlockTitleFontWeight}"
|
||||
IsHitTestVisible="False"
|
||||
IsVisible="{TemplateBinding Title,
|
||||
Converter={x:Static ObjectConverters.IsNotNull}}"
|
||||
Text="{TemplateBinding Title}"
|
||||
TextWrapping="Wrap" />
|
||||
<Button
|
||||
Name="{x:Static u:MessageBoxWindow.PART_CloseButton}"
|
||||
Grid.Column="2"
|
||||
Margin="0,24,24,0"
|
||||
DockPanel.Dock="Right"
|
||||
Theme="{DynamicResource OverlayCloseButton}" />
|
||||
<Panel>
|
||||
<Border
|
||||
Name="PART_Border"
|
||||
Padding="0"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalAlignment}"
|
||||
BoxShadow="0 0 8 0 #1A000000"
|
||||
Classes="Shadow"
|
||||
ClipToBounds="False"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
Focusable="True"
|
||||
IsHitTestVisible="True"
|
||||
Theme="{DynamicResource CardBorder}">
|
||||
<Border ClipToBounds="True" CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<Grid RowDefinitions="Auto, *, Auto">
|
||||
<ScrollViewer Grid.Row="1">
|
||||
<ContentPresenter
|
||||
Name="PART_ContentPresenter"
|
||||
Margin="24,8"
|
||||
Content="{TemplateBinding Content}" />
|
||||
</ScrollViewer>
|
||||
<Grid Grid.Row="0" ColumnDefinitions="Auto, *, Auto">
|
||||
<Panel
|
||||
Name="{x:Static u:DialogControlBase.PART_TitleArea}"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="3"
|
||||
Background="Transparent" />
|
||||
<PathIcon
|
||||
Name="PART_Icon"
|
||||
Grid.Column="0"
|
||||
Width="16"
|
||||
Height="16"
|
||||
Margin="24,24,8,0"
|
||||
VerticalAlignment="Center" />
|
||||
<TextBlock
|
||||
Name="PART_Title"
|
||||
Grid.Column="1"
|
||||
Margin="0,24,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="16"
|
||||
FontWeight="{DynamicResource TextBlockTitleFontWeight}"
|
||||
IsHitTestVisible="False"
|
||||
IsVisible="{TemplateBinding Title,
|
||||
Converter={x:Static ObjectConverters.IsNotNull}}"
|
||||
Text="{TemplateBinding Title}"
|
||||
TextWrapping="Wrap" />
|
||||
<Button
|
||||
Name="{x:Static u:MessageBoxWindow.PART_CloseButton}"
|
||||
Grid.Column="2"
|
||||
Margin="0,24,24,0"
|
||||
DockPanel.Dock="Right"
|
||||
Theme="{DynamicResource OverlayCloseButton}" />
|
||||
</Grid>
|
||||
<StackPanel
|
||||
Grid.Row="2"
|
||||
Margin="24,0,24,24"
|
||||
HorizontalAlignment="Right"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
Name="{x:Static u:DefaultDialogControl.PART_CancelButton}"
|
||||
Margin="8,0,0,0"
|
||||
Classes="Tertiary"
|
||||
Content="{DynamicResource STRING_MENU_DIALOG_CANCEL}" />
|
||||
<Button
|
||||
Name="{x:Static u:DefaultDialogControl.PART_NoButton}"
|
||||
Margin="8,0,0,0"
|
||||
Classes="Danger"
|
||||
Content="{DynamicResource STRING_MENU_DIALOG_NO}"
|
||||
Theme="{DynamicResource SolidButton}" />
|
||||
<Button
|
||||
Name="{x:Static u:DefaultDialogControl.PART_YesButton}"
|
||||
Margin="8,0,0,0"
|
||||
Classes="Primary"
|
||||
Content="{DynamicResource STRING_MENU_DIALOG_YES}"
|
||||
Theme="{DynamicResource SolidButton}" />
|
||||
<Button
|
||||
Name="{x:Static u:DefaultDialogControl.PART_OKButton}"
|
||||
Margin="8,0,0,0"
|
||||
Classes="Primary"
|
||||
Content="{DynamicResource STRING_MENU_DIALOG_OK}"
|
||||
Theme="{DynamicResource SolidButton}" />
|
||||
</StackPanel>
|
||||
|
||||
</Grid>
|
||||
<StackPanel
|
||||
Grid.Row="2"
|
||||
Margin="24,0,24,24"
|
||||
HorizontalAlignment="Right"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
Name="{x:Static u:DefaultDialogControl.PART_CancelButton}"
|
||||
Margin="8,0,0,0"
|
||||
Classes="Tertiary"
|
||||
Content="{DynamicResource STRING_MENU_DIALOG_CANCEL}" />
|
||||
<Button
|
||||
Name="{x:Static u:DefaultDialogControl.PART_NoButton}"
|
||||
Margin="8,0,0,0"
|
||||
Classes="Danger"
|
||||
Content="{DynamicResource STRING_MENU_DIALOG_NO}"
|
||||
Theme="{DynamicResource SolidButton}" />
|
||||
<Button
|
||||
Name="{x:Static u:DefaultDialogControl.PART_YesButton}"
|
||||
Margin="8,0,0,0"
|
||||
Classes="Primary"
|
||||
Content="{DynamicResource STRING_MENU_DIALOG_YES}"
|
||||
Theme="{DynamicResource SolidButton}" />
|
||||
<Button
|
||||
Name="{x:Static u:DefaultDialogControl.PART_OKButton}"
|
||||
Margin="8,0,0,0"
|
||||
Classes="Primary"
|
||||
Content="{DynamicResource STRING_MENU_DIALOG_OK}"
|
||||
Theme="{DynamicResource SolidButton}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Border>
|
||||
</Border>
|
||||
<u:DialogResizer IsVisible="{TemplateBinding CanResize}" Margin="{Binding #PART_Border.Margin}"/>
|
||||
</Panel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^:full-screen">
|
||||
<Setter Property="CornerRadius" Value="0"/>
|
||||
<Setter Property="CornerRadius" Value="0" />
|
||||
</Style>
|
||||
<Style Selector="^:full-screen /template/ Border#PART_Border">
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
||||
<Setter Property="VerticalAlignment" Value="Stretch"/>
|
||||
<Setter Property="Theme" Value="{x:Null}"/>
|
||||
<Setter Property="Margin" Value="0"></Setter>
|
||||
<Setter Property="Background" Value="{DynamicResource BorderCardBackground}"></Setter>
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
||||
<Setter Property="VerticalAlignment" Value="Stretch" />
|
||||
<Setter Property="Theme" Value="{x:Null}" />
|
||||
<Setter Property="Margin" Value="0" />
|
||||
<Setter Property="Background" Value="{DynamicResource BorderCardBackground}" />
|
||||
</Style>
|
||||
<Style Selector="^[Mode=None]">
|
||||
<Style Selector="^ /template/ PathIcon#PART_Icon">
|
||||
@@ -369,9 +375,7 @@
|
||||
<Style Selector="^ /template/ Panel#PART_TitleArea">
|
||||
<Setter Property="ContextFlyout">
|
||||
<MenuFlyout>
|
||||
<MenuItem
|
||||
Command="{Binding $parent[u:DialogControlBase].Close}"
|
||||
Header="{DynamicResource STRING_MENU_DIALOG_CLOSE}">
|
||||
<MenuItem Command="{Binding $parent[u:DialogControlBase].Close}" Header="{DynamicResource STRING_MENU_DIALOG_CLOSE}">
|
||||
<MenuItem.Icon>
|
||||
<PathIcon
|
||||
Width="12"
|
||||
@@ -458,6 +462,8 @@
|
||||
<Setter Property="ExtendClientAreaTitleBarHeightHint" Value="1" />
|
||||
<Setter Property="ExtendClientAreaToDecorationsHint" Value="True" />
|
||||
<Setter Property="ExtendClientAreaChromeHints" Value="SystemChrome" />
|
||||
<Setter Property="MinWidth" Value="{DynamicResource DialogMinWidth}"/>
|
||||
<Setter Property="MinHeight" Value="{DynamicResource DialogMinHeight}"/>
|
||||
<Setter Property="SystemDecorations">
|
||||
<OnPlatform>
|
||||
<OnPlatform.Windows>
|
||||
@@ -473,11 +479,12 @@
|
||||
<ControlTemplate TargetType="u:DialogWindow">
|
||||
<Panel>
|
||||
<Border Name="PART_TransparencyFallback" IsHitTestVisible="False" />
|
||||
<Border Background="{TemplateBinding Background}"
|
||||
BackgroundSizing="InnerBorderEdge"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
IsHitTestVisible="False" />
|
||||
<Border
|
||||
Background="{TemplateBinding Background}"
|
||||
BackgroundSizing="InnerBorderEdge"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
IsHitTestVisible="False" />
|
||||
<Panel Margin="{TemplateBinding WindowDecorationMargin}" Background="Transparent" />
|
||||
<VisualLayerManager>
|
||||
<Grid RowDefinitions="Auto, *">
|
||||
@@ -505,8 +512,10 @@
|
||||
Margin="0,24,24,0"
|
||||
Theme="{DynamicResource CloseButton}" />
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
</VisualLayerManager>
|
||||
<u:WindowResizer IsVisible="{TemplateBinding IsManagedResizerVisible}" />
|
||||
</Panel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
@@ -525,6 +534,8 @@
|
||||
<Setter Property="ExtendClientAreaTitleBarHeightHint" Value="1" />
|
||||
<Setter Property="ExtendClientAreaToDecorationsHint" Value="True" />
|
||||
<Setter Property="ExtendClientAreaChromeHints" Value="SystemChrome" />
|
||||
<Setter Property="MinWidth" Value="{DynamicResource DialogMinWidth}"/>
|
||||
<Setter Property="MinHeight" Value="{DynamicResource DialogMinHeight}"/>
|
||||
<Setter Property="SystemDecorations">
|
||||
<OnPlatform>
|
||||
<OnPlatform.Windows>
|
||||
@@ -540,11 +551,12 @@
|
||||
<ControlTemplate TargetType="u:DefaultDialogWindow">
|
||||
<Panel>
|
||||
<Border Name="PART_TransparencyFallback" IsHitTestVisible="False" />
|
||||
<Border Background="{TemplateBinding Background}"
|
||||
BackgroundSizing="InnerBorderEdge"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
IsHitTestVisible="False" />
|
||||
<Border
|
||||
Background="{TemplateBinding Background}"
|
||||
BackgroundSizing="InnerBorderEdge"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
IsHitTestVisible="False" />
|
||||
<Panel Margin="{TemplateBinding WindowDecorationMargin}" Background="Transparent" />
|
||||
<VisualLayerManager>
|
||||
<Grid RowDefinitions="Auto, *, Auto">
|
||||
@@ -614,8 +626,10 @@
|
||||
Content="{DynamicResource STRING_MENU_DIALOG_OK}"
|
||||
Theme="{DynamicResource SolidButton}" />
|
||||
</StackPanel>
|
||||
|
||||
</Grid>
|
||||
</VisualLayerManager>
|
||||
<u:WindowResizer IsVisible="{TemplateBinding IsManagedResizerVisible}" />
|
||||
</Panel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
@@ -738,4 +752,4 @@
|
||||
</Style>
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary>
|
||||
@@ -1,154 +1,60 @@
|
||||
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:u="https://irihi.tech/ursa"
|
||||
xmlns:c="clr-namespace:Ursa.Themes.Semi.Converters">
|
||||
<ControlTheme TargetType="u:CustomDrawerControl" x:Key="{x:Type u:CustomDrawerControl}">
|
||||
<Setter Property="VerticalAlignment" Value="Stretch"></Setter>
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch"></Setter>
|
||||
<Setter Property="Padding" Value="{DynamicResource DrawerMargin}"/>
|
||||
<Setter Property="BorderThickness" Value="{DynamicResource DrawerBorderThickness}"/>
|
||||
<Setter Property="CornerRadius" Value="{DynamicResource DrawerCornerRadius}"/>
|
||||
<ResourceDictionary
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:c="clr-namespace:Ursa.Themes.Semi.Converters"
|
||||
xmlns:u="https://irihi.tech/ursa">
|
||||
<ControlTheme x:Key="{x:Type u:CustomDrawerControl}" TargetType="u:CustomDrawerControl">
|
||||
<Setter Property="VerticalAlignment" Value="Stretch" />
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
||||
<Setter Property="MinWidth" Value="96" />
|
||||
<Setter Property="MinHeight" Value="96" />
|
||||
<Setter Property="Padding" Value="{DynamicResource DrawerMargin}" />
|
||||
<Setter Property="BorderThickness" Value="{DynamicResource DrawerBorderThickness}" />
|
||||
<Setter Property="CornerRadius" Value="{DynamicResource DrawerCornerRadius}" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:CustomDrawerControl">
|
||||
<Border Name="PART_Root"
|
||||
Focusable="True"
|
||||
Margin="{TemplateBinding Padding, Converter={x:Static c:ThicknessTakeConverter.Left}}"
|
||||
<Panel>
|
||||
<Border
|
||||
Name="PART_Root"
|
||||
Margin="{TemplateBinding Padding,
|
||||
Converter={x:Static c:ThicknessTakeConverter.Left}}"
|
||||
Padding="0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
BorderThickness="{TemplateBinding BorderThickness,
|
||||
Converter={x:Static c:ThicknessTakeConverter.Left}}"
|
||||
Classes="Shadow"
|
||||
ClipToBounds="False"
|
||||
CornerRadius="{TemplateBinding CornerRadius, Converter={x:Static c:CornerRadiusTakeConverter.Left}}"
|
||||
BorderThickness="{TemplateBinding BorderThickness, Converter={x:Static c:ThicknessTakeConverter.Left}}"
|
||||
IsHitTestVisible="True"
|
||||
Theme="{DynamicResource CardBorder}">
|
||||
<Border ClipToBounds="True" CornerRadius="{Binding #PART_Root.CornerRadius}">
|
||||
<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:DialogControlBase.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 OverlayCloseButton}" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^[Position=Right] /template/ Border#PART_Root">
|
||||
<Setter Property="Margin" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Padding, Converter={x:Static c:ThicknessTakeConverter.Left}}" />
|
||||
<Setter Property="CornerRadius" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=CornerRadius, Converter={x:Static c:CornerRadiusTakeConverter.Left}}" />
|
||||
<Setter Property="BorderThickness" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderThickness, Converter={x:Static c:ThicknessTakeConverter.Left}}" />
|
||||
</Style>
|
||||
<Style Selector="^[Position=Left] /template/ Border#PART_Root">
|
||||
<Setter Property="Margin" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Padding, Converter={x:Static c:ThicknessTakeConverter.Right}}" />
|
||||
<Setter Property="CornerRadius" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=CornerRadius, Converter={x:Static c:CornerRadiusTakeConverter.Right}}" />
|
||||
<Setter Property="BorderThickness" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderThickness, Converter={x:Static c:ThicknessTakeConverter.Right}}" />
|
||||
</Style>
|
||||
<Style Selector="^[Position=Top] /template/ Border#PART_Root">
|
||||
<Setter Property="Margin" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Padding, Converter={x:Static c:ThicknessTakeConverter.Bottom}}" />
|
||||
<Setter Property="CornerRadius" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=CornerRadius, Converter={x:Static c:CornerRadiusTakeConverter.Bottom}}" />
|
||||
<Setter Property="BorderThickness" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderThickness, Converter={x:Static c:ThicknessTakeConverter.Bottom}}" />
|
||||
</Style>
|
||||
<Style Selector="^[Position=Bottom] /template/ Border#PART_Root">
|
||||
<Setter Property="Margin" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Padding, Converter={x:Static c:ThicknessTakeConverter.Top}}" />
|
||||
<Setter Property="CornerRadius" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=CornerRadius, Converter={x:Static c:CornerRadiusTakeConverter.Top}}" />
|
||||
<Setter Property="BorderThickness" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderThickness, Converter={x:Static c:ThicknessTakeConverter.Top}}" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:DefaultDrawerControl}" TargetType="u:DefaultDrawerControl">
|
||||
<Setter Property="VerticalAlignment" Value="Stretch"></Setter>
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch"></Setter>
|
||||
<Setter Property="Padding" Value="{DynamicResource DrawerMargin}"/>
|
||||
<Setter Property="BorderThickness" Value="{DynamicResource DrawerBorderThickness}"/>
|
||||
<Setter Property="CornerRadius" Value="{DynamicResource DrawerCornerRadius}"/>
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:DefaultDrawerControl">
|
||||
<Border Name="PART_Root"
|
||||
CornerRadius="{TemplateBinding CornerRadius,
|
||||
Converter={x:Static c:CornerRadiusTakeConverter.Left}}"
|
||||
Focusable="True"
|
||||
Margin="{TemplateBinding Padding, Converter={x:Static c:ThicknessTakeConverter.Left}}"
|
||||
Padding="0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Classes="Shadow"
|
||||
ClipToBounds="False"
|
||||
CornerRadius="{TemplateBinding CornerRadius, Converter={x:Static c:CornerRadiusTakeConverter.Left}}"
|
||||
BorderThickness="{TemplateBinding BorderThickness, Converter={x:Static c:ThicknessTakeConverter.Left}}"
|
||||
IsHitTestVisible="True"
|
||||
Theme="{DynamicResource CardBorder}">
|
||||
<Border ClipToBounds="True" CornerRadius="{Binding #PART_Root.CornerRadius}">
|
||||
<Grid RowDefinitions="Auto, *, Auto">
|
||||
<ScrollViewer Grid.Row="1">
|
||||
<Border ClipToBounds="True" CornerRadius="{Binding #PART_Root.CornerRadius}">
|
||||
<Grid RowDefinitions="Auto, *">
|
||||
<ContentPresenter
|
||||
Name="PART_ContentPresenter"
|
||||
Margin="24,8"
|
||||
Grid.Row="0"
|
||||
Grid.RowSpan="2"
|
||||
Content="{TemplateBinding Content}" />
|
||||
</ScrollViewer>
|
||||
<Grid Grid.Row="0" ColumnDefinitions=" *, Auto">
|
||||
<TextBlock
|
||||
Name="PART_Title"
|
||||
Grid.Column="0"
|
||||
Margin="24,24,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="16"
|
||||
FontWeight="{DynamicResource TextBlockTitleFontWeight}"
|
||||
IsHitTestVisible="False"
|
||||
IsVisible="{TemplateBinding Title,
|
||||
Converter={x:Static ObjectConverters.IsNotNull}}"
|
||||
Text="{TemplateBinding Title}"
|
||||
TextWrapping="Wrap" />
|
||||
<Button
|
||||
Name="{x:Static u:DrawerControlBase.PART_CloseButton}"
|
||||
Grid.Column="1"
|
||||
Margin="0,24,24,0"
|
||||
DockPanel.Dock="Right"
|
||||
Theme="{DynamicResource OverlayCloseButton}" />
|
||||
<Grid Grid.Row="0" ColumnDefinitions="*, Auto">
|
||||
<Panel
|
||||
Name="{x:Static u:DialogControlBase.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 OverlayCloseButton}" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
<StackPanel
|
||||
Grid.Row="2"
|
||||
Margin="24,0,24,24"
|
||||
HorizontalAlignment="Right"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
Name="{x:Static u:DefaultDialogControl.PART_CancelButton}"
|
||||
Margin="8,0,0,0"
|
||||
Classes="Tertiary"
|
||||
Content="{DynamicResource STRING_MENU_DIALOG_CANCEL}" />
|
||||
<Button
|
||||
Name="{x:Static u:DefaultDialogControl.PART_NoButton}"
|
||||
Margin="8,0,0,0"
|
||||
Classes="Danger"
|
||||
Content="{DynamicResource STRING_MENU_DIALOG_NO}"
|
||||
Theme="{DynamicResource SolidButton}" />
|
||||
<Button
|
||||
Name="{x:Static u:DefaultDialogControl.PART_YesButton}"
|
||||
Margin="8,0,0,0"
|
||||
Classes="Primary"
|
||||
Content="{DynamicResource STRING_MENU_DIALOG_YES}"
|
||||
Theme="{DynamicResource SolidButton}" />
|
||||
<Button
|
||||
Name="{x:Static u:DefaultDialogControl.PART_OKButton}"
|
||||
Margin="8,0,0,0"
|
||||
Classes="Primary"
|
||||
Content="{DynamicResource STRING_MENU_DIALOG_OK}"
|
||||
Theme="{DynamicResource SolidButton}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Border>
|
||||
</Border>
|
||||
<u:DialogResizer IsVisible="{TemplateBinding CanResize}" />
|
||||
</Panel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^[Position=Right] /template/ Border#PART_Root">
|
||||
@@ -171,5 +77,150 @@
|
||||
<Setter Property="CornerRadius" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=CornerRadius, Converter={x:Static c:CornerRadiusTakeConverter.Top}}" />
|
||||
<Setter Property="BorderThickness" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderThickness, Converter={x:Static c:ThicknessTakeConverter.Top}}" />
|
||||
</Style>
|
||||
<Style Selector="^[Position=Top] /template/ u|DialogResizer">
|
||||
<Setter Property="Margin" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Padding, Converter={x:Static c:ThicknessTakeConverter.Bottom}}" />
|
||||
<Setter Property="ResizeDirection" Value="Bottom"/>
|
||||
</Style>
|
||||
<Style Selector="^[Position=Bottom] /template/ u|DialogResizer">
|
||||
<Setter Property="Margin" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Padding, Converter={x:Static c:ThicknessTakeConverter.Top}}" />
|
||||
<Setter Property="ResizeDirection" Value="Top"/>
|
||||
</Style>
|
||||
<Style Selector="^[Position=Left] /template/ u|DialogResizer">
|
||||
<Setter Property="Margin" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Padding, Converter={x:Static c:ThicknessTakeConverter.Right}}" />
|
||||
<Setter Property="ResizeDirection" Value="Right"/>
|
||||
</Style>
|
||||
<Style Selector="^[Position=Right] /template/ u|DialogResizer">
|
||||
<Setter Property="Margin" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Padding, Converter={x:Static c:ThicknessTakeConverter.Left}}" />
|
||||
<Setter Property="ResizeDirection" Value="Left"/>
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:DefaultDrawerControl}" TargetType="u:DefaultDrawerControl">
|
||||
<Setter Property="VerticalAlignment" Value="Stretch" />
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
||||
<Setter Property="MinWidth" Value="96" />
|
||||
<Setter Property="MinHeight" Value="96" />
|
||||
<Setter Property="Padding" Value="{DynamicResource DrawerMargin}" />
|
||||
<Setter Property="BorderThickness" Value="{DynamicResource DrawerBorderThickness}" />
|
||||
<Setter Property="CornerRadius" Value="{DynamicResource DrawerCornerRadius}" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:DefaultDrawerControl">
|
||||
<Panel>
|
||||
<Border
|
||||
Name="PART_Root"
|
||||
Margin="{TemplateBinding Padding,
|
||||
Converter={x:Static c:ThicknessTakeConverter.Left}}"
|
||||
Padding="0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
BorderThickness="{TemplateBinding BorderThickness,
|
||||
Converter={x:Static c:ThicknessTakeConverter.Left}}"
|
||||
Classes="Shadow"
|
||||
ClipToBounds="False"
|
||||
CornerRadius="{TemplateBinding CornerRadius,
|
||||
Converter={x:Static c:CornerRadiusTakeConverter.Left}}"
|
||||
Focusable="True"
|
||||
IsHitTestVisible="True"
|
||||
Theme="{DynamicResource CardBorder}">
|
||||
<Border ClipToBounds="True" CornerRadius="{Binding #PART_Root.CornerRadius}">
|
||||
<Grid RowDefinitions="Auto, *, Auto">
|
||||
<ScrollViewer Grid.Row="1">
|
||||
<ContentPresenter
|
||||
Name="PART_ContentPresenter"
|
||||
Margin="24,8"
|
||||
Content="{TemplateBinding Content}" />
|
||||
</ScrollViewer>
|
||||
<Grid Grid.Row="0" ColumnDefinitions=" *, Auto">
|
||||
<TextBlock
|
||||
Name="PART_Title"
|
||||
Grid.Column="0"
|
||||
Margin="24,24,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="16"
|
||||
FontWeight="{DynamicResource TextBlockTitleFontWeight}"
|
||||
IsHitTestVisible="False"
|
||||
IsVisible="{TemplateBinding Title,
|
||||
Converter={x:Static ObjectConverters.IsNotNull}}"
|
||||
Text="{TemplateBinding Title}"
|
||||
TextWrapping="Wrap" />
|
||||
<Button
|
||||
Name="{x:Static u:DrawerControlBase.PART_CloseButton}"
|
||||
Grid.Column="1"
|
||||
Margin="0,24,24,0"
|
||||
DockPanel.Dock="Right"
|
||||
Theme="{DynamicResource OverlayCloseButton}" />
|
||||
</Grid>
|
||||
<StackPanel
|
||||
Grid.Row="2"
|
||||
Margin="24,0,24,24"
|
||||
HorizontalAlignment="Right"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
Name="{x:Static u:DefaultDialogControl.PART_CancelButton}"
|
||||
Margin="8,0,0,0"
|
||||
Classes="Tertiary"
|
||||
Content="{DynamicResource STRING_MENU_DIALOG_CANCEL}" />
|
||||
<Button
|
||||
Name="{x:Static u:DefaultDialogControl.PART_NoButton}"
|
||||
Margin="8,0,0,0"
|
||||
Classes="Danger"
|
||||
Content="{DynamicResource STRING_MENU_DIALOG_NO}"
|
||||
Theme="{DynamicResource SolidButton}" />
|
||||
<Button
|
||||
Name="{x:Static u:DefaultDialogControl.PART_YesButton}"
|
||||
Margin="8,0,0,0"
|
||||
Classes="Primary"
|
||||
Content="{DynamicResource STRING_MENU_DIALOG_YES}"
|
||||
Theme="{DynamicResource SolidButton}" />
|
||||
<Button
|
||||
Name="{x:Static u:DefaultDialogControl.PART_OKButton}"
|
||||
Margin="8,0,0,0"
|
||||
Classes="Primary"
|
||||
Content="{DynamicResource STRING_MENU_DIALOG_OK}"
|
||||
Theme="{DynamicResource SolidButton}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Border>
|
||||
<u:DialogResizer IsVisible="{TemplateBinding CanResize}" />
|
||||
</Panel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^[Position=Right] /template/ Border#PART_Root">
|
||||
<Setter Property="Margin" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Padding, Converter={x:Static c:ThicknessTakeConverter.Left}}" />
|
||||
<Setter Property="CornerRadius" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=CornerRadius, Converter={x:Static c:CornerRadiusTakeConverter.Left}}" />
|
||||
<Setter Property="BorderThickness" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderThickness, Converter={x:Static c:ThicknessTakeConverter.Left}}" />
|
||||
</Style>
|
||||
<Style Selector="^[Position=Left] /template/ Border#PART_Root">
|
||||
<Setter Property="Margin" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Padding, Converter={x:Static c:ThicknessTakeConverter.Right}}" />
|
||||
<Setter Property="CornerRadius" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=CornerRadius, Converter={x:Static c:CornerRadiusTakeConverter.Right}}" />
|
||||
<Setter Property="BorderThickness" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderThickness, Converter={x:Static c:ThicknessTakeConverter.Right}}" />
|
||||
</Style>
|
||||
<Style Selector="^[Position=Top] /template/ Border#PART_Root">
|
||||
<Setter Property="Margin" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Padding, Converter={x:Static c:ThicknessTakeConverter.Bottom}}" />
|
||||
<Setter Property="CornerRadius" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=CornerRadius, Converter={x:Static c:CornerRadiusTakeConverter.Bottom}}" />
|
||||
<Setter Property="BorderThickness" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderThickness, Converter={x:Static c:ThicknessTakeConverter.Bottom}}" />
|
||||
</Style>
|
||||
<Style Selector="^[Position=Bottom] /template/ Border#PART_Root">
|
||||
<Setter Property="Margin" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Padding, Converter={x:Static c:ThicknessTakeConverter.Top}}" />
|
||||
<Setter Property="CornerRadius" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=CornerRadius, Converter={x:Static c:CornerRadiusTakeConverter.Top}}" />
|
||||
<Setter Property="BorderThickness" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderThickness, Converter={x:Static c:ThicknessTakeConverter.Top}}" />
|
||||
</Style>
|
||||
<Style Selector="^[Position=Top] /template/ u|DialogResizer">
|
||||
<Setter Property="Margin" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Padding, Converter={x:Static c:ThicknessTakeConverter.Bottom}}" />
|
||||
<Setter Property="ResizeDirection" Value="Bottom"/>
|
||||
</Style>
|
||||
<Style Selector="^[Position=Bottom] /template/ u|DialogResizer">
|
||||
<Setter Property="Margin" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Padding, Converter={x:Static c:ThicknessTakeConverter.Top}}" />
|
||||
<Setter Property="ResizeDirection" Value="Top"/>
|
||||
</Style>
|
||||
<Style Selector="^[Position=Left] /template/ u|DialogResizer">
|
||||
<Setter Property="Margin" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Padding, Converter={x:Static c:ThicknessTakeConverter.Right}}" />
|
||||
<Setter Property="ResizeDirection" Value="Right"/>
|
||||
</Style>
|
||||
<Style Selector="^[Position=Right] /template/ u|DialogResizer">
|
||||
<Setter Property="Margin" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Padding, Converter={x:Static c:ThicknessTakeConverter.Left}}" />
|
||||
<Setter Property="ResizeDirection" Value="Left"/>
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
|
||||
@@ -1,29 +1,144 @@
|
||||
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:u="https://irihi.tech/ursa"
|
||||
xmlns:iri="https://irihi.tech/shared">
|
||||
<!-- Add Resources Here -->
|
||||
<ControlTheme TargetType="u:WindowResizerThumb" x:Key="{x:Type u:WindowResizerThumb}">
|
||||
<ResourceDictionary
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:iri="https://irihi.tech/shared"
|
||||
xmlns:u="https://irihi.tech/ursa">
|
||||
<!-- Add Resources Here -->
|
||||
<ControlTheme x:Key="{x:Type u:WindowResizerThumb}" TargetType="u:WindowResizerThumb">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:WindowResizerThumb">
|
||||
<iri:PureRectangle HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="{TemplateBinding Background}"/>
|
||||
<iri:PureRectangle
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Background="{TemplateBinding Background}" />
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme TargetType="u:WindowResizer" x:Key="{x:Type u:WindowResizer}">
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:DialogResizerThumb}" TargetType="u:DialogResizerThumb">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:DialogResizerThumb">
|
||||
<Panel>
|
||||
<iri:PureRectangle
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Background="{TemplateBinding Background}" />
|
||||
</Panel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:DialogResizer}" TargetType="u:DialogResizer">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:WindowResizer">
|
||||
<Grid RowDefinitions="Auto, *, Auto" ColumnDefinitions="Auto, *, Auto" >
|
||||
<u:WindowResizerThumb Grid.Row="0" Grid.Column="0" ResizeDirection="TopLeft" Cursor="TopLeftCorner" />
|
||||
<u:WindowResizerThumb Grid.Row="0" Grid.Column="1" ResizeDirection="Top" Cursor="TopSide" Height="{DynamicResource ResizerThumbHeight}" />
|
||||
<u:WindowResizerThumb Grid.Row="0" Grid.Column="2" ResizeDirection="TopRight" Cursor="TopRightCorner" />
|
||||
<u:WindowResizerThumb Grid.Row="1" Grid.Column="0" ResizeDirection="Left" Cursor="LeftSide" Width="{DynamicResource ResizerThumbWidth}" />
|
||||
<u:WindowResizerThumb Grid.Row="1" Grid.Column="2" ResizeDirection="Right" Cursor="RightSide" Width="{DynamicResource ResizerThumbWidth}" />
|
||||
<u:WindowResizerThumb Grid.Row="2" Grid.Column="0" ResizeDirection="BottomLeft" Cursor="BottomLeftCorner" />
|
||||
<u:WindowResizerThumb Grid.Row="2" Grid.Column="1" ResizeDirection="Bottom" Cursor="BottomSide" Height="{DynamicResource ResizerThumbHeight}" />
|
||||
<u:WindowResizerThumb Grid.Row="2" Grid.Column="2" ResizeDirection="BottomRight" Cursor="BottomRightCorner" />
|
||||
<Grid ColumnDefinitions="Auto, *, Auto" RowDefinitions="Auto, *, Auto">
|
||||
<u:DialogResizerThumb
|
||||
Name="{x:Static u:DialogResizer.PART_TopLeft}"
|
||||
Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
Cursor="TopLeftCorner"
|
||||
ResizeDirection="TopLeft" />
|
||||
<u:DialogResizerThumb
|
||||
Name="{x:Static u:DialogResizer.PART_Top}"
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Height="{DynamicResource ResizerThumbHeight}"
|
||||
Cursor="TopSide"
|
||||
ResizeDirection="Top" />
|
||||
<u:DialogResizerThumb
|
||||
Name="{x:Static u:DialogResizer.PART_TopRight}"
|
||||
Grid.Row="0"
|
||||
Grid.Column="2"
|
||||
Cursor="TopRightCorner"
|
||||
ResizeDirection="TopRight" />
|
||||
<u:DialogResizerThumb
|
||||
Name="{x:Static u:DialogResizer.PART_Left}"
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Width="{DynamicResource ResizerThumbWidth}"
|
||||
Cursor="LeftSide"
|
||||
ResizeDirection="Left" />
|
||||
<u:DialogResizerThumb
|
||||
Name="{x:Static u:DialogResizer.PART_Right}"
|
||||
Grid.Row="1"
|
||||
Grid.Column="2"
|
||||
Width="{DynamicResource ResizerThumbWidth}"
|
||||
Cursor="RightSide"
|
||||
ResizeDirection="Right" />
|
||||
<u:DialogResizerThumb
|
||||
Name="{x:Static u:DialogResizer.PART_BottomLeft}"
|
||||
Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
Cursor="BottomLeftCorner"
|
||||
ResizeDirection="BottomLeft" />
|
||||
<u:DialogResizerThumb
|
||||
Name="{x:Static u:DialogResizer.PART_Bottom}"
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Height="{DynamicResource ResizerThumbHeight}"
|
||||
Cursor="BottomSide"
|
||||
ResizeDirection="Bottom" />
|
||||
<u:DialogResizerThumb
|
||||
Name="{x:Static u:DialogResizer.PART_BottomRight}"
|
||||
Grid.Row="2"
|
||||
Grid.Column="2"
|
||||
Cursor="BottomRightCorner"
|
||||
ResizeDirection="BottomRight" />
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:WindowResizer}" TargetType="u:WindowResizer">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:WindowResizer">
|
||||
<Grid ColumnDefinitions="Auto, *, Auto" RowDefinitions="Auto, *, Auto">
|
||||
<u:WindowResizerThumb
|
||||
Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
Cursor="TopLeftCorner"
|
||||
ResizeDirection="TopLeft" />
|
||||
<u:WindowResizerThumb
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Height="{DynamicResource ResizerThumbHeight}"
|
||||
Cursor="TopSide"
|
||||
ResizeDirection="Top" />
|
||||
<u:WindowResizerThumb
|
||||
Grid.Row="0"
|
||||
Grid.Column="2"
|
||||
Cursor="TopRightCorner"
|
||||
ResizeDirection="TopRight" />
|
||||
<u:WindowResizerThumb
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Width="{DynamicResource ResizerThumbWidth}"
|
||||
Cursor="LeftSide"
|
||||
ResizeDirection="Left" />
|
||||
<u:WindowResizerThumb
|
||||
Grid.Row="1"
|
||||
Grid.Column="2"
|
||||
Width="{DynamicResource ResizerThumbWidth}"
|
||||
Cursor="RightSide"
|
||||
ResizeDirection="Right" />
|
||||
<u:WindowResizerThumb
|
||||
Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
Cursor="BottomLeftCorner"
|
||||
ResizeDirection="BottomLeft" />
|
||||
<u:WindowResizerThumb
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Height="{DynamicResource ResizerThumbHeight}"
|
||||
Cursor="BottomSide"
|
||||
ResizeDirection="Bottom" />
|
||||
<u:WindowResizerThumb
|
||||
Grid.Row="2"
|
||||
Grid.Column="2"
|
||||
Cursor="BottomRightCorner"
|
||||
ResizeDirection="BottomRight" />
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
||||
@@ -6,4 +6,6 @@
|
||||
<StreamGeometry x:Key="DialogArrangeSendBackwardGlyph">M2,2H16V16H2V2M22,8V22H8V18H18V8H22M4,4V14H14V4H4Z</StreamGeometry>
|
||||
<StreamGeometry x:Key="DialogArrangeSendToBackGlyph">M2,2H11V11H2V2M9,4H4V9H9V4M22,13V22H13V13H22M15,20H20V15H15V20M16,8V11H13V8H16M11,16H8V13H11V16Z</StreamGeometry>
|
||||
<CornerRadius x:Key="DialogCornerRadius">12</CornerRadius>
|
||||
<x:Double x:Key="DialogMinWidth">48</x:Double>
|
||||
<x:Double x:Key="DialogMinHeight">48</x:Double>
|
||||
</ResourceDictionary>
|
||||
|
||||
@@ -205,6 +205,8 @@ public static class Dialog
|
||||
window.IsCloseButtonVisible = options.IsCloseButtonVisible;
|
||||
window.ShowInTaskbar = options.ShowInTaskBar;
|
||||
window.CanDragMove = options.CanDragMove;
|
||||
window.CanResize = options.CanResize;
|
||||
window.IsManagedResizerVisible = options.CanResize;
|
||||
if (options.StartupLocation == WindowStartupLocation.Manual)
|
||||
{
|
||||
if (options.Position is not null)
|
||||
@@ -229,6 +231,8 @@ public static class Dialog
|
||||
window.ShowInTaskbar = options.ShowInTaskBar;
|
||||
window.IsCloseButtonVisible = options.IsCloseButtonVisible;
|
||||
window.CanDragMove = options.CanDragMove;
|
||||
window.IsManagedResizerVisible = options.CanResize;
|
||||
window.CanResize = options.CanResize;
|
||||
if (options.StartupLocation == WindowStartupLocation.Manual)
|
||||
{
|
||||
if (options.Position is not null)
|
||||
|
||||
@@ -24,10 +24,16 @@ public abstract class DialogControlBase : OverlayFeedbackElement
|
||||
AvaloniaProperty.RegisterDirect<DialogControlBase, bool>(
|
||||
nameof(IsFullScreen), o => o.IsFullScreen, (o, v) => o.IsFullScreen = v);
|
||||
|
||||
public static readonly StyledProperty<bool> CanResizeProperty = AvaloniaProperty.Register<DialogControlBase, bool>(
|
||||
nameof(CanResize));
|
||||
|
||||
protected internal Button? _closeButton;
|
||||
|
||||
private bool _isFullScreen;
|
||||
private Panel? _titleArea;
|
||||
private bool _moveDragging;
|
||||
private Point _moveDragStartPoint;
|
||||
|
||||
|
||||
static DialogControlBase()
|
||||
{
|
||||
@@ -36,6 +42,12 @@ public abstract class DialogControlBase : OverlayFeedbackElement
|
||||
IsFullScreenProperty.AffectsPseudoClass<DialogControlBase>(PC_FullScreen);
|
||||
}
|
||||
|
||||
public bool CanResize
|
||||
{
|
||||
get => GetValue(CanResizeProperty);
|
||||
set => SetValue(CanResizeProperty, value);
|
||||
}
|
||||
|
||||
internal HorizontalPosition HorizontalAnchor { get; set; } = HorizontalPosition.Center;
|
||||
internal VerticalPosition VerticalAnchor { get; set; } = VerticalPosition.Center;
|
||||
internal HorizontalPosition ActualHorizontalAnchor { get; set; }
|
||||
@@ -79,17 +91,44 @@ public abstract class DialogControlBase : OverlayFeedbackElement
|
||||
|
||||
private void OnTitlePointerPressed(InputElement sender, PointerPressedEventArgs e)
|
||||
{
|
||||
e.Source = this;
|
||||
//e.Source = this;
|
||||
if (ContainerPanel is OverlayDialogHost h)
|
||||
{
|
||||
if (h.IsTopLevel && this.IsFullScreen)
|
||||
{
|
||||
var top = TopLevel.GetTopLevel(this);
|
||||
if (top is Window w)
|
||||
{
|
||||
w.BeginMoveDrag(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!e.GetCurrentPoint(this).Properties.IsLeftButtonPressed) return;
|
||||
if (IsFullScreen) return;
|
||||
_moveDragging = true;
|
||||
_moveDragStartPoint = e.GetPosition(this);
|
||||
}
|
||||
|
||||
private void OnTitlePointerMove(InputElement sender, PointerEventArgs e)
|
||||
{
|
||||
e.Source = this;
|
||||
//e.Source = this;
|
||||
if (!_moveDragging) return;
|
||||
if (ContainerPanel is null) return;
|
||||
var p = e.GetPosition(this);
|
||||
var left = Canvas.GetLeft(this) + p.X - _moveDragStartPoint.X;
|
||||
var top = Canvas.GetTop(this) + p.Y - _moveDragStartPoint.Y;
|
||||
left = MathHelpers.SafeClamp(left, 0, ContainerPanel.Bounds.Width - Bounds.Width);
|
||||
top = MathHelpers.SafeClamp(top, 0, ContainerPanel.Bounds.Height - Bounds.Height);
|
||||
Canvas.SetLeft(this, left);
|
||||
Canvas.SetTop(this, top);
|
||||
}
|
||||
|
||||
private void OnTitlePointerRelease(InputElement sender, PointerReleasedEventArgs e)
|
||||
{
|
||||
e.Source = this;
|
||||
// e.Source = this;
|
||||
_moveDragging = false;
|
||||
AnchorAndUpdatePositionInfo();
|
||||
}
|
||||
|
||||
private void OnCloseButtonClick(object? sender, RoutedEventArgs args)
|
||||
@@ -195,4 +234,50 @@ public abstract class DialogControlBase : OverlayFeedbackElement
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
protected internal override void AnchorAndUpdatePositionInfo()
|
||||
{
|
||||
if (ContainerPanel is null) return;
|
||||
ActualHorizontalAnchor = HorizontalPosition.Center;
|
||||
ActualVerticalAnchor = VerticalPosition.Center;
|
||||
double left = Canvas.GetLeft(this);
|
||||
double top = Canvas.GetTop(this);
|
||||
double right = ContainerPanel.Bounds.Width - left - Bounds.Width;
|
||||
double bottom = ContainerPanel.Bounds.Height - top - Bounds.Height;
|
||||
if (ContainerPanel is OverlayDialogHost h)
|
||||
{
|
||||
var snapThickness = h.SnapThickness;
|
||||
if(top < snapThickness.Top)
|
||||
{
|
||||
Canvas.SetTop(this, 0);
|
||||
ActualVerticalAnchor = VerticalPosition.Top;
|
||||
VerticalOffsetRatio = 0;
|
||||
}
|
||||
if(bottom < snapThickness.Bottom)
|
||||
{
|
||||
Canvas.SetTop(this, ContainerPanel.Bounds.Height - Bounds.Height);
|
||||
ActualVerticalAnchor = VerticalPosition.Bottom;
|
||||
VerticalOffsetRatio = 1;
|
||||
}
|
||||
if(left < snapThickness.Left)
|
||||
{
|
||||
Canvas.SetLeft(this, 0);
|
||||
ActualHorizontalAnchor = HorizontalPosition.Left;
|
||||
HorizontalOffsetRatio = 0;
|
||||
}
|
||||
if(right < snapThickness.Right)
|
||||
{
|
||||
Canvas.SetLeft(this, ContainerPanel.Bounds.Width - this.Bounds.Width);
|
||||
ActualHorizontalAnchor = HorizontalPosition.Right;
|
||||
HorizontalOffsetRatio = 1;
|
||||
}
|
||||
}
|
||||
left = Canvas.GetLeft(this);
|
||||
top = Canvas.GetTop(this);
|
||||
right = ContainerPanel.Bounds.Width - left - Bounds.Width;
|
||||
bottom = ContainerPanel.Bounds.Height - top - Bounds.Height;
|
||||
|
||||
HorizontalOffsetRatio = (left + right) == 0 ? 0 : left / (left + right);
|
||||
VerticalOffsetRatio = (top + bottom) == 0 ? 0 : top / (top + bottom);
|
||||
}
|
||||
}
|
||||
@@ -17,8 +17,17 @@ public class DialogWindow : Window
|
||||
public const string PART_TitleArea = "PART_TitleArea";
|
||||
|
||||
protected internal Button? _closeButton;
|
||||
|
||||
private Panel? _titleArea;
|
||||
public bool CanDragMove { get; set; } = true;
|
||||
|
||||
public static readonly StyledProperty<bool> IsManagedResizerVisibleProperty = AvaloniaProperty.Register<DialogWindow, bool>(
|
||||
nameof(IsManagedResizerVisible));
|
||||
|
||||
public bool IsManagedResizerVisible
|
||||
{
|
||||
get => GetValue(IsManagedResizerVisibleProperty);
|
||||
set => SetValue(IsManagedResizerVisibleProperty, value);
|
||||
}
|
||||
|
||||
static DialogWindow()
|
||||
{
|
||||
@@ -26,9 +35,11 @@ public class DialogWindow : Window
|
||||
window.OnDataContextChange(e));
|
||||
}
|
||||
|
||||
public bool CanDragMove { get; set; } = true;
|
||||
internal bool? IsCloseButtonVisible { get; set; }
|
||||
|
||||
protected override Type StyleKeyOverride { get; } = typeof(DialogWindow);
|
||||
|
||||
internal bool? IsCloseButtonVisible { get; set; }
|
||||
|
||||
private void OnDataContextChange(AvaloniaPropertyChangedEventArgs<object?> args)
|
||||
{
|
||||
|
||||
@@ -30,4 +30,6 @@ public class DialogOptions
|
||||
public bool ShowInTaskBar { get; set; } = true;
|
||||
|
||||
public bool CanDragMove { get; set; } = true;
|
||||
|
||||
public bool CanResize { get; set; }
|
||||
}
|
||||
@@ -62,4 +62,6 @@ public class OverlayDialogOptions
|
||||
/// id.
|
||||
/// </summary>
|
||||
public int? TopLevelHashCode { get; set; }
|
||||
|
||||
public bool CanResize { get; set; }
|
||||
}
|
||||
@@ -204,6 +204,7 @@ public static class OverlayDialog
|
||||
options.VerticalAnchor == VerticalPosition.Center ? null : options.VerticalOffset;
|
||||
control.IsCloseButtonVisible = options.IsCloseButtonVisible;
|
||||
control.CanLightDismiss = options.CanLightDismiss;
|
||||
control.CanResize = options.CanResize;
|
||||
DialogControlBase.SetCanDragMove(control, options.CanDragMove);
|
||||
}
|
||||
|
||||
@@ -229,6 +230,7 @@ public static class OverlayDialog
|
||||
control.Title = options.Title;
|
||||
control.CanLightDismiss = options.CanLightDismiss;
|
||||
control.IsCloseButtonVisible = options.IsCloseButtonVisible;
|
||||
control.CanResize = options.CanResize;
|
||||
DialogControlBase.SetCanDragMove(control, options.CanDragMove);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,4 +25,9 @@ public class CustomDrawerControl: DrawerControlBase
|
||||
OnElementClosing(this, null);
|
||||
}
|
||||
}
|
||||
|
||||
protected internal override void AnchorAndUpdatePositionInfo()
|
||||
{
|
||||
// throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -135,4 +135,9 @@ public class DefaultDrawerControl : DrawerControlBase
|
||||
RaiseEvent(new ResultEventArgs(ClosedEvent, result));
|
||||
}
|
||||
}
|
||||
|
||||
protected internal override void AnchorAndUpdatePositionInfo()
|
||||
{
|
||||
// throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -205,16 +205,17 @@ public static class Drawer
|
||||
drawer.Position = options.Position;
|
||||
drawer.IsCloseButtonVisible = options.IsCloseButtonVisible;
|
||||
drawer.CanLightDismiss = options.CanLightDismiss;
|
||||
drawer.CanResize = options.CanResize;
|
||||
if (options.Position == Position.Left || options.Position == Position.Right)
|
||||
{
|
||||
drawer.MinWidth = options.MinWidth ?? 0.0;
|
||||
drawer.MaxWidth = options.MaxWidth ?? double.PositiveInfinity;
|
||||
if(options.MinWidth is not null) drawer.MinWidth = options.MinWidth.Value;
|
||||
if(options.MaxWidth is not null) drawer.MaxWidth = options.MaxWidth.Value;
|
||||
}
|
||||
|
||||
if (options.Position is Position.Top or Position.Bottom)
|
||||
{
|
||||
drawer.MinHeight = options.MinHeight ?? 0.0;
|
||||
drawer.MaxHeight = options.MaxHeight ?? double.PositiveInfinity;
|
||||
if(options.MinHeight is not null) drawer.MinHeight = options.MinHeight.Value;
|
||||
if(options.MaxHeight is not null) drawer.MaxHeight = options.MaxHeight.Value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,16 +227,17 @@ public static class Drawer
|
||||
drawer.CanLightDismiss = options.CanLightDismiss;
|
||||
drawer.Buttons = options.Buttons;
|
||||
drawer.Title = options.Title;
|
||||
drawer.CanResize = options.CanResize;
|
||||
if (options.Position == Position.Left || options.Position == Position.Right)
|
||||
{
|
||||
drawer.MinWidth = options.MinWidth ?? 0.0;
|
||||
drawer.MaxWidth = options.MaxWidth ?? double.PositiveInfinity;
|
||||
if(options.MinWidth is not null) drawer.MinWidth = options.MinWidth.Value;
|
||||
if(options.MaxWidth is not null) drawer.MaxWidth = options.MaxWidth.Value;
|
||||
}
|
||||
|
||||
if (options.Position is Position.Top or Position.Bottom)
|
||||
{
|
||||
drawer.MinHeight = options.MinHeight ?? 0.0;
|
||||
drawer.MaxHeight = options.MaxHeight ?? double.PositiveInfinity;
|
||||
if(options.MinHeight is not null) drawer.MinHeight = options.MinHeight.Value;
|
||||
if(options.MaxHeight is not null) drawer.MaxHeight = options.MaxHeight.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,15 @@ public abstract class DrawerControlBase: OverlayFeedbackElement
|
||||
AvaloniaProperty.Register<DrawerControlBase, Position>(
|
||||
nameof(Position), defaultValue: Position.Right);
|
||||
|
||||
public static readonly StyledProperty<bool> CanResizeProperty = AvaloniaProperty.Register<DrawerControlBase, bool>(
|
||||
nameof(CanResize));
|
||||
|
||||
public bool CanResize
|
||||
{
|
||||
get => GetValue(CanResizeProperty);
|
||||
set => SetValue(CanResizeProperty, value);
|
||||
}
|
||||
|
||||
public Position Position
|
||||
{
|
||||
get => GetValue(PositionProperty);
|
||||
|
||||
@@ -20,4 +20,6 @@ public class DrawerOptions
|
||||
/// The hash code of the top level dialog host. This is used to identify the dialog host if there are multiple dialog hosts with the same id. If this is not provided, the dialog will be added to the first dialog host with the same id.
|
||||
/// </summary>
|
||||
public int? TopLevelHashCode { get; set; }
|
||||
|
||||
public bool CanResize { get; set; }
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.VisualTree;
|
||||
using Irihi.Avalonia.Shared.Helpers;
|
||||
@@ -10,10 +9,8 @@ namespace Ursa.Controls;
|
||||
|
||||
public partial class OverlayDialogHost
|
||||
{
|
||||
private Point _lastPoint;
|
||||
|
||||
public Thickness SnapThickness { get; set; } = new Thickness(0);
|
||||
|
||||
public Thickness SnapThickness { get; set; } = new(0);
|
||||
|
||||
private static void ResetDialogPosition(DialogControlBase control, Size newSize)
|
||||
{
|
||||
control.MaxWidth = newSize.Width;
|
||||
@@ -26,138 +23,71 @@ public partial class OverlayDialogHost
|
||||
SetTop(control, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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 OnPointerMoved(PointerEventArgs e)
|
||||
{
|
||||
if (e.Source is DialogControlBase item)
|
||||
{
|
||||
if (item.IsFullScreen) return;
|
||||
if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
|
||||
{
|
||||
var p = e.GetPosition(this);
|
||||
var left = p.X - _lastPoint.X;
|
||||
var top = p.Y - _lastPoint.Y;
|
||||
left = MathHelpers.SafeClamp(left, 0, Bounds.Width - item.Bounds.Width);
|
||||
top = MathHelpers.SafeClamp(top, 0, Bounds.Height - item.Bounds.Height);
|
||||
SetLeft(item, left);
|
||||
SetTop(item, top);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPointerPressed(PointerPressedEventArgs e)
|
||||
{
|
||||
if (e.Source is DialogControlBase item)
|
||||
{
|
||||
if (IsTopLevel && item.IsFullScreen)
|
||||
{
|
||||
var top = TopLevel.GetTopLevel(item);
|
||||
if (top is Window w)
|
||||
{
|
||||
w.BeginMoveDrag(e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_lastPoint = e.GetPosition(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPointerReleased(PointerReleasedEventArgs e)
|
||||
{
|
||||
if (e.Source is DialogControlBase item)
|
||||
{
|
||||
AnchorAndUpdatePositionInfo(item);
|
||||
}
|
||||
}
|
||||
|
||||
internal void AddDialog(DialogControlBase control)
|
||||
{
|
||||
PureRectangle? mask = null;
|
||||
if (control.CanLightDismiss)
|
||||
{
|
||||
mask = CreateOverlayMask(false, control.CanLightDismiss);
|
||||
}
|
||||
if (mask is not null)
|
||||
{
|
||||
Children.Add(mask);
|
||||
}
|
||||
this.Children.Add(control);
|
||||
if (control.CanLightDismiss) mask = CreateOverlayMask(false, control.CanLightDismiss);
|
||||
if (mask is not null) Children.Add(mask);
|
||||
Children.Add(control);
|
||||
_layers.Add(new DialogPair(mask, control, false));
|
||||
if (control.IsFullScreen)
|
||||
{
|
||||
control.Width = Bounds.Width;
|
||||
control.Height = Bounds.Height;
|
||||
}
|
||||
|
||||
control.MaxWidth = Bounds.Width;
|
||||
control.MaxHeight = Bounds.Height;
|
||||
control.Measure(this.Bounds.Size);
|
||||
control.Measure(Bounds.Size);
|
||||
control.Arrange(new Rect(control.DesiredSize));
|
||||
SetToPosition(control);
|
||||
control.AddHandler(OverlayFeedbackElement.ClosedEvent, OnDialogControlClosing);
|
||||
control.AddHandler(DialogControlBase.LayerChangedEvent, OnDialogLayerChanged);
|
||||
ResetZIndices();
|
||||
}
|
||||
|
||||
|
||||
private async void OnDialogControlClosing(object? sender, object? e)
|
||||
{
|
||||
if (sender is DialogControlBase control)
|
||||
if (sender is not DialogControlBase control) return;
|
||||
var layer = _layers.FirstOrDefault(a => a.Element == control);
|
||||
if (layer is null) return;
|
||||
_layers.Remove(layer);
|
||||
|
||||
control.RemoveHandler(OverlayFeedbackElement.ClosedEvent, OnDialogControlClosing);
|
||||
control.RemoveHandler(DialogControlBase.LayerChangedEvent, OnDialogLayerChanged);
|
||||
layer.Mask?.RemoveHandler(PointerPressedEvent, DragMaskToMoveWindow);
|
||||
|
||||
Children.Remove(control);
|
||||
|
||||
if (layer.Mask is not null)
|
||||
{
|
||||
var layer = _layers.FirstOrDefault(a => a.Element == control);
|
||||
if (layer is null) return;
|
||||
_layers.Remove(layer);
|
||||
|
||||
control.RemoveHandler(OverlayFeedbackElement.ClosedEvent, OnDialogControlClosing);
|
||||
control.RemoveHandler(DialogControlBase.LayerChangedEvent, OnDialogLayerChanged);
|
||||
control.RemoveHandler(PointerPressedEvent, DragMaskToMoveWindow);
|
||||
|
||||
Children.Remove(control);
|
||||
|
||||
if (layer.Mask is not null)
|
||||
Children.Remove(layer.Mask);
|
||||
if (layer.Modal)
|
||||
{
|
||||
Children.Remove(layer.Mask);
|
||||
|
||||
if (layer.Modal)
|
||||
{
|
||||
_modalCount--;
|
||||
IsInModalStatus = _modalCount > 0;
|
||||
if (!IsAnimationDisabled)
|
||||
{
|
||||
await _maskDisappearAnimation.RunAsync(layer.Mask);
|
||||
}
|
||||
}
|
||||
_modalCount--;
|
||||
IsInModalStatus = _modalCount > 0;
|
||||
if (!IsAnimationDisabled) await MaskDisappearAnimation.RunAsync(layer.Mask);
|
||||
}
|
||||
|
||||
ResetZIndices();
|
||||
}
|
||||
|
||||
ResetZIndices();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a dialog as a modal dialog to the host
|
||||
/// Add a dialog as a modal dialog to the host
|
||||
/// </summary>
|
||||
/// <param name="control"></param>
|
||||
internal void AddModalDialog(DialogControlBase control)
|
||||
@@ -166,24 +96,22 @@ public partial class OverlayDialogHost
|
||||
_layers.Add(new DialogPair(mask, control));
|
||||
control.SetAsModal(true);
|
||||
ResetZIndices();
|
||||
this.Children.Add(mask);
|
||||
this.Children.Add(control);
|
||||
Children.Add(mask);
|
||||
Children.Add(control);
|
||||
if (control.IsFullScreen)
|
||||
{
|
||||
control.Width = Bounds.Width;
|
||||
control.Height = Bounds.Height;
|
||||
}
|
||||
|
||||
control.MaxWidth = Bounds.Width;
|
||||
control.MaxHeight = Bounds.Height;
|
||||
control.Measure(this.Bounds.Size);
|
||||
control.Measure(Bounds.Size);
|
||||
control.Arrange(new Rect(control.DesiredSize));
|
||||
SetToPosition(control);
|
||||
control.AddHandler(OverlayFeedbackElement.ClosedEvent, OnDialogControlClosing);
|
||||
control.AddHandler(DialogControlBase.LayerChangedEvent, OnDialogLayerChanged);
|
||||
if (!IsAnimationDisabled)
|
||||
{
|
||||
_maskAppearAnimation.RunAsync(mask);
|
||||
}
|
||||
if (!IsAnimationDisabled) MaskAppearAnimation.RunAsync(mask);
|
||||
|
||||
var element = control.GetVisualDescendants().OfType<InputElement>().FirstOrDefault(a => a.Focusable);
|
||||
element?.Focus();
|
||||
@@ -200,9 +128,9 @@ public partial class OverlayDialogHost
|
||||
return;
|
||||
var layer = _layers.FirstOrDefault(a => a.Element == control);
|
||||
if (layer is null) return;
|
||||
int index = _layers.IndexOf(layer);
|
||||
var index = _layers.IndexOf(layer);
|
||||
_layers.Remove(layer);
|
||||
int newIndex = index;
|
||||
var newIndex = index;
|
||||
switch (e.ChangeType)
|
||||
{
|
||||
case DialogLayerChangeType.BringForward:
|
||||
@@ -222,63 +150,21 @@ public partial class OverlayDialogHost
|
||||
_layers.Insert(newIndex, layer);
|
||||
ResetZIndices();
|
||||
}
|
||||
|
||||
|
||||
private void SetToPosition(DialogControlBase? control)
|
||||
{
|
||||
if (control is null) return;
|
||||
double left = GetLeftPosition(control);
|
||||
double top = GetTopPosition(control);
|
||||
var left = GetLeftPosition(control);
|
||||
var top = GetTopPosition(control);
|
||||
SetLeft(control, left);
|
||||
SetTop(control, top);
|
||||
AnchorAndUpdatePositionInfo(control);
|
||||
}
|
||||
|
||||
private void AnchorAndUpdatePositionInfo(DialogControlBase 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 < 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 < 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 + right) == 0 ? 0 : left / (left + right);
|
||||
control.VerticalOffsetRatio = (top + bottom) == 0 ? 0 : top / (top + bottom);
|
||||
control.AnchorAndUpdatePositionInfo();
|
||||
}
|
||||
|
||||
private double GetLeftPosition(DialogControlBase control)
|
||||
{
|
||||
double left;
|
||||
double offset = Math.Max(0, control.HorizontalOffset ?? 0);
|
||||
left = this.Bounds.Width - control.Bounds.Width;
|
||||
var offset = Math.Max(0, control.HorizontalOffset ?? 0);
|
||||
var left = Bounds.Width - control.Bounds.Width;
|
||||
if (control.HorizontalAnchor == HorizontalPosition.Center)
|
||||
{
|
||||
left *= 0.5;
|
||||
@@ -290,20 +176,18 @@ public partial class OverlayDialogHost
|
||||
}
|
||||
else if (control.HorizontalAnchor == HorizontalPosition.Right)
|
||||
{
|
||||
double leftOffset = Bounds.Width - control.Bounds.Width - offset;
|
||||
var leftOffset = Bounds.Width - control.Bounds.Width - offset;
|
||||
leftOffset = Math.Max(0, leftOffset);
|
||||
if(control.HorizontalOffset.HasValue)
|
||||
{
|
||||
left = MathHelpers.SafeClamp(left, 0, leftOffset);
|
||||
}
|
||||
if (control.HorizontalOffset.HasValue) left = MathHelpers.SafeClamp(left, 0, leftOffset);
|
||||
}
|
||||
|
||||
return left;
|
||||
}
|
||||
}
|
||||
|
||||
private double GetTopPosition(DialogControlBase control)
|
||||
{
|
||||
double offset = Math.Max(0, control.VerticalOffset ?? 0);
|
||||
var top = this.Bounds.Height - control.Bounds.Height;
|
||||
var offset = Math.Max(0, control.VerticalOffset ?? 0);
|
||||
var top = Bounds.Height - control.Bounds.Height;
|
||||
if (control.VerticalAnchor == VerticalPosition.Center)
|
||||
{
|
||||
top *= 0.5;
|
||||
@@ -318,8 +202,7 @@ public partial class OverlayDialogHost
|
||||
var topOffset = Math.Max(0, Bounds.Height - control.Bounds.Height - offset);
|
||||
top = MathHelpers.SafeClamp(top, 0, topOffset);
|
||||
}
|
||||
|
||||
return top;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -42,7 +42,7 @@ public partial class OverlayDialogHost
|
||||
}
|
||||
else
|
||||
{
|
||||
await Task.WhenAll(animation.RunAsync(control), _maskAppearAnimation.RunAsync(mask));
|
||||
await Task.WhenAll(animation.RunAsync(control), MaskAppearAnimation.RunAsync(mask));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -67,7 +67,7 @@ public partial class OverlayDialogHost
|
||||
}
|
||||
else
|
||||
{
|
||||
await Task.WhenAll(animation.RunAsync(control), _maskAppearAnimation.RunAsync(mask));
|
||||
await Task.WhenAll(animation.RunAsync(control), MaskAppearAnimation.RunAsync(mask));
|
||||
}
|
||||
var element = control.GetVisualDescendants().OfType<InputElement>().FirstOrDefault(a => a.Focusable);
|
||||
element?.Focus();
|
||||
@@ -174,7 +174,7 @@ public partial class OverlayDialogHost
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -14,8 +14,8 @@ namespace Ursa.Controls;
|
||||
|
||||
public partial class OverlayDialogHost: Canvas
|
||||
{
|
||||
private static readonly Animation _maskAppearAnimation;
|
||||
private static readonly Animation _maskDisappearAnimation;
|
||||
private static readonly Animation MaskAppearAnimation;
|
||||
private static readonly Animation MaskDisappearAnimation;
|
||||
|
||||
private readonly List<DialogPair> _layers = new List<DialogPair>(10);
|
||||
|
||||
@@ -61,8 +61,8 @@ public partial class OverlayDialogHost: Canvas
|
||||
static OverlayDialogHost()
|
||||
{
|
||||
ClipToBoundsProperty.OverrideDefaultValue<OverlayDialogHost>(true);
|
||||
_maskAppearAnimation = CreateOpacityAnimation(true);
|
||||
_maskDisappearAnimation = CreateOpacityAnimation(false);
|
||||
MaskAppearAnimation = CreateOpacityAnimation(true);
|
||||
MaskDisappearAnimation = CreateOpacityAnimation(false);
|
||||
}
|
||||
|
||||
private static Animation CreateOpacityAnimation(bool appear)
|
||||
@@ -128,28 +128,21 @@ public partial class OverlayDialogHost: Canvas
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (sender is PureRectangle mask)
|
||||
if (sender is not PureRectangle mask) return;
|
||||
if(TopLevel.GetTopLevel(mask) is Window window)
|
||||
{
|
||||
var window = this.GetVisualAncestors().OfType<Window>().FirstOrDefault();
|
||||
if(window is not null)
|
||||
{
|
||||
window.BeginMoveDrag(e);
|
||||
}
|
||||
window.BeginMoveDrag(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void ClickMaskToCloseDialog(object? sender, PointerReleasedEventArgs e)
|
||||
{
|
||||
if (sender is PureRectangle border)
|
||||
{
|
||||
var layer = _layers.FirstOrDefault(a => a.Mask == border);
|
||||
if (layer is not null)
|
||||
{
|
||||
layer.Element.Close();
|
||||
border.RemoveHandler(PointerReleasedEvent, ClickMaskToCloseDialog);
|
||||
border.RemoveHandler(PointerPressedEvent, DragMaskToMoveWindow);
|
||||
}
|
||||
}
|
||||
if (sender is not PureRectangle border) return;
|
||||
var layer = _layers.FirstOrDefault(a => a.Mask == border);
|
||||
if (layer is null) return;
|
||||
border.RemoveHandler(PointerReleasedEvent, ClickMaskToCloseDialog);
|
||||
border.RemoveHandler(PointerPressedEvent, DragMaskToMoveWindow);
|
||||
layer.Element.Close();
|
||||
}
|
||||
private IDisposable? _modalStatusSubscription;
|
||||
private int? _toplevelHash;
|
||||
|
||||
@@ -1,90 +1,201 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Threading;
|
||||
using Avalonia.VisualTree;
|
||||
using Irihi.Avalonia.Shared.Contracts;
|
||||
using Irihi.Avalonia.Shared.Helpers;
|
||||
using Ursa.EventArgs;
|
||||
|
||||
namespace Ursa.Controls.OverlayShared;
|
||||
|
||||
public abstract class OverlayFeedbackElement: ContentControl
|
||||
public abstract class OverlayFeedbackElement : ContentControl
|
||||
{
|
||||
public static readonly StyledProperty<bool> IsClosedProperty =
|
||||
AvaloniaProperty.Register<OverlayFeedbackElement, bool>(nameof(IsClosed), defaultValue: true);
|
||||
AvaloniaProperty.Register<OverlayFeedbackElement, bool>(nameof(IsClosed), true);
|
||||
|
||||
public static readonly RoutedEvent<ResultEventArgs> ClosedEvent =
|
||||
RoutedEvent.Register<DrawerControlBase, ResultEventArgs>(
|
||||
nameof(Closed), RoutingStrategies.Bubble);
|
||||
|
||||
private bool _resizeDragging;
|
||||
|
||||
protected Panel? ContainerPanel;
|
||||
private Rect _resizeDragStartBounds;
|
||||
private Point _resizeDragStartPoint;
|
||||
|
||||
private WindowEdge? _windowEdge;
|
||||
|
||||
static OverlayFeedbackElement()
|
||||
{
|
||||
FocusableProperty.OverrideDefaultValue<OverlayFeedbackElement>(false);
|
||||
DataContextProperty.Changed.AddClassHandler<OverlayFeedbackElement, object?>((o, e) =>
|
||||
o.OnDataContextChange(e));
|
||||
ClosedEvent.AddClassHandler<OverlayFeedbackElement>((o, e) => o.OnClosed(e));
|
||||
}
|
||||
|
||||
public bool IsClosed
|
||||
{
|
||||
get => GetValue(IsClosedProperty);
|
||||
set => SetValue(IsClosedProperty, value);
|
||||
}
|
||||
|
||||
static OverlayFeedbackElement()
|
||||
{
|
||||
FocusableProperty.OverrideDefaultValue<OverlayFeedbackElement>(false);
|
||||
DataContextProperty.Changed.AddClassHandler<OverlayFeedbackElement, object?>((o, e) => o.OnDataContextChange(e));
|
||||
ClosedEvent.AddClassHandler<OverlayFeedbackElement>((o,e)=>o.OnClosed(e));
|
||||
}
|
||||
|
||||
private void OnClosed(ResultEventArgs _)
|
||||
{
|
||||
SetCurrentValue(IsClosedProperty,true);
|
||||
SetCurrentValue(IsClosedProperty, true);
|
||||
}
|
||||
|
||||
public static readonly RoutedEvent<ResultEventArgs> ClosedEvent = RoutedEvent.Register<DrawerControlBase, ResultEventArgs>(
|
||||
nameof(Closed), RoutingStrategies.Bubble);
|
||||
|
||||
public event EventHandler<ResultEventArgs> Closed
|
||||
{
|
||||
add => AddHandler(ClosedEvent, value);
|
||||
remove => RemoveHandler(ClosedEvent, value);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
if (args.OldValue.Value is IDialogContext oldContext) oldContext.RequestClose -= OnContextRequestClose;
|
||||
if (args.NewValue.Value is IDialogContext newContext) newContext.RequestClose += OnContextRequestClose;
|
||||
}
|
||||
|
||||
|
||||
protected virtual void OnElementClosing(object? sender, object? args)
|
||||
{
|
||||
RaiseEvent(new ResultEventArgs(ClosedEvent, args));
|
||||
}
|
||||
|
||||
|
||||
private void OnContextRequestClose(object? sender, object? args)
|
||||
{
|
||||
RaiseEvent(new ResultEventArgs(ClosedEvent, args));
|
||||
}
|
||||
|
||||
|
||||
public Task<T?> ShowAsync<T>(CancellationToken? token = default)
|
||||
{
|
||||
{
|
||||
var tcs = new TaskCompletionSource<T?>();
|
||||
token?.Register(() =>
|
||||
{
|
||||
Dispatcher.UIThread.Invoke(Close);
|
||||
});
|
||||
|
||||
token?.Register(() => { Dispatcher.UIThread.Invoke(Close); });
|
||||
|
||||
void OnCloseHandler(object? sender, ResultEventArgs? args)
|
||||
{
|
||||
if (args?.Result is T result)
|
||||
{
|
||||
tcs.SetResult(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
tcs.SetResult(default);
|
||||
}
|
||||
RemoveHandler(ClosedEvent, OnCloseHandler);
|
||||
}
|
||||
|
||||
AddHandler(ClosedEvent, OnCloseHandler);
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
|
||||
public abstract void Close();
|
||||
|
||||
internal void BeginResizeDrag(WindowEdge windowEdge, PointerPressedEventArgs e)
|
||||
{
|
||||
if (!e.GetCurrentPoint(this).Properties.IsLeftButtonPressed) return;
|
||||
_resizeDragging = true;
|
||||
_resizeDragStartPoint = e.GetPosition(this);
|
||||
_resizeDragStartBounds = Bounds;
|
||||
_windowEdge = windowEdge;
|
||||
}
|
||||
|
||||
internal void BeginMoveDrag(PointerPressedEventArgs e)
|
||||
{
|
||||
if (!e.GetCurrentPoint(this).Properties.IsLeftButtonPressed) return;
|
||||
_resizeDragging = true;
|
||||
_resizeDragStartPoint = e.GetPosition(this);
|
||||
_resizeDragStartBounds = Bounds;
|
||||
_windowEdge = null;
|
||||
}
|
||||
|
||||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnAttachedToVisualTree(e);
|
||||
ContainerPanel = this.FindAncestorOfType<Panel>();
|
||||
}
|
||||
|
||||
protected override void OnPointerReleased(PointerReleasedEventArgs e)
|
||||
{
|
||||
base.OnPointerReleased(e);
|
||||
_resizeDragging = false;
|
||||
}
|
||||
|
||||
protected override void OnPointerCaptureLost(PointerCaptureLostEventArgs e)
|
||||
{
|
||||
base.OnPointerCaptureLost(e);
|
||||
_resizeDragging = false;
|
||||
}
|
||||
|
||||
protected override void OnPointerMoved(PointerEventArgs e)
|
||||
{
|
||||
base.OnPointerMoved(e);
|
||||
if (!_resizeDragging || _windowEdge is null) return;
|
||||
var point = e.GetPosition(this);
|
||||
Vector diff = point - _resizeDragStartPoint;
|
||||
var left = Canvas.GetLeft(this);
|
||||
var top = Canvas.GetTop(this);
|
||||
var width = _windowEdge is WindowEdge.West or WindowEdge.NorthWest or WindowEdge.SouthWest
|
||||
? Bounds.Width : _resizeDragStartBounds.Width;
|
||||
var height = _windowEdge is WindowEdge.North or WindowEdge.NorthEast or WindowEdge.NorthWest
|
||||
? Bounds.Height : _resizeDragStartBounds.Height;
|
||||
var newBounds = CalculateNewBounds(left, top, width, height, diff, ContainerPanel?.Bounds, _windowEdge.Value);
|
||||
Canvas.SetLeft(this, newBounds.Left);
|
||||
Canvas.SetTop(this, newBounds.Top);
|
||||
SetCurrentValue(WidthProperty, newBounds.Width);
|
||||
SetCurrentValue(HeightProperty, newBounds.Height);
|
||||
AnchorAndUpdatePositionInfo();
|
||||
}
|
||||
|
||||
private Rect CalculateNewBounds(double left, double top, double width, double height, Vector diff, Rect? containerBounds,
|
||||
WindowEdge windowEdge)
|
||||
{
|
||||
diff = CoerceDelta(left, top, width, height, diff, containerBounds, windowEdge);
|
||||
switch (windowEdge)
|
||||
{
|
||||
case WindowEdge.North:
|
||||
top += diff.Y; height -= diff.Y;
|
||||
break;
|
||||
case WindowEdge.NorthEast:
|
||||
top += diff.Y; width += diff.X; height -= diff.Y;
|
||||
break;
|
||||
case WindowEdge.East:
|
||||
width += diff.X;
|
||||
break;
|
||||
case WindowEdge.SouthEast:
|
||||
width += diff.X; height += diff.Y;
|
||||
break;
|
||||
case WindowEdge.South:
|
||||
height += diff.Y;
|
||||
break;
|
||||
case WindowEdge.SouthWest:
|
||||
left += diff.X; width -= diff.X; height += diff.Y;
|
||||
break;
|
||||
case WindowEdge.West:
|
||||
left += diff.X; width -= diff.X;
|
||||
break;
|
||||
case WindowEdge.NorthWest:
|
||||
left += diff.X; top += diff.Y; width -= diff.X; height -= diff.Y;
|
||||
break;
|
||||
}
|
||||
return new Rect(left, top, width, height);
|
||||
}
|
||||
|
||||
private Vector CoerceDelta(double left, double top, double width, double height, Vector diff, Rect? containerBounds,
|
||||
WindowEdge windowEdge)
|
||||
{
|
||||
if (containerBounds is null) return diff;
|
||||
var minX = windowEdge is WindowEdge.West or WindowEdge.NorthWest or WindowEdge.SouthWest
|
||||
? -left
|
||||
: -width;
|
||||
var minY = windowEdge is WindowEdge.North or WindowEdge.NorthEast or WindowEdge.NorthWest
|
||||
? -top
|
||||
: -height;
|
||||
var maxX = windowEdge is WindowEdge.West or WindowEdge.NorthWest or WindowEdge.SouthWest
|
||||
? width-MinWidth
|
||||
: containerBounds.Value.Width - left - width;
|
||||
var maxY = windowEdge is WindowEdge.North or WindowEdge.NorthEast or WindowEdge.NorthWest
|
||||
? height-MinWidth
|
||||
: containerBounds.Value.Height - top - height;
|
||||
return new Vector(MathHelpers.SafeClamp(diff.X, minX, maxX), MathHelpers.SafeClamp(diff.Y, minY, maxY));
|
||||
}
|
||||
|
||||
protected internal abstract void AnchorAndUpdatePositionInfo();
|
||||
}
|
||||
75
src/Ursa/Controls/Resizers/DialogResizer.cs
Normal file
75
src/Ursa/Controls/Resizers/DialogResizer.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Irihi.Avalonia.Shared.Helpers;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public class DialogResizer: TemplatedControl
|
||||
{
|
||||
public const string PART_Top = "PART_Top";
|
||||
public const string PART_Bottom = "PART_Bottom";
|
||||
public const string PART_Left = "PART_Left";
|
||||
public const string PART_Right = "PART_Right";
|
||||
public const string PART_TopLeft = "PART_TopLeft";
|
||||
public const string PART_TopRight = "PART_TopRight";
|
||||
public const string PART_BottomLeft = "PART_BottomLeft";
|
||||
public const string PART_BottomRight = "PART_BottomRight";
|
||||
|
||||
private Thumb? _top;
|
||||
private Thumb? _bottom;
|
||||
private Thumb? _left;
|
||||
private Thumb? _right;
|
||||
private Thumb? _topLeft;
|
||||
private Thumb? _topRight;
|
||||
private Thumb? _bottomLeft;
|
||||
private Thumb? _bottomRight;
|
||||
|
||||
public static readonly StyledProperty<ResizeDirection> ResizeDirectionProperty = AvaloniaProperty.Register<DialogResizer, ResizeDirection>(
|
||||
nameof(ResizeDirection), ResizeDirection.All);
|
||||
|
||||
/// <summary>
|
||||
/// Defines what direction the dialog is allowed to be resized.
|
||||
/// </summary>
|
||||
public ResizeDirection ResizeDirection
|
||||
{
|
||||
get => GetValue(ResizeDirectionProperty);
|
||||
set => SetValue(ResizeDirectionProperty, value);
|
||||
}
|
||||
|
||||
static DialogResizer()
|
||||
{
|
||||
ResizeDirectionProperty.Changed.AddClassHandler<DialogResizer, ResizeDirection>((resizer, e) => resizer.OnResizeDirectionChanged(e));
|
||||
}
|
||||
|
||||
private void OnResizeDirectionChanged(AvaloniaPropertyChangedEventArgs<ResizeDirection> args)
|
||||
{
|
||||
UpdateThumbVisibility(args.NewValue.Value);
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
_top = e.NameScope.Find<Thumb>(PART_Top);
|
||||
_bottom = e.NameScope.Find<Thumb>(PART_Bottom);
|
||||
_left = e.NameScope.Find<Thumb>(PART_Left);
|
||||
_right = e.NameScope.Find<Thumb>(PART_Right);
|
||||
_topLeft = e.NameScope.Find<Thumb>(PART_TopLeft);
|
||||
_topRight = e.NameScope.Find<Thumb>(PART_TopRight);
|
||||
_bottomLeft = e.NameScope.Find<Thumb>(PART_BottomLeft);
|
||||
_bottomRight = e.NameScope.Find<Thumb>(PART_BottomRight);
|
||||
UpdateThumbVisibility(ResizeDirection);
|
||||
}
|
||||
|
||||
private void UpdateThumbVisibility(ResizeDirection direction)
|
||||
{
|
||||
IsVisibleProperty.SetValue(direction.HasFlag(ResizeDirection.Top), _top);
|
||||
IsVisibleProperty.SetValue(direction.HasFlag(ResizeDirection.Bottom), _bottom);
|
||||
IsVisibleProperty.SetValue(direction.HasFlag(ResizeDirection.Left), _left);
|
||||
IsVisibleProperty.SetValue(direction.HasFlag(ResizeDirection.Right), _right);
|
||||
IsVisibleProperty.SetValue(direction.HasFlag(ResizeDirection.TopLeft), _topLeft);
|
||||
IsVisibleProperty.SetValue(direction.HasFlag(ResizeDirection.TopRight), _topRight);
|
||||
IsVisibleProperty.SetValue(direction.HasFlag(ResizeDirection.BottomLeft), _bottomLeft);
|
||||
IsVisibleProperty.SetValue(direction.HasFlag(ResizeDirection.BottomRight), _bottomRight);
|
||||
}
|
||||
}
|
||||
48
src/Ursa/Controls/Resizers/DialogResizerThumb.cs
Normal file
48
src/Ursa/Controls/Resizers/DialogResizerThumb.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.LogicalTree;
|
||||
using Ursa.Controls.OverlayShared;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public class DialogResizerThumb: Thumb
|
||||
{
|
||||
private OverlayFeedbackElement? _dialog;
|
||||
|
||||
public static readonly StyledProperty<ResizeDirection> ResizeDirectionProperty = AvaloniaProperty.Register<DialogResizerThumb, ResizeDirection>(
|
||||
nameof(ResizeDirection));
|
||||
|
||||
public ResizeDirection ResizeDirection
|
||||
{
|
||||
get => GetValue(ResizeDirectionProperty);
|
||||
set => SetValue(ResizeDirectionProperty, value);
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
_dialog = this.FindLogicalAncestorOfType<OverlayFeedbackElement>();
|
||||
}
|
||||
|
||||
protected override void OnPointerPressed(PointerPressedEventArgs e)
|
||||
{
|
||||
base.OnPointerPressed(e);
|
||||
if (_dialog is null) return;
|
||||
if (!e.GetCurrentPoint(this).Properties.IsLeftButtonPressed) return;
|
||||
var windowEdge = ResizeDirection switch
|
||||
{
|
||||
ResizeDirection.Top => WindowEdge.North,
|
||||
ResizeDirection.TopRight => WindowEdge.NorthEast,
|
||||
ResizeDirection.Right => WindowEdge.East,
|
||||
ResizeDirection.BottomRight => WindowEdge.SouthEast,
|
||||
ResizeDirection.Bottom => WindowEdge.South,
|
||||
ResizeDirection.BottomLeft => WindowEdge.SouthWest,
|
||||
ResizeDirection.Left => WindowEdge.West,
|
||||
ResizeDirection.TopLeft => WindowEdge.NorthWest,
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
_dialog.BeginResizeDrag(windowEdge, e);
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,18 @@
|
||||
namespace Ursa.Controls;
|
||||
|
||||
[Flags]
|
||||
public enum ResizeDirection
|
||||
{
|
||||
Top,
|
||||
Bottom,
|
||||
Left,
|
||||
Right,
|
||||
TopLeft,
|
||||
TopRight,
|
||||
BottomLeft,
|
||||
BottomRight,
|
||||
Top = 1,
|
||||
Bottom = 2,
|
||||
Left = 4,
|
||||
Right = 8,
|
||||
TopLeft = 16,
|
||||
TopRight = 32,
|
||||
BottomLeft = 64,
|
||||
BottomRight = 128,
|
||||
|
||||
Sides = Top | Bottom | Left | Right,
|
||||
Corners = TopLeft | TopRight | BottomLeft | BottomRight,
|
||||
All = Sides | Corners,
|
||||
}
|
||||
Reference in New Issue
Block a user