Merge pull request #465 from irihitech/issue-422

New Dialog/Drawer/MessageBox option: StyleClass
This commit is contained in:
Dong Bin
2024-11-11 23:46:53 +08:00
committed by GitHub
26 changed files with 486 additions and 215 deletions

23
.github/workflows/test.yml vendored Normal file
View File

@@ -0,0 +1,23 @@
name: Test
on:
push:
branches: [ "action/publish" ]
pull_request:
branches: [ "main" ]
jobs:
windows:
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v4.1.1
- name: Ursa Headless Test
run: dotnet test ./tests/HeadlessTest.Ursa
ubuntu:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4.1.1
- name: Ursa Headless Test
run: dotnet test ./tests/HeadlessTest.Ursa

View File

@@ -3,9 +3,18 @@
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:semi="https://irihi.tech/semi"
xmlns:u-semi="https://irihi.tech/ursa/themes/semi">
xmlns:u-semi="https://irihi.tech/ursa/themes/semi"
xmlns:u="https://irihi.tech/ursa"
xmlns:helpers="clr-namespace:Irihi.Avalonia.Shared.Helpers;assembly=Irihi.Avalonia.Shared">
<Application.Styles>
<semi:SemiTheme Locale="zh-CN" />
<u-semi:SemiTheme Locale="zh-CN" />
<!--This style is created to demonstrate Dialog StyleClass feature. This style is applied to Dialog Window-->
<Style Selector="u|DefaultDialogWindow.Custom">
<Style Selector="^ /template/ Button#PART_OKButton">
<Setter Property="Content" Value="CUSTOM"/>
<Setter Property="helpers:ClassHelper.Classes" Value="Warning"></Setter>
</Style>
</Style>
</Application.Styles>
</Application>

View File

@@ -51,6 +51,21 @@
IsThreeState="True" />
<CheckBox u:FormItem.Label="CanDragMove" IsChecked="{Binding CanDragMove}" />
<CheckBox u:FormItem.Label="CanResize" IsChecked="{Binding CanResize}" />
<u:FormItem>
<u:FormItem.Label>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Style Class" />
<PathIcon
Width="12"
Height="12"
VerticalAlignment="Center"
TextElement.FontWeight="Normal"
Data="{DynamicResource DialogQuestionIconGlyph}"
ToolTip.Tip="Pass a Style Class to the created Dialog. In this example, if you set StyleClass as 'Custom', You will get Special Style for OK Button. These styles usually are defined in the root of your App/Window" />
</StackPanel>
</u:FormItem.Label>
<TextBox HorizontalAlignment="Stretch" Text="{Binding StyleClass}" />
</u:FormItem>
<Button
HorizontalAlignment="Left"
u:FormItem.NoLabel="True"
@@ -128,6 +143,21 @@
IsChecked="{Binding IsLocal}"
OffContent="Global"
OnContent="Local" />
<u:FormItem>
<u:FormItem.Label>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Style Class" />
<PathIcon
Width="12"
Height="12"
VerticalAlignment="Center"
TextElement.FontWeight="Normal"
Data="{DynamicResource DialogQuestionIconGlyph}"
ToolTip.Tip="Pass a Style Class to the created Dialog. In this example, if you set StyleClass as 'Custom', You will get Special Style for OK Button. These styles usually are defined in the root of your App/Window" />
</StackPanel>
</u:FormItem.Label>
<TextBox HorizontalAlignment="Stretch" Text="{Binding StyleClass}" />
</u:FormItem>
<Button
HorizontalAlignment="Left"
u:FormItem.NoLabel="True"

View File

@@ -33,6 +33,7 @@ public partial class DefaultWindowDialogDemoViewModel: ObservableObject
[ObservableProperty] private bool? _isCloseButtonVisible;
[ObservableProperty] private bool _canDragMove;
[ObservableProperty] private bool _canResize;
[ObservableProperty] private string? _styleClass;
public ICommand ShowDialogCommand { get; }
@@ -57,6 +58,7 @@ public partial class DefaultWindowDialogDemoViewModel: ObservableObject
StartupLocation = Location,
CanDragMove = CanDragMove,
CanResize = CanResize,
StyleClass = StyleClass,
};
if (X.HasValue && Y.HasValue)
{
@@ -133,6 +135,7 @@ public partial class DefaultOverlayDialogDemoViewModel : ObservableObject
[ObservableProperty] private bool _isModal;
[ObservableProperty] private bool _isLocal;
[ObservableProperty] private bool _canResize;
[ObservableProperty] private string? _styleClass;
public ICommand ShowDialogCommand { get; }
@@ -163,6 +166,7 @@ public partial class DefaultOverlayDialogDemoViewModel : ObservableObject
CanDragMove = CanDragMove,
IsCloseButtonVisible = IsCloseButtonVisible,
CanResize = CanResize,
StyleClass = StyleClass,
};
string? dialogHostId = IsLocal ? DialogDemoViewModel.LocalHost : null;
if (IsModal)

View File

@@ -3,21 +3,31 @@
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:helpers="clr-namespace:Irihi.Avalonia.Shared.Helpers;assembly=Irihi.Avalonia.Shared"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:views="clr-namespace:Ursa.Demo.Views"
xmlns:u="https://irihi.tech/ursa"
xmlns:viewModels="clr-namespace:Ursa.Demo.ViewModels"
xmlns:views="clr-namespace:Ursa.Demo.Views"
Title="Ursa.Demo"
d:DesignHeight="450"
d:DesignWidth="800"
x:CompileBindings="True"
IsFullScreenButtonVisible="{OnPlatform True, macOS=False}"
IsManagedResizerVisible="{OnPlatform False, Linux=True}"
x:DataType="viewModels:MainWindowViewModel"
Icon="/Assets/Ursa.ico"
IsFullScreenButtonVisible="{OnPlatform True, macOS=False}"
IsManagedResizerVisible="{OnPlatform False, Linux=True}"
mc:Ignorable="d">
<u:UrsaWindow.RightContent>
<views:TitleBarRightContent/>
<views:TitleBarRightContent />
</u:UrsaWindow.RightContent>
<u:UrsaWindow.Styles>
<!--This style is created to demonstrate Dialog StyleClass feature. This style is applied to dialogs in MainWindow OverlayDialogHost -->
<Style Selector="u|DefaultDialogControl.Custom">
<Style Selector="^ /template/ Button#PART_OKButton">
<Setter Property="Content" Value="CUSTOM" />
<Setter Property="helpers:ClassHelper.Classes" Value="Warning" />
</Style>
</Style>
</u:UrsaWindow.Styles>
<views:MainView />
</u:UrsaWindow>

View File

@@ -1,69 +0,0 @@
using System.Collections.Specialized;
using Avalonia;
using Avalonia.Collections;
namespace Ursa.Themes.Semi;
internal class ClassHelper : AvaloniaObject
{
public static readonly AttachedProperty<string> ClassesProperty =
AvaloniaProperty.RegisterAttached<ClassHelper, StyledElement, string>("Classes");
public static readonly AttachedProperty<StyledElement> ClassSourceProperty =
AvaloniaProperty.RegisterAttached<ClassHelper, StyledElement, StyledElement>("ClassSource");
static ClassHelper()
{
ClassesProperty.Changed.AddClassHandler<StyledElement>(OnClassesChanged);
ClassSourceProperty.Changed.AddClassHandler<StyledElement>(OnClassSourceChanged);
}
private static void OnClassSourceChanged(StyledElement arg1, AvaloniaPropertyChangedEventArgs arg2)
{
if (arg2.NewValue is StyledElement styledElement)
{
arg1.Classes.Clear();
var nonPseudoClasses = styledElement.Classes.Where(c => !c.StartsWith(":"));
arg1.Classes.AddRange(nonPseudoClasses);
styledElement.Classes.WeakSubscribe((o, e) => OnSourceClassesChanged(o, e, arg1));
}
}
private static void OnSourceClassesChanged(object sender, NotifyCollectionChangedEventArgs e, StyledElement target)
{
if (sender is AvaloniaList<string> classes)
{
target.Classes.Clear();
var nonPseudoClasses = classes.Where(c => !c.StartsWith(":"));
target.Classes.AddRange(nonPseudoClasses);
}
}
public static void SetClasses(AvaloniaObject obj, string value)
{
obj.SetValue(ClassesProperty, value);
}
public static string GetClasses(AvaloniaObject obj)
{
return obj.GetValue(ClassesProperty);
}
private static void OnClassesChanged(StyledElement sender, AvaloniaPropertyChangedEventArgs value)
{
var classes = value.GetNewValue<string?>();
if (classes is null) return;
sender.Classes.Clear();
sender.Classes.Add(classes);
}
public static void SetClassSource(StyledElement obj, StyledElement value)
{
obj.SetValue(ClassSourceProperty, value);
}
public static StyledElement GetClassSource(StyledElement obj)
{
return obj.GetValue(ClassSourceProperty);
}
}

View File

@@ -2,7 +2,7 @@
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:u="https://irihi.tech/ursa"
xmlns:usemi="https://irihi.tech/ursa/themes/semi">
xmlns:helpers="clr-namespace:Irihi.Avalonia.Shared.Helpers;assembly=Irihi.Avalonia.Shared">
<!-- Add Resources Here -->
<ControlTheme x:Key="{x:Type u:AutoCompleteBox}" TargetType="u:AutoCompleteBox">
<Setter Property="VerticalAlignment" Value="Center" />
@@ -15,7 +15,7 @@
Name="PART_TextBox"
MinHeight="{TemplateBinding MinHeight}"
VerticalAlignment="Stretch"
usemi:ClassHelper.ClassSource="{TemplateBinding}"
helpers:ClassHelper.ClassSource="{TemplateBinding}"
DataValidationErrors.Errors="{TemplateBinding (DataValidationErrors.Errors)}"
InnerLeftContent="{TemplateBinding InnerLeftContent}"
InnerRightContent="{TemplateBinding InnerRightContent}"

View File

@@ -1,8 +1,8 @@
<ResourceDictionary
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:theme="clr-namespace:Ursa.Themes.Semi"
xmlns:u="https://irihi.tech/ursa">
xmlns:u="https://irihi.tech/ursa"
xmlns:helpers="clr-namespace:Irihi.Avalonia.Shared.Helpers;assembly=Irihi.Avalonia.Shared">
<ControlTheme x:Key="{x:Type u:OverlayDialogHost}" TargetType="u:OverlayDialogHost">
<Setter Property="OverlayMaskBrush" Value="{DynamicResource OverlayDialogMaskBrush}" />
@@ -207,35 +207,24 @@
DockPanel.Dock="Right"
Theme="{DynamicResource OverlayCloseButton}" />
</Grid>
<StackPanel
<Grid
Grid.Row="2"
Margin="24,0,24,24"
HorizontalAlignment="Right"
Orientation="Horizontal">
ColumnDefinitions="Auto, Auto, Auto, Auto">
<Button
Name="{x:Static u:DefaultDialogControl.PART_CancelButton}"
Margin="8,0,0,0"
Classes="Tertiary"
Content="{DynamicResource STRING_MENU_DIALOG_CANCEL}" />
Margin="8,0,0,0" />
<Button
Name="{x:Static u:DefaultDialogControl.PART_NoButton}"
Margin="8,0,0,0"
Classes="Danger"
Content="{DynamicResource STRING_MENU_DIALOG_NO}"
Theme="{DynamicResource SolidButton}" />
Margin="8,0,0,0"/>
<Button
Name="{x:Static u:DefaultDialogControl.PART_YesButton}"
Margin="8,0,0,0"
Classes="Primary"
Content="{DynamicResource STRING_MENU_DIALOG_YES}"
Theme="{DynamicResource SolidButton}" />
Margin="8,0,0,0"/>
<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>
Margin="8,0,0,0"/>
</Grid>
</Grid>
</Border>
@@ -254,6 +243,29 @@
<Setter Property="Margin" Value="0" />
<Setter Property="Background" Value="{DynamicResource BorderCardBackground}" />
</Style>
<Style Selector="^ /template/ Button#PART_CancelButton">
<Setter Property="Grid.Column" Value="0"/>
<Setter Property="helpers:ClassHelper.Classes" Value="Tertiary"/>
<Setter Property="Content" Value="{DynamicResource STRING_MENU_DIALOG_CANCEL}"/>
</Style>
<Style Selector="^ /template/ Button#PART_NoButton">
<Setter Property="Grid.Column" Value="1"></Setter>
<Setter Property="helpers:ClassHelper.Classes" Value="Danger"/>
<Setter Property="Content" Value="{DynamicResource STRING_MENU_DIALOG_NO}"/>
<Setter Property="Theme" Value="{DynamicResource SolidButton}"/>
</Style>
<Style Selector="^ /template/ Button#PART_YesButton">
<Setter Property="Grid.Column" Value="2"></Setter>
<Setter Property="helpers:ClassHelper.Classes" Value="Primary"/>
<Setter Property="Content" Value="{DynamicResource STRING_MENU_DIALOG_YES}"/>
<Setter Property="Theme" Value="{DynamicResource SolidButton}"/>
</Style>
<Style Selector="^ /template/ Button#PART_OKButton">
<Setter Property="Grid.Column" Value="3"></Setter>
<Setter Property="helpers:ClassHelper.Classes" Value="Primary"/>
<Setter Property="Content" Value="{DynamicResource STRING_MENU_DIALOG_OK}"/>
<Setter Property="Theme" Value="{DynamicResource SolidButton}"/>
</Style>
<Style Selector="^[Mode=None]">
<Style Selector="^ /template/ PathIcon#PART_Icon">
<Setter Property="IsVisible" Value="False" />
@@ -262,16 +274,16 @@
<Setter Property="Margin" Value="24 24 0 0" />
</Style>
<Style Selector="^ /template/ Button#PART_OKButton">
<Setter Property="theme:ClassHelper.Classes" Value="Primary" />
<Setter Property="helpers:ClassHelper.Classes" Value="Primary" />
</Style>
<Style Selector="^ /template/ Button#PART_YesButton">
<Setter Property="theme:ClassHelper.Classes" Value="Primary" />
<Setter Property="helpers:ClassHelper.Classes" Value="Primary" />
</Style>
<Style Selector="^ /template/ Button#PART_NoButton">
<Setter Property="theme:ClassHelper.Classes" Value="Danger" />
<Setter Property="helpers:ClassHelper.Classes" Value="Danger" />
</Style>
<Style Selector="^ /template/ Button#PART_CancelButton">
<Setter Property="theme:ClassHelper.Classes" Value="Tertiary" />
<Setter Property="helpers:ClassHelper.Classes" Value="Tertiary" />
</Style>
</Style>
<Style Selector="^[Mode=Info]">
@@ -281,16 +293,16 @@
<Setter Property="Foreground" Value="{DynamicResource SemiBlue6}" />
</Style>
<Style Selector="^ /template/ Button#PART_OKButton">
<Setter Property="theme:ClassHelper.Classes" Value="Primary" />
<Setter Property="helpers:ClassHelper.Classes" Value="Primary" />
</Style>
<Style Selector="^ /template/ Button#PART_YesButton">
<Setter Property="theme:ClassHelper.Classes" Value="Primary" />
<Setter Property="helpers:ClassHelper.Classes" Value="Primary" />
</Style>
<Style Selector="^ /template/ Button#PART_NoButton">
<Setter Property="theme:ClassHelper.Classes" Value="Danger" />
<Setter Property="helpers:ClassHelper.Classes" Value="Danger" />
</Style>
<Style Selector="^ /template/ Button#PART_CancelButton">
<Setter Property="theme:ClassHelper.Classes" Value="Tertiary" />
<Setter Property="helpers:ClassHelper.Classes" Value="Tertiary" />
</Style>
</Style>
<Style Selector="^[Mode=Warning]">
@@ -300,19 +312,19 @@
<Setter Property="Foreground" Value="{DynamicResource SemiOrange6}" />
</Style>
<Style Selector="^ /template/ Button#PART_OKButton">
<Setter Property="theme:ClassHelper.Classes" Value="Warning" />
<Setter Property="helpers:ClassHelper.Classes" Value="Warning" />
<Setter Property="Theme" Value="{DynamicResource SolidButton}" />
</Style>
<Style Selector="^ /template/ Button#PART_YesButton">
<Setter Property="theme:ClassHelper.Classes" Value="Warning" />
<Setter Property="helpers:ClassHelper.Classes" Value="Warning" />
<Setter Property="Theme" Value="{DynamicResource SolidButton}" />
</Style>
<Style Selector="^ /template/ Button#PART_NoButton">
<Setter Property="theme:ClassHelper.Classes" Value="Danger" />
<Setter Property="helpers:ClassHelper.Classes" Value="Danger" />
<Setter Property="Theme" Value="{DynamicResource SolidButton}" />
</Style>
<Style Selector="^ /template/ Button#PART_CancelButton">
<Setter Property="theme:ClassHelper.Classes" Value="Tertiary" />
<Setter Property="helpers:ClassHelper.Classes" Value="Tertiary" />
</Style>
</Style>
<Style Selector="^[Mode=Error]">
@@ -322,16 +334,16 @@
<Setter Property="Foreground" Value="{DynamicResource SemiRed6}" />
</Style>
<Style Selector="^ /template/ Button#PART_OKButton">
<Setter Property="theme:ClassHelper.Classes" Value="Danger" />
<Setter Property="helpers:ClassHelper.Classes" Value="Danger" />
</Style>
<Style Selector="^ /template/ Button#PART_YesButton">
<Setter Property="theme:ClassHelper.Classes" Value="Danger" />
<Setter Property="helpers:ClassHelper.Classes" Value="Danger" />
</Style>
<Style Selector="^ /template/ Button#PART_NoButton">
<Setter Property="theme:ClassHelper.Classes" Value="Tertiary" />
<Setter Property="helpers:ClassHelper.Classes" Value="Tertiary" />
</Style>
<Style Selector="^ /template/ Button#PART_CancelButton">
<Setter Property="theme:ClassHelper.Classes" Value="Tertiary" />
<Setter Property="helpers:ClassHelper.Classes" Value="Tertiary" />
</Style>
</Style>
<Style Selector="^[Mode=Question]">
@@ -341,16 +353,16 @@
<Setter Property="Foreground" Value="{DynamicResource SemiBlue6}" />
</Style>
<Style Selector="^ /template/ Button#PART_OKButton">
<Setter Property="theme:ClassHelper.Classes" Value="Primary" />
<Setter Property="helpers:ClassHelper.Classes" Value="Primary" />
</Style>
<Style Selector="^ /template/ Button#PART_YesButton">
<Setter Property="theme:ClassHelper.Classes" Value="Primary" />
<Setter Property="helpers:ClassHelper.Classes" Value="Primary" />
</Style>
<Style Selector="^ /template/ Button#PART_NoButton">
<Setter Property="theme:ClassHelper.Classes" Value="Danger" />
<Setter Property="helpers:ClassHelper.Classes" Value="Danger" />
</Style>
<Style Selector="^ /template/ Button#PART_CancelButton">
<Setter Property="theme:ClassHelper.Classes" Value="Tertiary" />
<Setter Property="helpers:ClassHelper.Classes" Value="Tertiary" />
</Style>
</Style>
<Style Selector="^[Mode=Success]">
@@ -360,16 +372,16 @@
<Setter Property="Foreground" Value="{DynamicResource SemiGreen6}" />
</Style>
<Style Selector="^ /template/ Button#PART_OKButton">
<Setter Property="theme:ClassHelper.Classes" Value="Success" />
<Setter Property="helpers:ClassHelper.Classes" Value="Success" />
</Style>
<Style Selector="^ /template/ Button#PART_YesButton">
<Setter Property="theme:ClassHelper.Classes" Value="Success" />
<Setter Property="helpers:ClassHelper.Classes" Value="Success" />
</Style>
<Style Selector="^ /template/ Button#PART_NoButton">
<Setter Property="theme:ClassHelper.Classes" Value="Danger" />
<Setter Property="helpers:ClassHelper.Classes" Value="Danger" />
</Style>
<Style Selector="^ /template/ Button#PART_CancelButton">
<Setter Property="theme:ClassHelper.Classes" Value="Tertiary" />
<Setter Property="helpers:ClassHelper.Classes" Value="Tertiary" />
</Style>
</Style>
<Style Selector="^ /template/ Panel#PART_TitleArea">
@@ -604,27 +616,16 @@
Orientation="Horizontal">
<Button
Name="{x:Static u:DefaultDialogControl.PART_CancelButton}"
Margin="8,0,0,0"
Classes="Tertiary"
Content="{DynamicResource STRING_MENU_DIALOG_CANCEL}" />
Margin="8,0,0,0" />
<Button
Name="{x:Static u:DefaultDialogControl.PART_NoButton}"
Margin="8,0,0,0"
Classes="Danger"
Content="{DynamicResource STRING_MENU_DIALOG_NO}"
Theme="{DynamicResource SolidButton}" />
Margin="8,0,0,0" />
<Button
Name="{x:Static u:DefaultDialogControl.PART_YesButton}"
Margin="8,0,0,0"
Classes="Primary"
Content="{DynamicResource STRING_MENU_DIALOG_YES}"
Theme="{DynamicResource SolidButton}" />
Margin="8,0,0,0" />
<Button
Name="{x:Static u:DefaultDialogControl.PART_OKButton}"
Margin="8,0,0,0"
Classes="Primary"
Content="{DynamicResource STRING_MENU_DIALOG_OK}"
Theme="{DynamicResource SolidButton}" />
Margin="8,0,0,0" />
</StackPanel>
</Grid>
@@ -633,6 +634,29 @@
</Panel>
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ Button#PART_CancelButton">
<Setter Property="Grid.Column" Value="0"/>
<Setter Property="helpers:ClassHelper.Classes" Value="Tertiary"/>
<Setter Property="Content" Value="{DynamicResource STRING_MENU_DIALOG_CANCEL}"/>
</Style>
<Style Selector="^ /template/ Button#PART_NoButton">
<Setter Property="Grid.Column" Value="1"></Setter>
<Setter Property="helpers:ClassHelper.Classes" Value="Danger"/>
<Setter Property="Content" Value="{DynamicResource STRING_MENU_DIALOG_NO}"/>
<Setter Property="Theme" Value="{DynamicResource SolidButton}"/>
</Style>
<Style Selector="^ /template/ Button#PART_YesButton">
<Setter Property="Grid.Column" Value="2"></Setter>
<Setter Property="helpers:ClassHelper.Classes" Value="Primary"/>
<Setter Property="Content" Value="{DynamicResource STRING_MENU_DIALOG_YES}"/>
<Setter Property="Theme" Value="{DynamicResource SolidButton}"/>
</Style>
<Style Selector="^ /template/ Button#PART_OKButton">
<Setter Property="Grid.Column" Value="3"></Setter>
<Setter Property="helpers:ClassHelper.Classes" Value="Primary"/>
<Setter Property="Content" Value="{DynamicResource STRING_MENU_DIALOG_OK}"/>
<Setter Property="Theme" Value="{DynamicResource SolidButton}"/>
</Style>
<Style Selector="^[Mode=None]">
<Style Selector="^ /template/ PathIcon#PART_Icon">
<Setter Property="IsVisible" Value="False" />
@@ -641,16 +665,16 @@
<Setter Property="Margin" Value="24 24 0 0" />
</Style>
<Style Selector="^ /template/ Button#PART_OKButton">
<Setter Property="theme:ClassHelper.Classes" Value="Primary" />
<Setter Property="helpers:ClassHelper.Classes" Value="Primary" />
</Style>
<Style Selector="^ /template/ Button#PART_YesButton">
<Setter Property="theme:ClassHelper.Classes" Value="Primary" />
<Setter Property="helpers:ClassHelper.Classes" Value="Primary" />
</Style>
<Style Selector="^ /template/ Button#PART_NoButton">
<Setter Property="theme:ClassHelper.Classes" Value="Danger" />
<Setter Property="helpers:ClassHelper.Classes" Value="Danger" />
</Style>
<Style Selector="^ /template/ Button#PART_CancelButton">
<Setter Property="theme:ClassHelper.Classes" Value="Tertiary" />
<Setter Property="helpers:ClassHelper.Classes" Value="Tertiary" />
</Style>
</Style>
<Style Selector="^[Mode=Info]">
@@ -660,16 +684,16 @@
<Setter Property="Foreground" Value="{DynamicResource SemiBlue6}" />
</Style>
<Style Selector="^ /template/ Button#PART_OKButton">
<Setter Property="theme:ClassHelper.Classes" Value="Primary" />
<Setter Property="helpers:ClassHelper.Classes" Value="Primary" />
</Style>
<Style Selector="^ /template/ Button#PART_YesButton">
<Setter Property="theme:ClassHelper.Classes" Value="Primary" />
<Setter Property="helpers:ClassHelper.Classes" Value="Primary" />
</Style>
<Style Selector="^ /template/ Button#PART_NoButton">
<Setter Property="theme:ClassHelper.Classes" Value="Danger" />
<Setter Property="helpers:ClassHelper.Classes" Value="Danger" />
</Style>
<Style Selector="^ /template/ Button#PART_CancelButton">
<Setter Property="theme:ClassHelper.Classes" Value="Tertiary" />
<Setter Property="helpers:ClassHelper.Classes" Value="Tertiary" />
</Style>
</Style>
<Style Selector="^[Mode=Warning]">
@@ -679,19 +703,19 @@
<Setter Property="Foreground" Value="{DynamicResource SemiOrange6}" />
</Style>
<Style Selector="^ /template/ Button#PART_OKButton">
<Setter Property="theme:ClassHelper.Classes" Value="Warning" />
<Setter Property="helpers:ClassHelper.Classes" Value="Warning" />
<Setter Property="Theme" Value="{DynamicResource SolidButton}" />
</Style>
<Style Selector="^ /template/ Button#PART_YesButton">
<Setter Property="theme:ClassHelper.Classes" Value="Warning" />
<Setter Property="helpers:ClassHelper.Classes" Value="Warning" />
<Setter Property="Theme" Value="{DynamicResource SolidButton}" />
</Style>
<Style Selector="^ /template/ Button#PART_NoButton">
<Setter Property="theme:ClassHelper.Classes" Value="Danger" />
<Setter Property="helpers:ClassHelper.Classes" Value="Danger" />
<Setter Property="Theme" Value="{DynamicResource SolidButton}" />
</Style>
<Style Selector="^ /template/ Button#PART_CancelButton">
<Setter Property="theme:ClassHelper.Classes" Value="Tertiary" />
<Setter Property="helpers:ClassHelper.Classes" Value="Tertiary" />
</Style>
</Style>
<Style Selector="^[Mode=Error]">
@@ -701,16 +725,16 @@
<Setter Property="Foreground" Value="{DynamicResource SemiRed6}" />
</Style>
<Style Selector="^ /template/ Button#PART_OKButton">
<Setter Property="theme:ClassHelper.Classes" Value="Danger" />
<Setter Property="helpers:ClassHelper.Classes" Value="Danger" />
</Style>
<Style Selector="^ /template/ Button#PART_YesButton">
<Setter Property="theme:ClassHelper.Classes" Value="Danger" />
<Setter Property="helpers:ClassHelper.Classes" Value="Danger" />
</Style>
<Style Selector="^ /template/ Button#PART_NoButton">
<Setter Property="theme:ClassHelper.Classes" Value="Tertiary" />
<Setter Property="helpers:ClassHelper.Classes" Value="Tertiary" />
</Style>
<Style Selector="^ /template/ Button#PART_CancelButton">
<Setter Property="theme:ClassHelper.Classes" Value="Tertiary" />
<Setter Property="helpers:ClassHelper.Classes" Value="Tertiary" />
</Style>
</Style>
<Style Selector="^[Mode=Question]">
@@ -720,16 +744,16 @@
<Setter Property="Foreground" Value="{DynamicResource SemiBlue6}" />
</Style>
<Style Selector="^ /template/ Button#PART_OKButton">
<Setter Property="theme:ClassHelper.Classes" Value="Primary" />
<Setter Property="helpers:ClassHelper.Classes" Value="Primary" />
</Style>
<Style Selector="^ /template/ Button#PART_YesButton">
<Setter Property="theme:ClassHelper.Classes" Value="Primary" />
<Setter Property="helpers:ClassHelper.Classes" Value="Primary" />
</Style>
<Style Selector="^ /template/ Button#PART_NoButton">
<Setter Property="theme:ClassHelper.Classes" Value="Danger" />
<Setter Property="helpers:ClassHelper.Classes" Value="Danger" />
</Style>
<Style Selector="^ /template/ Button#PART_CancelButton">
<Setter Property="theme:ClassHelper.Classes" Value="Tertiary" />
<Setter Property="helpers:ClassHelper.Classes" Value="Tertiary" />
</Style>
</Style>
<Style Selector="^[Mode=Success]">
@@ -739,16 +763,16 @@
<Setter Property="Foreground" Value="{DynamicResource SemiGreen6}" />
</Style>
<Style Selector="^ /template/ Button#PART_OKButton">
<Setter Property="theme:ClassHelper.Classes" Value="Success" />
<Setter Property="helpers:ClassHelper.Classes" Value="Success" />
</Style>
<Style Selector="^ /template/ Button#PART_YesButton">
<Setter Property="theme:ClassHelper.Classes" Value="Success" />
<Setter Property="helpers:ClassHelper.Classes" Value="Success" />
</Style>
<Style Selector="^ /template/ Button#PART_NoButton">
<Setter Property="theme:ClassHelper.Classes" Value="Danger" />
<Setter Property="helpers:ClassHelper.Classes" Value="Danger" />
</Style>
<Style Selector="^ /template/ Button#PART_CancelButton">
<Setter Property="theme:ClassHelper.Classes" Value="Tertiary" />
<Setter Property="helpers:ClassHelper.Classes" Value="Tertiary" />
</Style>
</Style>
</ControlTheme>

View File

@@ -2,7 +2,8 @@
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">
xmlns:u="https://irihi.tech/ursa"
xmlns:helpers="clr-namespace:Irihi.Avalonia.Shared.Helpers;assembly=Irihi.Avalonia.Shared">
<ControlTheme x:Key="{x:Type u:CustomDrawerControl}" TargetType="u:CustomDrawerControl">
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
@@ -157,27 +158,16 @@
Orientation="Horizontal">
<Button
Name="{x:Static u:DefaultDialogControl.PART_CancelButton}"
Margin="8,0,0,0"
Classes="Tertiary"
Content="{DynamicResource STRING_MENU_DIALOG_CANCEL}" />
Margin="8,0,0,0" />
<Button
Name="{x:Static u:DefaultDialogControl.PART_NoButton}"
Margin="8,0,0,0"
Classes="Danger"
Content="{DynamicResource STRING_MENU_DIALOG_NO}"
Theme="{DynamicResource SolidButton}" />
Margin="8,0,0,0" />
<Button
Name="{x:Static u:DefaultDialogControl.PART_YesButton}"
Margin="8,0,0,0"
Classes="Primary"
Content="{DynamicResource STRING_MENU_DIALOG_YES}"
Theme="{DynamicResource SolidButton}" />
Margin="8,0,0,0" />
<Button
Name="{x:Static u:DefaultDialogControl.PART_OKButton}"
Margin="8,0,0,0"
Classes="Primary"
Content="{DynamicResource STRING_MENU_DIALOG_OK}"
Theme="{DynamicResource SolidButton}" />
Margin="8,0,0,0" />
</StackPanel>
</Grid>
</Border>
@@ -186,6 +176,29 @@
</Panel>
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ Button#PART_CancelButton">
<Setter Property="Grid.Column" Value="0"/>
<Setter Property="helpers:ClassHelper.Classes" Value="Tertiary"/>
<Setter Property="Content" Value="{DynamicResource STRING_MENU_DIALOG_CANCEL}"/>
</Style>
<Style Selector="^ /template/ Button#PART_NoButton">
<Setter Property="Grid.Column" Value="1"></Setter>
<Setter Property="helpers:ClassHelper.Classes" Value="Danger"/>
<Setter Property="Content" Value="{DynamicResource STRING_MENU_DIALOG_NO}"/>
<Setter Property="Theme" Value="{DynamicResource SolidButton}"/>
</Style>
<Style Selector="^ /template/ Button#PART_YesButton">
<Setter Property="Grid.Column" Value="2"></Setter>
<Setter Property="helpers:ClassHelper.Classes" Value="Primary"/>
<Setter Property="Content" Value="{DynamicResource STRING_MENU_DIALOG_YES}"/>
<Setter Property="Theme" Value="{DynamicResource SolidButton}"/>
</Style>
<Style Selector="^ /template/ Button#PART_OKButton">
<Setter Property="Grid.Column" Value="3"></Setter>
<Setter Property="helpers:ClassHelper.Classes" Value="Primary"/>
<Setter Property="Content" Value="{DynamicResource STRING_MENU_DIALOG_OK}"/>
<Setter Property="Theme" Value="{DynamicResource SolidButton}"/>
</Style>
<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}}" />

View File

@@ -2,7 +2,7 @@
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:u="https://irihi.tech/ursa"
xmlns:u-semi="https://irihi.tech/ursa/themes/semi">
xmlns:helpers="clr-namespace:Irihi.Avalonia.Shared.Helpers;assembly=Irihi.Avalonia.Shared">
<!-- Add Resources Here -->
<ControlTheme x:Key="{x:Type u:EnumSelector}" TargetType="u:EnumSelector">
<Setter Property="HorizontalAlignment" Value="Left" />
@@ -10,7 +10,7 @@
<ControlTemplate TargetType="u:EnumSelector">
<ComboBox
Width="{TemplateBinding Width}"
u-semi:ClassHelper.ClassSource="{TemplateBinding}"
helpers:ClassHelper.ClassSource="{TemplateBinding}"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
VerticalAlignment="{TemplateBinding VerticalAlignment}"
Name="PART_ComboBox"

View File

@@ -1,7 +1,8 @@
<ResourceDictionary
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:u="https://irihi.tech/ursa">
xmlns:u="https://irihi.tech/ursa"
xmlns:helpers="clr-namespace:Irihi.Avalonia.Shared.Helpers;assembly=Irihi.Avalonia.Shared">
<!-- Add Resources Here -->
<ControlTheme x:Key="{x:Type u:MessageBoxWindow}" TargetType="u:MessageBoxWindow">
<Setter Property="Title" Value="{x:Null}" />
@@ -90,33 +91,45 @@
Orientation="Horizontal">
<Button
Name="{x:Static u:MessageBoxWindow.PART_CancelButton}"
Margin="8,0,0,0"
Classes="Tertiary"
Content="{DynamicResource STRING_MENU_DIALOG_CANCEL}" />
Margin="8,0,0,0" />
<Button
Name="{x:Static u:MessageBoxWindow.PART_NoButton}"
Margin="8,0,0,0"
Classes="Danger"
Content="{DynamicResource STRING_MENU_DIALOG_NO}"
Theme="{DynamicResource SolidButton}" />
Margin="8,0,0,0" />
<Button
Name="{x:Static u:MessageBoxWindow.PART_YesButton}"
Margin="8,0,0,0"
Classes="Primary"
Content="{DynamicResource STRING_MENU_DIALOG_YES}"
Theme="{DynamicResource SolidButton}" />
Margin="8,0,0,0" />
<Button
Name="{x:Static u:MessageBoxWindow.PART_OKButton}"
Margin="8,0,0,0"
Classes="Primary"
Content="{DynamicResource STRING_MENU_DIALOG_OK}"
Theme="{DynamicResource SolidButton}" />
Margin="8,0,0,0" />
</StackPanel>
</Grid>
</VisualLayerManager>
</Panel>
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ Button#PART_CancelButton">
<Setter Property="Grid.Column" Value="0"/>
<Setter Property="helpers:ClassHelper.Classes" Value="Tertiary"/>
<Setter Property="Content" Value="{DynamicResource STRING_MENU_DIALOG_CANCEL}"/>
</Style>
<Style Selector="^ /template/ Button#PART_NoButton">
<Setter Property="Grid.Column" Value="1"></Setter>
<Setter Property="helpers:ClassHelper.Classes" Value="Danger"/>
<Setter Property="Content" Value="{DynamicResource STRING_MENU_DIALOG_NO}"/>
<Setter Property="Theme" Value="{DynamicResource SolidButton}"/>
</Style>
<Style Selector="^ /template/ Button#PART_YesButton">
<Setter Property="Grid.Column" Value="2"></Setter>
<Setter Property="helpers:ClassHelper.Classes" Value="Primary"/>
<Setter Property="Content" Value="{DynamicResource STRING_MENU_DIALOG_YES}"/>
<Setter Property="Theme" Value="{DynamicResource SolidButton}"/>
</Style>
<Style Selector="^ /template/ Button#PART_OKButton">
<Setter Property="Grid.Column" Value="3"></Setter>
<Setter Property="helpers:ClassHelper.Classes" Value="Primary"/>
<Setter Property="Content" Value="{DynamicResource STRING_MENU_DIALOG_OK}"/>
<Setter Property="Theme" Value="{DynamicResource SolidButton}"/>
</Style>
<Style Selector="^[MessageIcon=None] /template/ PathIcon#PART_Icon">
<Setter Property="IsVisible" Value="False" />
</Style>
@@ -224,27 +237,16 @@
Orientation="Horizontal">
<Button
Name="{x:Static u:MessageBoxControl.PART_CancelButton}"
Margin="8,0,0,0"
Classes="Tertiary"
Content="{DynamicResource STRING_MENU_DIALOG_CANCEL}" />
Margin="8,0,0,0" />
<Button
Name="{x:Static u:MessageBoxControl.PART_NoButton}"
Margin="8,0,0,0"
Classes="Danger"
Content="{DynamicResource STRING_MENU_DIALOG_NO}"
Theme="{DynamicResource SolidButton}" />
Margin="8,0,0,0" />
<Button
Name="{x:Static u:MessageBoxControl.PART_YesButton}"
Margin="8,0,0,0"
Classes="Primary"
Content="{DynamicResource STRING_MENU_DIALOG_YES}"
Theme="{DynamicResource SolidButton}" />
Margin="8,0,0,0" />
<Button
Name="{x:Static u:MessageBoxControl.PART_OKButton}"
Margin="8,0,0,0"
Classes="Primary"
Content="{DynamicResource STRING_MENU_DIALOG_OK}"
Theme="{DynamicResource SolidButton}" />
Margin="8,0,0,0" />
</StackPanel>
</Grid>
</Border>
@@ -265,6 +267,29 @@
</MenuFlyout>
</Setter>
</Style>
<Style Selector="^ /template/ Button#PART_CancelButton">
<Setter Property="Grid.Column" Value="0"/>
<Setter Property="helpers:ClassHelper.Classes" Value="Tertiary"/>
<Setter Property="Content" Value="{DynamicResource STRING_MENU_DIALOG_CANCEL}"/>
</Style>
<Style Selector="^ /template/ Button#PART_NoButton">
<Setter Property="Grid.Column" Value="1"></Setter>
<Setter Property="helpers:ClassHelper.Classes" Value="Danger"/>
<Setter Property="Content" Value="{DynamicResource STRING_MENU_DIALOG_NO}"/>
<Setter Property="Theme" Value="{DynamicResource SolidButton}"/>
</Style>
<Style Selector="^ /template/ Button#PART_YesButton">
<Setter Property="Grid.Column" Value="2"></Setter>
<Setter Property="helpers:ClassHelper.Classes" Value="Primary"/>
<Setter Property="Content" Value="{DynamicResource STRING_MENU_DIALOG_YES}"/>
<Setter Property="Theme" Value="{DynamicResource SolidButton}"/>
</Style>
<Style Selector="^ /template/ Button#PART_OKButton">
<Setter Property="Grid.Column" Value="3"></Setter>
<Setter Property="helpers:ClassHelper.Classes" Value="Primary"/>
<Setter Property="Content" Value="{DynamicResource STRING_MENU_DIALOG_OK}"/>
<Setter Property="Theme" Value="{DynamicResource SolidButton}"/>
</Style>
<Style Selector="^[MessageIcon=None] /template/ PathIcon#PART_Icon">
<Setter Property="IsVisible" Value="False" />
</Style>

View File

@@ -1,7 +1,8 @@
<Styles xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:u="https://irihi.tech/ursa"
xmlns:theme="https://irihi.tech/ursa/themes/semi">
xmlns:theme="https://irihi.tech/ursa/themes/semi"
xmlns:helpers="clr-namespace:Irihi.Avalonia.Shared.Helpers;assembly=Irihi.Avalonia.Shared">
<Design.PreviewWith>
<Border Padding="20">
<!-- Add Controls for Previewer Here -->
@@ -16,7 +17,7 @@
</Style>
<Style Selector="u|PinCode.Small">
<Style Selector="^ u|PinCodeItem">
<Setter Property="theme:ClassHelper.Classes" Value="Small"></Setter>
<Setter Property="helpers:ClassHelper.Classes" Value="Small"></Setter>
<Style Selector="^:nth-last-child(n+2)">
<Setter Property="Margin" Value="0 0 6 0"></Setter>
</Style>
@@ -24,7 +25,7 @@
</Style>
<Style Selector="u|PinCode.Large">
<Style Selector="^ u|PinCodeItem">
<Setter Property="theme:ClassHelper.Classes" Value="Large"></Setter>
<Setter Property="helpers:ClassHelper.Classes" Value="Large"></Setter>
<Style Selector="^:nth-last-child(n+2)">
<Setter Property="Margin" Value="0 0 12 0"></Setter>
</Style>

View File

@@ -214,6 +214,11 @@ public static class Dialog
else
window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
}
if (!string.IsNullOrWhiteSpace(options.StyleClass))
{
var styles = options.StyleClass!.Split([' '], StringSplitOptions.RemoveEmptyEntries);
window.Classes.AddRange(styles);
}
}
/// <summary>
@@ -240,5 +245,10 @@ public static class Dialog
else
window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
}
if (!string.IsNullOrWhiteSpace(options.StyleClass))
{
var styles = options.StyleClass!.Split([' '], StringSplitOptions.RemoveEmptyEntries);
window.Classes.AddRange(styles);
}
}
}

View File

@@ -32,4 +32,5 @@ public class DialogOptions
public bool CanDragMove { get; set; } = true;
public bool CanResize { get; set; }
public string? StyleClass { get; set; }
}

View File

@@ -64,4 +64,6 @@ public class OverlayDialogOptions
public int? TopLevelHashCode { get; set; }
public bool CanResize { get; set; }
public string? StyleClass { get; set; }
}

View File

@@ -205,6 +205,11 @@ public static class OverlayDialog
control.IsCloseButtonVisible = options.IsCloseButtonVisible;
control.CanLightDismiss = options.CanLightDismiss;
control.CanResize = options.CanResize;
if (!string.IsNullOrWhiteSpace(options.StyleClass))
{
var styles = options.StyleClass!.Split([' '], StringSplitOptions.RemoveEmptyEntries);
control.Classes.AddRange(styles);
}
DialogControlBase.SetCanDragMove(control, options.CanDragMove);
}
@@ -231,6 +236,11 @@ public static class OverlayDialog
control.CanLightDismiss = options.CanLightDismiss;
control.IsCloseButtonVisible = options.IsCloseButtonVisible;
control.CanResize = options.CanResize;
if (!string.IsNullOrWhiteSpace(options.StyleClass))
{
var styles = options.StyleClass!.Split([' '], StringSplitOptions.RemoveEmptyEntries);
control.Classes.AddRange(styles);
}
DialogControlBase.SetCanDragMove(control, options.CanDragMove);
}

View File

@@ -217,6 +217,12 @@ public static class Drawer
if(options.MinHeight is not null) drawer.MinHeight = options.MinHeight.Value;
if(options.MaxHeight is not null) drawer.MaxHeight = options.MaxHeight.Value;
}
if (!string.IsNullOrWhiteSpace(options.StyleClass))
{
var styles = options.StyleClass!.Split([' '], StringSplitOptions.RemoveEmptyEntries);
drawer.Classes.AddRange(styles);
}
}
private static void ConfigureDefaultDrawer(DefaultDrawerControl drawer, DrawerOptions? options)
@@ -239,5 +245,10 @@ public static class Drawer
if(options.MinHeight is not null) drawer.MinHeight = options.MinHeight.Value;
if(options.MaxHeight is not null) drawer.MaxHeight = options.MaxHeight.Value;
}
if (!string.IsNullOrWhiteSpace(options.StyleClass))
{
var styles = options.StyleClass!.Split([' '], StringSplitOptions.RemoveEmptyEntries);
drawer.Classes.AddRange(styles);
}
}
}

View File

@@ -22,4 +22,6 @@ public class DrawerOptions
public int? TopLevelHashCode { get; set; }
public bool CanResize { get; set; }
public string? StyleClass { get; set; }
}

View File

@@ -11,7 +11,8 @@ public static class MessageBox
string message,
string? title = null,
MessageBoxIcon icon = MessageBoxIcon.None,
MessageBoxButton button = MessageBoxButton.OK)
MessageBoxButton button = MessageBoxButton.OK,
string? styleClass = null)
{
var messageWindow = new MessageBoxWindow(button)
{
@@ -19,6 +20,11 @@ public static class MessageBox
Title = title,
MessageIcon = icon
};
if (!string.IsNullOrWhiteSpace(styleClass))
{
var styles = styleClass!.Split([' '], StringSplitOptions.RemoveEmptyEntries);
messageWindow.Classes.AddRange(styles);
}
var lifetime = Application.Current?.ApplicationLifetime;
if (lifetime is not IClassicDesktopStyleApplicationLifetime classLifetime) return MessageBoxResult.None;
var main = classLifetime.MainWindow;
@@ -37,7 +43,8 @@ public static class MessageBox
string message,
string title,
MessageBoxIcon icon = MessageBoxIcon.None,
MessageBoxButton button = MessageBoxButton.OK)
MessageBoxButton button = MessageBoxButton.OK,
string? styleClass = null)
{
var messageWindow = new MessageBoxWindow(button)
{
@@ -45,6 +52,11 @@ public static class MessageBox
Title = title,
MessageIcon = icon
};
if (!string.IsNullOrWhiteSpace(styleClass))
{
var styles = styleClass!.Split([' '], StringSplitOptions.RemoveEmptyEntries);
messageWindow.Classes.AddRange(styles!);
}
var result = await messageWindow.ShowDialog<MessageBoxResult>(owner);
return result;
}
@@ -55,7 +67,8 @@ public static class MessageBox
string? hostId = null,
MessageBoxIcon icon = MessageBoxIcon.None,
MessageBoxButton button = MessageBoxButton.OK,
int? toplevelHashCode = null)
int? toplevelHashCode = null,
string? styleClass = null)
{
var host = OverlayDialogManager.GetHost(hostId, toplevelHashCode);
if (host is null) return MessageBoxResult.None;
@@ -67,6 +80,11 @@ public static class MessageBox
MessageIcon = icon,
[KeyboardNavigation.TabNavigationProperty] = KeyboardNavigationMode.Cycle
};
if (!string.IsNullOrWhiteSpace(styleClass))
{
var styles = styleClass!.Split([' '], StringSplitOptions.RemoveEmptyEntries);
messageControl.Classes.AddRange(styles!);
}
host.AddModalDialog(messageControl);
var result = await messageControl.ShowAsync<MessageBoxResult>();
return result;

View File

@@ -1,4 +1,5 @@
using System.Collections.Concurrent;
using System.Diagnostics;
namespace Ursa.Controls;
@@ -10,6 +11,7 @@ internal static class OverlayDialogManager
public static void RegisterHost(OverlayDialogHost host, string? id, int? hash)
{
Debug.WriteLine("Count: "+Hosts.Count);
Hosts.TryAdd(new HostKey(id, hash), host);
}

View File

@@ -15,7 +15,8 @@
<ItemGroup>
<PackageReference Include="Avalonia" Version="$(AvaloniaVersion)"/>
<PackageReference Include="Irihi.Avalonia.Shared" Version="0.1.9" />
<PackageReference Include="Irihi.Avalonia.Shared" Version="0.2.1" />
<PackageReference Include="Irihi.Avalonia.Shared.Contracts" Version="0.2.1" />
</ItemGroup>
<ItemGroup>

View File

@@ -0,0 +1,86 @@
using Avalonia.Controls;
using Avalonia.Headless.XUnit;
using Avalonia.Threading;
using Avalonia.VisualTree;
using Ursa.Controls;
using Xunit;
namespace HeadlessTest.Ursa.Controls.DialogTests.StyleClassTests;
public class StyleClassTests
{
[AvaloniaFact]
public void StyleClass_Changes_Button_Content()
{
var vm = new TestViewModel();
var ursaWindow = new TestWindow()
{
DataContext = vm,
};
ursaWindow.Show();
vm.InvokeDialog("Custom", ursaWindow.GetHashCode());
Dispatcher.UIThread.RunJobs();
var dialog = ursaWindow.GetVisualDescendants().OfType<DefaultDialogControl>().SingleOrDefault();
Assert.NotNull(dialog);
Assert.Contains("Custom", dialog.Classes);
var okButton = dialog.GetVisualDescendants().OfType<Button>().SingleOrDefault(a=>a.Name == DefaultDialogControl.PART_OKButton);
Assert.NotNull(okButton);
Assert.Equal("CUSTOM", okButton.Content);
var cancelButton = dialog.GetVisualDescendants().OfType<Button>().SingleOrDefault(a=>a.Name == DefaultDialogControl.PART_CancelButton);
Assert.NotNull(cancelButton);
Assert.Equal("取消", cancelButton.Content);
ursaWindow.Close();
Dispatcher.UIThread.RunJobs();
}
[AvaloniaFact]
public void StyleClass_Changes_Button_Content_With_Multiple_Classes()
{
var vm = new TestViewModel();
var ursaWindow = new TestWindow()
{
DataContext = vm,
};
ursaWindow.Show();
vm.InvokeDialog("Custom Custom2", ursaWindow.GetHashCode());
Dispatcher.UIThread.RunJobs();
var dialog = ursaWindow.GetVisualDescendants().OfType<DefaultDialogControl>().SingleOrDefault();
Assert.NotNull(dialog);
Assert.Contains("Custom", dialog.Classes);
Assert.Contains("Custom2", dialog.Classes);
var okButton = dialog.GetVisualDescendants().OfType<Button>().SingleOrDefault(a=>a.Name == DefaultDialogControl.PART_OKButton);
Assert.NotNull(okButton);
Assert.Equal("CUSTOM", okButton.Content);
Assert.Contains("Warning", okButton.Classes);
Assert.Contains("Small", okButton.Classes);
var cancelButton = dialog.GetVisualDescendants().OfType<Button>().SingleOrDefault(a=>a.Name == DefaultDialogControl.PART_CancelButton);
Assert.NotNull(cancelButton);
Assert.Equal("取消", cancelButton.Content);
ursaWindow.Close();
Dispatcher.UIThread.RunJobs();
}
[AvaloniaFact]
public void StyleClass_Changes_Button_Content_With_No_StyleClass()
{
var vm = new TestViewModel();
var ursaWindow = new TestWindow()
{
DataContext = vm,
};
ursaWindow.Show();
vm.InvokeDialog(null, ursaWindow.GetHashCode());
Dispatcher.UIThread.RunJobs();
var dialog = ursaWindow.GetVisualDescendants().OfType<DefaultDialogControl>().SingleOrDefault();
Assert.NotNull(dialog);
Assert.DoesNotContain("Custom", dialog.Classes);
var okButton = dialog.GetVisualDescendants().OfType<Button>().SingleOrDefault(a=>a.Name == DefaultDialogControl.PART_OKButton);
Assert.NotNull(okButton);
Assert.Equal("确认", okButton.Content);
var cancelButton = dialog.GetVisualDescendants().OfType<Button>().SingleOrDefault(a=>a.Name == DefaultDialogControl.PART_CancelButton);
Assert.NotNull(cancelButton);
Assert.Equal("取消", cancelButton.Content);
ursaWindow.Close();
Dispatcher.UIThread.RunJobs();
}
}

View File

@@ -0,0 +1,18 @@
using Avalonia.Controls;
using CommunityToolkit.Mvvm.ComponentModel;
using Ursa.Controls;
namespace HeadlessTest.Ursa.Controls.DialogTests.StyleClassTests;
public class TestViewModel: ObservableObject
{
public void InvokeDialog(string? classes, int? hash)
{
OverlayDialog.Show<TextBlock, string>("Hello World", options: new OverlayDialogOptions()
{
Buttons = DialogButton.OKCancel,
StyleClass = classes,
TopLevelHashCode = hash,
});
}
}

View File

@@ -0,0 +1,25 @@
<u:UrsaWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:u="https://irihi.tech/ursa"
xmlns:helpers="clr-namespace:Irihi.Avalonia.Shared.Helpers;assembly=Irihi.Avalonia.Shared"
mc:Ignorable="d" d:DesignWidth="800"
d:DesignHeight="450"
x:Class="HeadlessTest.Ursa.Controls.DialogTests.StyleClassTests.TestWindow"
Title="TestWindow">
<u:UrsaWindow.Styles>
<Style Selector="u|DefaultDialogControl.Custom">
<Style Selector="^ /template/ Button#PART_OKButton">
<Setter Property="Content" Value="CUSTOM"/>
</Style>
</Style>
<Style Selector="u|DefaultDialogControl.Custom2">
<Style Selector="^ /template/ Button#PART_OKButton">
<Setter Property="helpers:ClassHelper.Classes" Value="Warning Small" />
</Style>
</Style>
</u:UrsaWindow.Styles>
Welcome to Avalonia!
</u:UrsaWindow>

View File

@@ -0,0 +1,14 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Ursa.Controls;
namespace HeadlessTest.Ursa.Controls.DialogTests.StyleClassTests;
public partial class TestWindow : UrsaWindow
{
public TestWindow()
{
InitializeComponent();
}
}

View File

@@ -11,6 +11,7 @@
<ItemGroup>
<PackageReference Include="Avalonia.Headless.XUnit" Version="11.1.3" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.0" />
<PackageReference Include="coverlet.collector" Version="6.0.0"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/>
<PackageReference Include="Semi.Avalonia" Version="11.1.0.4" />