Merge branch 'main' into Coolkeke/main
This commit is contained in:
15
src/Ursa.PrismExtension/IUrsaDialogService.cs
Normal file
15
src/Ursa.PrismExtension/IUrsaDialogService.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using Avalonia.Controls;
|
||||
using Ursa.Controls;
|
||||
|
||||
namespace Ursa.PrismExtension;
|
||||
|
||||
public interface IUrsaDialogService
|
||||
{
|
||||
public void ShowCustom(string viewName, object? vm, Window? owner = null, DialogOptions? options = null);
|
||||
|
||||
public Task<DialogResult> ShowModal(string viewName, object? vm, Window? owner = null,
|
||||
DialogOptions? options = null);
|
||||
|
||||
public Task<TResult?> ShowCustomModal<TResult>(string viewName, object? vm, Window? owner = null,
|
||||
DialogOptions? options = null);
|
||||
}
|
||||
12
src/Ursa.PrismExtension/IUrsaDrawerService.cs
Normal file
12
src/Ursa.PrismExtension/IUrsaDrawerService.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using Ursa.Controls;
|
||||
using Ursa.Controls.Options;
|
||||
|
||||
namespace Ursa.PrismExtension;
|
||||
|
||||
public interface IUrsaDrawerService
|
||||
{
|
||||
public void Show(string viewName, object? vm, string? hostId = null, DrawerOptions? options = null);
|
||||
public void ShowCustom<TResult>(string viewName, object? vm, string? hostId = null, DrawerOptions? options = null);
|
||||
public Task<DialogResult> ShowModal(string viewName, object? vm, string? hostId = null, DrawerOptions? options = null);
|
||||
public Task<TResult?> ShowCustomModal<TResult>(string viewName, object? vm, string? hostId = null, DrawerOptions? options = null);
|
||||
}
|
||||
17
src/Ursa.PrismExtension/IUrsaOverlayDialogService.cs
Normal file
17
src/Ursa.PrismExtension/IUrsaOverlayDialogService.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using Avalonia.Controls;
|
||||
using Ursa.Controls;
|
||||
|
||||
namespace Ursa.PrismExtension;
|
||||
|
||||
public interface IUrsaOverlayDialogService
|
||||
{
|
||||
public void Show(string viewName, object? vm, string? hostId = null, OverlayDialogOptions? options = null);
|
||||
|
||||
public void ShowCustom(string viewName, object? vm, string? hostId = null, OverlayDialogOptions? options = null);
|
||||
|
||||
public Task<DialogResult> ShowModal(string viewName, object? vm, string? hostId = null,
|
||||
OverlayDialogOptions? options = null);
|
||||
|
||||
public Task<TResult?> ShowCustomModal<TResult>(string viewName, object? vm, string? hostId = null,
|
||||
OverlayDialogOptions? options = null);
|
||||
}
|
||||
21
src/Ursa.PrismExtension/Ursa.PrismExtension.csproj
Normal file
21
src/Ursa.PrismExtension/Ursa.PrismExtension.csproj
Normal file
@@ -0,0 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<Version>0.2.0-beta20240213</Version>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Authors>IRIHI Technology Co., Ltd.</Authors>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<PackageId>Irihi.Ursa.PrismExtension</PackageId>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ursa\Ursa.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Prism.Core" Version="8.1.97" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
26
src/Ursa.PrismExtension/UrsaDialogService.cs
Normal file
26
src/Ursa.PrismExtension/UrsaDialogService.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using Avalonia.Controls;
|
||||
using Prism.Ioc;
|
||||
using Ursa.Controls;
|
||||
|
||||
namespace Ursa.PrismExtension;
|
||||
|
||||
public class UrsaDialogService(IContainerExtension container) : IUrsaDialogService
|
||||
{
|
||||
public void ShowCustom(string viewName, object? vm, Window? owner = null, DialogOptions? options = null)
|
||||
{
|
||||
var v = container.Resolve<Control>(UrsaDialogServiceExtension.UrsaDialogViewPrefix + viewName);
|
||||
Dialog.ShowCustom(v, vm, owner, options);
|
||||
}
|
||||
|
||||
public Task<DialogResult> ShowModal(string viewName, object? vm, Window? owner = null, DialogOptions? options = null)
|
||||
{
|
||||
var v = container.Resolve<Control>(UrsaDialogServiceExtension.UrsaDialogViewPrefix + viewName);
|
||||
return Dialog.ShowModal(v, vm, owner, options);
|
||||
}
|
||||
|
||||
public Task<TResult?> ShowCustomModal<TResult>(string viewName, object? vm, Window? owner = null, DialogOptions? options = null)
|
||||
{
|
||||
var v = container.Resolve<Control>(UrsaDialogServiceExtension.UrsaDialogViewPrefix + viewName);
|
||||
return Dialog.ShowCustomModal<TResult>(v, vm, owner, options);
|
||||
}
|
||||
}
|
||||
21
src/Ursa.PrismExtension/UrsaDialogServiceExtension.cs
Normal file
21
src/Ursa.PrismExtension/UrsaDialogServiceExtension.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using Avalonia.Controls;
|
||||
using Prism.Ioc;
|
||||
|
||||
namespace Ursa.PrismExtension;
|
||||
|
||||
public static class UrsaDialogServiceExtension
|
||||
{
|
||||
internal const string UrsaDialogViewPrefix = "URSA_DIALOG_VIEW_";
|
||||
|
||||
public static void RegisterUrsaDialogService(this IContainerRegistry containerRegistry)
|
||||
{
|
||||
containerRegistry.RegisterSingleton<IUrsaDialogService, UrsaDialogService>();
|
||||
containerRegistry.RegisterSingleton<IUrsaOverlayDialogService, UrsaOverlayDialogService>();
|
||||
containerRegistry.RegisterSingleton<IUrsaDrawerService, UrsaDrawerService>();
|
||||
}
|
||||
|
||||
public static void RegisterUrsaDialogView<T>(this IContainerRegistry containerRegistry, string name) where T : Control
|
||||
{
|
||||
containerRegistry.Register<Control, T>(UrsaDialogViewPrefix+name);
|
||||
}
|
||||
}
|
||||
33
src/Ursa.PrismExtension/UrsaDrawerService.cs
Normal file
33
src/Ursa.PrismExtension/UrsaDrawerService.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using Avalonia.Controls;
|
||||
using Prism.Ioc;
|
||||
using Ursa.Controls;
|
||||
using Ursa.Controls.Options;
|
||||
|
||||
namespace Ursa.PrismExtension;
|
||||
|
||||
public class UrsaDrawerService(IContainerExtension container): IUrsaDrawerService
|
||||
{
|
||||
public void Show(string viewName, object? vm, string? hostId = null, DrawerOptions? options = null)
|
||||
{
|
||||
var v = container.Resolve<Control>(UrsaDialogServiceExtension.UrsaDialogViewPrefix + viewName);
|
||||
Drawer.Show(v, vm, hostId, options);
|
||||
}
|
||||
|
||||
public void ShowCustom<TResult>(string viewName, object? vm, string? hostId = null, DrawerOptions? options = null)
|
||||
{
|
||||
var v = container.Resolve<Control>(UrsaDialogServiceExtension.UrsaDialogViewPrefix + viewName);
|
||||
Drawer.ShowCustom(v, vm, hostId, options);
|
||||
}
|
||||
|
||||
public Task<DialogResult> ShowModal(string viewName, object? vm, string? hostId = null, DrawerOptions? options = null)
|
||||
{
|
||||
var v = container.Resolve<Control>(UrsaDialogServiceExtension.UrsaDialogViewPrefix + viewName);
|
||||
return Drawer.ShowModal(v, vm, hostId, options);
|
||||
}
|
||||
|
||||
public Task<TResult?> ShowCustomModal<TResult>(string viewName, object? vm, string? hostId = null, DrawerOptions? options = null)
|
||||
{
|
||||
var v = container.Resolve<Control>(UrsaDialogServiceExtension.UrsaDialogViewPrefix + viewName);
|
||||
return Drawer.ShowCustomModal<TResult?>(v, vm, hostId, options);
|
||||
}
|
||||
}
|
||||
32
src/Ursa.PrismExtension/UrsaOverlayDialogService.cs
Normal file
32
src/Ursa.PrismExtension/UrsaOverlayDialogService.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using Avalonia.Controls;
|
||||
using Prism.Ioc;
|
||||
using Ursa.Controls;
|
||||
|
||||
namespace Ursa.PrismExtension;
|
||||
|
||||
public class UrsaOverlayDialogService(IContainerExtension container): IUrsaOverlayDialogService
|
||||
{
|
||||
public void Show(string viewName, object? vm, string? hostId = null, OverlayDialogOptions? options = null)
|
||||
{
|
||||
var v = container.Resolve<Control>(UrsaDialogServiceExtension.UrsaDialogViewPrefix + viewName);
|
||||
OverlayDialog.Show(v, vm, hostId, options);
|
||||
}
|
||||
|
||||
public void ShowCustom(string viewName, object? vm, string? hostId = null, OverlayDialogOptions? options = null)
|
||||
{
|
||||
var v = container.Resolve<Control>(UrsaDialogServiceExtension.UrsaDialogViewPrefix + viewName);
|
||||
OverlayDialog.ShowCustom(v, vm, hostId, options);
|
||||
}
|
||||
|
||||
public Task<DialogResult> ShowModal(string viewName, object? vm, string? hostId = null, OverlayDialogOptions? options = null)
|
||||
{
|
||||
var v = container.Resolve<Control>(UrsaDialogServiceExtension.UrsaDialogViewPrefix + viewName);
|
||||
return OverlayDialog.ShowModal(v, vm, hostId, options);
|
||||
}
|
||||
|
||||
public Task<TResult?> ShowCustomModal<TResult>(string viewName, object? vm, string? hostId = null, OverlayDialogOptions? options = null)
|
||||
{
|
||||
var v = container.Resolve<Control>(UrsaDialogServiceExtension.UrsaDialogViewPrefix + viewName);
|
||||
return OverlayDialog.ShowCustomModal<TResult>(v, vm, hostId, options);
|
||||
}
|
||||
}
|
||||
4
src/Ursa.Themes.Semi/AssemblyInfo.cs
Normal file
4
src/Ursa.Themes.Semi/AssemblyInfo.cs
Normal file
@@ -0,0 +1,4 @@
|
||||
using Avalonia.Metadata;
|
||||
|
||||
[assembly:XmlnsPrefix("https://irihi.tech/ursa/themes/semi", "u-semi")]
|
||||
[assembly:XmlnsDefinition("https://irihi.tech/ursa/themes/semi", "Ursa.Themes.Semi")]
|
||||
24
src/Ursa.Themes.Semi/Behaviors/ClassHelper.cs
Normal file
24
src/Ursa.Themes.Semi/Behaviors/ClassHelper.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using Avalonia;
|
||||
|
||||
namespace Ursa.Themes.Semi;
|
||||
|
||||
internal class ClassHelper: AvaloniaObject
|
||||
{
|
||||
static ClassHelper()
|
||||
{
|
||||
ClassesProperty.Changed.AddClassHandler<StyledElement>(OnClassesChanged);
|
||||
}
|
||||
|
||||
public static readonly AttachedProperty<string> ClassesProperty =
|
||||
AvaloniaProperty.RegisterAttached<ClassHelper, StyledElement, string>("Classes");
|
||||
|
||||
public static void SetClasses(AvaloniaObject obj, string value) => obj.SetValue(ClassesProperty, value);
|
||||
public static string GetClasses(AvaloniaObject obj) => obj.GetValue(ClassesProperty);
|
||||
|
||||
private static void OnClassesChanged(StyledElement sender, AvaloniaPropertyChangedEventArgs value)
|
||||
{
|
||||
string classes = value.GetNewValue<string>();
|
||||
sender.Classes.Clear();
|
||||
sender.Classes.Add(classes);
|
||||
}
|
||||
}
|
||||
@@ -9,22 +9,23 @@
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:Badge}" TargetType="{x:Type u:Badge}">
|
||||
<!-- Set a very large corner radius to achieve pill look. -->
|
||||
<Setter Property="u:Badge.CornerRadius" Value="100" />
|
||||
<Setter Property="u:Badge.FontSize" Value="14" />
|
||||
<Setter Property="u:Badge.Background" Value="{DynamicResource BadgePrimaryBadgeBackground}" />
|
||||
<Setter Property="u:Badge.ClipToBounds" Value="False" />
|
||||
<Setter Property="u:Badge.HorizontalAlignment" Value="Center" />
|
||||
<Setter Property="u:Badge.VerticalAlignment" Value="Center" />
|
||||
<Setter Property="u:Badge.BorderThickness" Value="{DynamicResource BadgeBorderThickness}" />
|
||||
<Setter Property="u:Badge.UseLayoutRounding" Value="False" />
|
||||
<Setter Property="u:Badge.BorderBrush" Value="{DynamicResource BadgeBorderBrush}" />
|
||||
<Setter Property="u:Badge.Template">
|
||||
<Setter Property="CornerRadius" Value="{DynamicResource BadgeCornerRadius}" />
|
||||
<Setter Property="BadgeFontSize" Value="{DynamicResource BadgeFontSize}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource BadgeForeground}" />
|
||||
<Setter Property="Background" Value="{DynamicResource BadgePrimaryBadgeBackground}" />
|
||||
<Setter Property="ClipToBounds" Value="False" />
|
||||
<Setter Property="HorizontalAlignment" Value="Center" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="BorderThickness" Value="{DynamicResource BadgeBorderThickness}" />
|
||||
<Setter Property="UseLayoutRounding" Value="False" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource BadgeBorderBrush}" />
|
||||
<Setter Property="CornerPosition" Value="{DynamicResource BadgeCornerPosition}" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="{x:Type u:Badge}">
|
||||
<Grid
|
||||
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalAlignment}"
|
||||
ClipToBounds="False">
|
||||
|
||||
<ContentPresenter
|
||||
Name="{x:Static u:Badge.PART_ContentPresenter}"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
@@ -34,8 +35,8 @@
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}" />
|
||||
<Border
|
||||
Name="{x:Static u:Badge.PART_BadgeContainer}"
|
||||
MinWidth="{DynamicResource BadgeHeight}"
|
||||
MinHeight="{DynamicResource BadgeHeight}"
|
||||
MinWidth="{DynamicResource BadgeMinWidth}"
|
||||
MinHeight="{DynamicResource BadgeMinHeight}"
|
||||
Padding="{DynamicResource BadgePadding}"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
@@ -43,21 +44,21 @@
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
IsVisible="{Binding !!BadgeContent, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
IsVisible="{Binding !!Header, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
RenderTransformOrigin=".5,.5"
|
||||
Theme="{TemplateBinding BadgeTheme}"
|
||||
UseLayoutRounding="False">
|
||||
<ContentPresenter
|
||||
Name="{x:Static u:Badge.PART_BadgeContentPresenter}"
|
||||
Name="{x:Static u:Badge.PART_HeaderPresenter}"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Focusable="False"
|
||||
IsTabStop="False"
|
||||
TextElement.FontSize="{TemplateBinding FontSize}"
|
||||
TextElement.Foreground="{DynamicResource BadgeForeground}">
|
||||
TextElement.FontSize="{TemplateBinding BadgeFontSize}"
|
||||
TextElement.Foreground="{TemplateBinding Foreground}">
|
||||
<ContentPresenter.Content>
|
||||
<MultiBinding Converter="{StaticResource BadgeContentConverter}">
|
||||
<Binding Path="BadgeContent" RelativeSource="{RelativeSource TemplatedParent}" />
|
||||
<Binding Path="Header" RelativeSource="{RelativeSource TemplatedParent}" />
|
||||
<Binding Path="OverflowCount" RelativeSource="{RelativeSource TemplatedParent}" />
|
||||
</MultiBinding>
|
||||
</ContentPresenter.Content>
|
||||
@@ -83,7 +84,7 @@
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}" />
|
||||
<Border
|
||||
Name="{x:Static u:Badge.PART_BadgeContainer}"
|
||||
Width="{DynamicResource BadgeDotHeight}"
|
||||
Width="{DynamicResource BadgeDotWidth}"
|
||||
Height="{DynamicResource BadgeDotHeight}"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
@@ -91,7 +92,7 @@
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
IsVisible="{Binding !!BadgeContent, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
IsVisible="{Binding !!Header, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
RenderTransformOrigin=".5,.5" />
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
@@ -130,5 +131,56 @@
|
||||
<Style Selector="^.Danger">
|
||||
<Setter Property="u:Badge.Background" Value="{DynamicResource BadgeDangerBadgeBackground}" />
|
||||
</Style>
|
||||
<Style Selector="^.Success">
|
||||
<Setter Property="u:Badge.Background" Value="{DynamicResource BadgeSuccessBadgeBackground}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^.Light">
|
||||
<Style Selector="^.Primary">
|
||||
<Setter Property="u:Badge.Foreground" Value="{DynamicResource BadgeLightPrimaryBadgeForeground}" />
|
||||
<Setter Property="u:Badge.Background" Value="{DynamicResource BadgeLightPrimaryBadgeBackground}" />
|
||||
</Style>
|
||||
<Style Selector="^.Secondary">
|
||||
<Setter Property="u:Badge.Foreground" Value="{DynamicResource BadgeLightSecondaryBadgeForeground}" />
|
||||
<Setter Property="u:Badge.Background" Value="{DynamicResource BadgeLightSecondaryBadgeBackground}" />
|
||||
</Style>
|
||||
<Style Selector="^.Tertiary">
|
||||
<Setter Property="u:Badge.Foreground" Value="{DynamicResource BadgeLightTertiaryBadgeForeground}" />
|
||||
<Setter Property="u:Badge.Background" Value="{DynamicResource BadgeLightTertiaryBadgeBackground}" />
|
||||
</Style>
|
||||
<Style Selector="^.Warning">
|
||||
<Setter Property="u:Badge.Foreground" Value="{DynamicResource BadgeLightWarningBadgeForeground}" />
|
||||
<Setter Property="u:Badge.Background" Value="{DynamicResource BadgeLightWarningBadgeBackground}" />
|
||||
</Style>
|
||||
<Style Selector="^.Danger">
|
||||
<Setter Property="u:Badge.Foreground" Value="{DynamicResource BadgeLightDangerBadgeForeground}" />
|
||||
<Setter Property="u:Badge.Background" Value="{DynamicResource BadgeLightDangerBadgeBackground}" />
|
||||
</Style>
|
||||
<Style Selector="^.Success">
|
||||
<Setter Property="u:Badge.Foreground" Value="{DynamicResource BadgeLightSuccessBadgeForeground}" />
|
||||
<Setter Property="u:Badge.Background" Value="{DynamicResource BadgeLightSuccessBadgeBackground}" />
|
||||
</Style>
|
||||
</Style>
|
||||
<Style Selector="^.Inverted">
|
||||
<Setter Property="u:Badge.Background" Value="{DynamicResource BadgeInvertedBadgeBackground}" />
|
||||
<Style Selector="^.Primary">
|
||||
<Setter Property="u:Badge.Foreground" Value="{DynamicResource BadgeInvertedPrimaryBadgeForeground}" />
|
||||
</Style>
|
||||
<Style Selector="^.Secondary">
|
||||
<Setter Property="u:Badge.Foreground" Value="{DynamicResource BadgeInvertedSecondaryBadgeForeground}" />
|
||||
</Style>
|
||||
<Style Selector="^.Tertiary">
|
||||
<Setter Property="u:Badge.Foreground" Value="{DynamicResource BadgeInvertedTertiaryBadgeForeground}" />
|
||||
</Style>
|
||||
<Style Selector="^.Warning">
|
||||
<Setter Property="u:Badge.Foreground" Value="{DynamicResource BadgeInvertedWarningBadgeForeground}" />
|
||||
</Style>
|
||||
<Style Selector="^.Danger">
|
||||
<Setter Property="u:Badge.Foreground" Value="{DynamicResource BadgeInvertedDangerBadgeForeground}" />
|
||||
</Style>
|
||||
<Style Selector="^.Success">
|
||||
<Setter Property="u:Badge.Foreground" Value="{DynamicResource BadgeInvertedSuccessBadgeForeground}" />
|
||||
</Style>
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary>
|
||||
@@ -80,6 +80,19 @@
|
||||
<Setter Property="PathIcon.Foreground" Value="{DynamicResource BannerInformationBorderBrush}" />
|
||||
</Style>
|
||||
</Style>
|
||||
<Style Selector="^[Type=Success]">
|
||||
<Style Selector="^.Bordered /template/ Border#PART_Container">
|
||||
<Setter Property="Border.CornerRadius" Value="{DynamicResource BannerCornerRadius}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource BannerSuccessBorderBrush}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Border#PART_Container">
|
||||
<Setter Property="Background" Value="{DynamicResource BannerSuccessBackground}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ PathIcon#PART_BuildInIcon">
|
||||
<Setter Property="PathIcon.Data" Value="{DynamicResource BannerSuccessIconGeometry}" />
|
||||
<Setter Property="PathIcon.Foreground" Value="{DynamicResource BannerSuccessBorderBrush}" />
|
||||
</Style>
|
||||
</Style>
|
||||
<Style Selector="^[Type=Warning]">
|
||||
<Style Selector="^.Bordered /template/ Border#PART_Container">
|
||||
<Setter Property="Border.CornerRadius" Value="{DynamicResource BannerCornerRadius}" />
|
||||
@@ -106,18 +119,5 @@
|
||||
<Setter Property="PathIcon.Foreground" Value="{DynamicResource BannerErrorBorderBrush}" />
|
||||
</Style>
|
||||
</Style>
|
||||
<Style Selector="^[Type=Success]">
|
||||
<Style Selector="^.Bordered /template/ Border#PART_Container">
|
||||
<Setter Property="Border.CornerRadius" Value="{DynamicResource BannerCornerRadius}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource BannerSuccessBorderBrush}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Border#PART_Container">
|
||||
<Setter Property="Background" Value="{DynamicResource BannerSuccessBackground}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ PathIcon#PART_BuildInIcon">
|
||||
<Setter Property="PathIcon.Data" Value="{DynamicResource BannerSuccessIconGeometry}" />
|
||||
<Setter Property="PathIcon.Foreground" Value="{DynamicResource BannerSuccessBorderBrush}" />
|
||||
</Style>
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
FontWeight="{TemplateBinding FontWeight}"
|
||||
Foreground="{TemplateBinding Foreground}" />
|
||||
</Border>
|
||||
|
||||
27
src/Ursa.Themes.Semi/Controls/ControlClassesInput.axaml
Normal file
27
src/Ursa.Themes.Semi/Controls/ControlClassesInput.axaml
Normal file
@@ -0,0 +1,27 @@
|
||||
<ResourceDictionary
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:u="https://irihi.tech/ursa">
|
||||
<!-- Add Resources Here -->
|
||||
<ControlTheme x:Key="{x:Type u:ControlClassesInput}" TargetType="u:ControlClassesInput">
|
||||
<Setter Property="Width" Value="200" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:ControlClassesInput">
|
||||
<u:TagInput
|
||||
HorizontalAlignment="Stretch"
|
||||
AllowDuplicates="False"
|
||||
Separator="{TemplateBinding Separator}"
|
||||
Tags="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TargetClasses, Mode=TwoWay}" />
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<!--
|
||||
<Setter Property="ContextFlyout">
|
||||
<MenuFlyout>
|
||||
<MenuItem Header="Undo" Command="{Binding $parent[u:ControlClassesInput].UnDo}" />
|
||||
<MenuItem Header="Redo" Command="{Binding $parent[u:ControlClassesInput].Redo}" />
|
||||
<MenuItem Header="Clear" Command="{Binding $parent[u:ControlClassesInput].Clear}" />
|
||||
</MenuFlyout>
|
||||
</Setter>
|
||||
-->
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
716
src/Ursa.Themes.Semi/Controls/Dialog.axaml
Normal file
716
src/Ursa.Themes.Semi/Controls/Dialog.axaml
Normal file
@@ -0,0 +1,716 @@
|
||||
<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">
|
||||
|
||||
<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="CornerRadius" Value="12" />
|
||||
<Setter Property="Transitions">
|
||||
<Transitions>
|
||||
<TransformOperationsTransition Duration="0.2" Property="RenderTransform"/>
|
||||
</Transitions>
|
||||
</Setter>
|
||||
<Setter Property="RenderTransform" Value="scale(1.0)"></Setter>
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:CustomDialogControl">
|
||||
<Border
|
||||
Margin="8"
|
||||
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 CloseButton}" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^[IsClosed=True]">
|
||||
<Setter Property="RenderTransform" Value="scale(0.95)"/>
|
||||
</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.Icon>
|
||||
<PathIcon
|
||||
Width="12"
|
||||
Height="12"
|
||||
Data="{DynamicResource WindowCloseIconGlyph}" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</MenuFlyout>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style Selector="^:not(:modal) /template/ Panel#PART_TitleArea">
|
||||
<Setter Property="ContextFlyout">
|
||||
<MenuFlyout>
|
||||
<MenuItem
|
||||
Command="{Binding $parent[u:DialogControlBase].UpdateLayer}"
|
||||
CommandParameter="{x:Static u:DialogLayerChangeType.BringForward}"
|
||||
Header="{DynamicResource STRING_MENU_BRING_FORWARD}">
|
||||
<MenuItem.Icon>
|
||||
<PathIcon
|
||||
Width="12"
|
||||
Height="12"
|
||||
Data="{DynamicResource DialogArrangeBringForwardGlyph}" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
Command="{Binding $parent[u:DialogControlBase].UpdateLayer}"
|
||||
CommandParameter="{x:Static u:DialogLayerChangeType.BringToFront}"
|
||||
Header="{DynamicResource STRING_MENU_BRING_TO_FRONT}">
|
||||
<MenuItem.Icon>
|
||||
<PathIcon
|
||||
Width="12"
|
||||
Height="12"
|
||||
Data="{DynamicResource DialogArrangeBringToFrontGlyph}" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
Command="{Binding $parent[u:DialogControlBase].UpdateLayer}"
|
||||
CommandParameter="{x:Static u:DialogLayerChangeType.SendBackward}"
|
||||
Header="{DynamicResource STRING_MENU_SEND_BACKWARD}">
|
||||
<MenuItem.Icon>
|
||||
<PathIcon
|
||||
Width="12"
|
||||
Height="12"
|
||||
Data="{DynamicResource DialogArrangeSendBackwardGlyph}" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
Command="{Binding $parent[u:DialogControlBase].UpdateLayer}"
|
||||
CommandParameter="{x:Static u:DialogLayerChangeType.SendToBack}"
|
||||
Header="{DynamicResource STRING_MENU_SEND_TO_BACK}">
|
||||
<MenuItem.Icon>
|
||||
<PathIcon
|
||||
Width="12"
|
||||
Height="12"
|
||||
Data="{DynamicResource DialogArrangeSendToBackGlyph}" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
Command="{Binding $parent[u:DialogControlBase].Close}"
|
||||
Header="{DynamicResource STRING_MENU_DIALOG_CLOSE}">
|
||||
<MenuItem.Icon>
|
||||
<PathIcon
|
||||
Width="12"
|
||||
Height="12"
|
||||
Data="{DynamicResource WindowCloseIconGlyph}" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</MenuFlyout>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:DefaultDialogControl}" TargetType="u:DefaultDialogControl">
|
||||
<Setter Property="CornerRadius" Value="12" />
|
||||
<Setter Property="Transitions">
|
||||
<Transitions>
|
||||
<TransformOperationsTransition Duration="0.2" Property="RenderTransform"/>
|
||||
</Transitions>
|
||||
</Setter>
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:DefaultDialogControl">
|
||||
<Border
|
||||
Margin="10"
|
||||
Padding="0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
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"
|
||||
Grid.Row="1"
|
||||
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="Bold"
|
||||
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 CloseButton}" />
|
||||
</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>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^[IsClosed=True]">
|
||||
<Setter Property="RenderTransform" Value="scale(0.95)"/>
|
||||
</Style>
|
||||
<Style Selector="^[Mode=None]">
|
||||
<Style Selector="^ /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="False" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ TextBlock#PART_Title">
|
||||
<Setter Property="Margin" Value="24 24 0 0" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_OKButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Primary" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_YesButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Primary" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_NoButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Danger" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_CancelButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Tertiary" />
|
||||
</Style>
|
||||
</Style>
|
||||
<Style Selector="^[Mode=Info]">
|
||||
<Style Selector="^ /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
<Setter Property="Data" Value="{DynamicResource DialogInformationIconGlyph}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SemiBlue6}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_OKButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Primary" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_YesButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Primary" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_NoButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Danger" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_CancelButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Tertiary" />
|
||||
</Style>
|
||||
</Style>
|
||||
<Style Selector="^[Mode=Warning]">
|
||||
<Style Selector="^ /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
<Setter Property="Data" Value="{DynamicResource DialogWarningIconGlyph}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SemiOrange6}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_OKButton">
|
||||
<Setter Property="theme: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="Theme" Value="{DynamicResource SolidButton}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_NoButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Danger" />
|
||||
<Setter Property="Theme" Value="{DynamicResource SolidButton}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_CancelButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Tertiary" />
|
||||
</Style>
|
||||
</Style>
|
||||
<Style Selector="^[Mode=Error]">
|
||||
<Style Selector="^ /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
<Setter Property="Data" Value="{DynamicResource DialogErrorIconGlyph}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SemiRed6}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_OKButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Danger" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_YesButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Danger" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_NoButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Tertiary" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_CancelButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Tertiary" />
|
||||
</Style>
|
||||
</Style>
|
||||
<Style Selector="^[Mode=Question]">
|
||||
<Style Selector="^ /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
<Setter Property="Data" Value="{DynamicResource DialogQuestionIconGlyph}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SemiBlue6}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_OKButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Primary" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_YesButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Primary" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_NoButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Danger" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_CancelButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Tertiary" />
|
||||
</Style>
|
||||
</Style>
|
||||
<Style Selector="^[Mode=Success]">
|
||||
<Style Selector="^ /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
<Setter Property="Data" Value="{DynamicResource DialogSuccessIconGlyph}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SemiGreen6}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_OKButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Success" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_YesButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Success" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_NoButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Danger" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_CancelButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Tertiary" />
|
||||
</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.Icon>
|
||||
<PathIcon
|
||||
Width="12"
|
||||
Height="12"
|
||||
Data="{DynamicResource WindowCloseIconGlyph}" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</MenuFlyout>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style Selector="^:not(:modal) /template/ Panel#PART_TitleArea">
|
||||
<Setter Property="ContextFlyout">
|
||||
<MenuFlyout>
|
||||
<MenuItem
|
||||
Command="{Binding $parent[u:DialogControlBase].UpdateLayer}"
|
||||
CommandParameter="{x:Static u:DialogLayerChangeType.BringForward}"
|
||||
Header="{DynamicResource STRING_MENU_BRING_FORWARD}">
|
||||
<MenuItem.Icon>
|
||||
<PathIcon
|
||||
Width="12"
|
||||
Height="12"
|
||||
Data="{DynamicResource DialogArrangeBringForwardGlyph}" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
Command="{Binding $parent[u:DialogControlBase].UpdateLayer}"
|
||||
CommandParameter="{x:Static u:DialogLayerChangeType.BringToFront}"
|
||||
Header="{DynamicResource STRING_MENU_BRING_TO_FRONT}">
|
||||
<MenuItem.Icon>
|
||||
<PathIcon
|
||||
Width="12"
|
||||
Height="12"
|
||||
Data="{DynamicResource DialogArrangeBringToFrontGlyph}" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
Command="{Binding $parent[u:DialogControlBase].UpdateLayer}"
|
||||
CommandParameter="{x:Static u:DialogLayerChangeType.SendBackward}"
|
||||
Header="{DynamicResource STRING_MENU_SEND_BACKWARD}">
|
||||
<MenuItem.Icon>
|
||||
<PathIcon
|
||||
Width="12"
|
||||
Height="12"
|
||||
Data="{DynamicResource DialogArrangeSendBackwardGlyph}" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
Command="{Binding $parent[u:DialogControlBase].UpdateLayer}"
|
||||
CommandParameter="{x:Static u:DialogLayerChangeType.SendToBack}"
|
||||
Header="{DynamicResource STRING_MENU_SEND_TO_BACK}">
|
||||
<MenuItem.Icon>
|
||||
<PathIcon
|
||||
Width="12"
|
||||
Height="12"
|
||||
Data="{DynamicResource DialogArrangeSendToBackGlyph}" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
Command="{Binding $parent[u:DialogControlBase].Close}"
|
||||
CommandParameter="{x:Static u:DialogLayerChangeType.BringForward}"
|
||||
Header="{DynamicResource STRING_MENU_DIALOG_CLOSE}">
|
||||
<MenuItem.Icon>
|
||||
<PathIcon
|
||||
Width="12"
|
||||
Height="12"
|
||||
Data="{DynamicResource WindowCloseIconGlyph}" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</MenuFlyout>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:DialogWindow}" TargetType="u:DialogWindow">
|
||||
<Setter Property="Title" Value="{x:Null}" />
|
||||
<Setter Property="Background" Value="{DynamicResource BorderCardBackground}" />
|
||||
<Setter Property="TransparencyBackgroundFallback" Value="{DynamicResource WindowDefaultBackground}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource WindowDefaultForeground}" />
|
||||
<Setter Property="FontSize" Value="{DynamicResource DefaultFontSize}" />
|
||||
<Setter Property="FontFamily" Value="{DynamicResource DefaultFontFamily}" />
|
||||
<Setter Property="Padding" Value="48 24" />
|
||||
<Setter Property="SizeToContent" Value="WidthAndHeight" />
|
||||
<Setter Property="WindowStartupLocation" Value="CenterOwner" />
|
||||
<Setter Property="ExtendClientAreaTitleBarHeightHint" Value="1" />
|
||||
<Setter Property="ExtendClientAreaToDecorationsHint" Value="True" />
|
||||
<Setter Property="ExtendClientAreaChromeHints" Value="SystemChrome" />
|
||||
<Setter Property="SystemDecorations">
|
||||
<OnPlatform>
|
||||
<OnPlatform.Windows>
|
||||
<SystemDecorations>Full</SystemDecorations>
|
||||
</OnPlatform.Windows>
|
||||
<OnPlatform.Default>
|
||||
<SystemDecorations>BorderOnly</SystemDecorations>
|
||||
</OnPlatform.Default>
|
||||
</OnPlatform>
|
||||
</Setter>
|
||||
<Setter Property="CanResize" Value="False" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:DialogWindow">
|
||||
<Panel>
|
||||
<Border Name="PART_TransparencyFallback" IsHitTestVisible="False" />
|
||||
<Border Background="{TemplateBinding Background}" IsHitTestVisible="False" />
|
||||
<Panel Margin="{TemplateBinding WindowDecorationMargin}" Background="Transparent" />
|
||||
<VisualLayerManager>
|
||||
<Grid RowDefinitions="Auto, *">
|
||||
<ContentPresenter
|
||||
Grid.Row="0"
|
||||
Grid.RowSpan="2"
|
||||
Content="{TemplateBinding Content}" />
|
||||
<Grid Grid.Row="0" ColumnDefinitions="*, Auto">
|
||||
<Panel
|
||||
Name="{x:Static u:DialogWindow.PART_TitleArea}"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="2"
|
||||
Background="Transparent" />
|
||||
<TextBlock
|
||||
Grid.Column="0"
|
||||
Margin="24,24,0,0"
|
||||
FontSize="14"
|
||||
FontWeight="Bold"
|
||||
Text="{TemplateBinding Title}"
|
||||
TextTrimming="CharacterEllipsis"
|
||||
TextWrapping="NoWrap" />
|
||||
<Button
|
||||
Name="{x:Static u:MessageBoxWindow.PART_CloseButton}"
|
||||
Grid.Column="1"
|
||||
Margin="0,24,24,0"
|
||||
Theme="{DynamicResource CloseButton}" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</VisualLayerManager>
|
||||
</Panel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:DefaultDialogWindow}" TargetType="u:DefaultDialogWindow">
|
||||
<Setter Property="Title" Value="{x:Null}" />
|
||||
<Setter Property="Background" Value="{DynamicResource BorderCardBackground}" />
|
||||
<Setter Property="TransparencyBackgroundFallback" Value="{DynamicResource WindowDefaultBackground}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource WindowDefaultForeground}" />
|
||||
<Setter Property="FontSize" Value="{DynamicResource DefaultFontSize}" />
|
||||
<Setter Property="FontFamily" Value="{DynamicResource DefaultFontFamily}" />
|
||||
<Setter Property="Padding" Value="48 24" />
|
||||
<Setter Property="SizeToContent" Value="WidthAndHeight" />
|
||||
<Setter Property="WindowStartupLocation" Value="CenterOwner" />
|
||||
<Setter Property="ExtendClientAreaTitleBarHeightHint" Value="1" />
|
||||
<Setter Property="ExtendClientAreaToDecorationsHint" Value="True" />
|
||||
<Setter Property="ExtendClientAreaChromeHints" Value="SystemChrome" />
|
||||
<Setter Property="SystemDecorations">
|
||||
<OnPlatform>
|
||||
<OnPlatform.Windows>
|
||||
<SystemDecorations>Full</SystemDecorations>
|
||||
</OnPlatform.Windows>
|
||||
<OnPlatform.Default>
|
||||
<SystemDecorations>BorderOnly</SystemDecorations>
|
||||
</OnPlatform.Default>
|
||||
</OnPlatform>
|
||||
</Setter>
|
||||
<Setter Property="CanResize" Value="False" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:DefaultDialogWindow">
|
||||
<Panel>
|
||||
<Border Name="PART_TransparencyFallback" IsHitTestVisible="False" />
|
||||
<Border Background="{TemplateBinding Background}" IsHitTestVisible="False" />
|
||||
<Panel Margin="{TemplateBinding WindowDecorationMargin}" Background="Transparent" />
|
||||
<VisualLayerManager>
|
||||
<Grid RowDefinitions="Auto, *, Auto">
|
||||
<ContentPresenter
|
||||
Name="PART_ContentPresenter"
|
||||
Grid.Row="1"
|
||||
Margin="24,8"
|
||||
Content="{TemplateBinding Content}" />
|
||||
<Grid Grid.Row="0" ColumnDefinitions="Auto, *, Auto">
|
||||
<Panel
|
||||
Name="{x:Static u:DialogWindow.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="Bold"
|
||||
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 CloseButton}" />
|
||||
</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>
|
||||
</VisualLayerManager>
|
||||
</Panel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^[Mode=None]">
|
||||
<Style Selector="^ /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="False" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ TextBlock#PART_Title">
|
||||
<Setter Property="Margin" Value="24 24 0 0" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_OKButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Primary" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_YesButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Primary" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_NoButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Danger" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_CancelButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Tertiary" />
|
||||
</Style>
|
||||
</Style>
|
||||
<Style Selector="^[Mode=Info]">
|
||||
<Style Selector="^ /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
<Setter Property="Data" Value="{DynamicResource DialogInformationIconGlyph}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SemiBlue6}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_OKButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Primary" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_YesButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Primary" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_NoButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Danger" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_CancelButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Tertiary" />
|
||||
</Style>
|
||||
</Style>
|
||||
<Style Selector="^[Mode=Warning]">
|
||||
<Style Selector="^ /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
<Setter Property="Data" Value="{DynamicResource DialogWarningIconGlyph}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SemiOrange6}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_OKButton">
|
||||
<Setter Property="theme: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="Theme" Value="{DynamicResource SolidButton}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_NoButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Danger" />
|
||||
<Setter Property="Theme" Value="{DynamicResource SolidButton}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_CancelButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Tertiary" />
|
||||
</Style>
|
||||
</Style>
|
||||
<Style Selector="^[Mode=Error]">
|
||||
<Style Selector="^ /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
<Setter Property="Data" Value="{DynamicResource DialogErrorIconGlyph}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SemiRed6}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_OKButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Danger" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_YesButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Danger" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_NoButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Tertiary" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_CancelButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Tertiary" />
|
||||
</Style>
|
||||
</Style>
|
||||
<Style Selector="^[Mode=Question]">
|
||||
<Style Selector="^ /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
<Setter Property="Data" Value="{DynamicResource DialogQuestionIconGlyph}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SemiBlue6}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_OKButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Primary" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_YesButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Primary" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_NoButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Danger" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_CancelButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Tertiary" />
|
||||
</Style>
|
||||
</Style>
|
||||
<Style Selector="^[Mode=Success]">
|
||||
<Style Selector="^ /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
<Setter Property="Data" Value="{DynamicResource DialogSuccessIconGlyph}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SemiGreen6}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_OKButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Success" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_YesButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Success" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_NoButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Danger" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_CancelButton">
|
||||
<Setter Property="theme:ClassHelper.Classes" Value="Tertiary" />
|
||||
</Style>
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
42
src/Ursa.Themes.Semi/Controls/DialogShared.axaml
Normal file
42
src/Ursa.Themes.Semi/Controls/DialogShared.axaml
Normal file
@@ -0,0 +1,42 @@
|
||||
<ResourceDictionary xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<!-- Add Resources Here -->
|
||||
|
||||
<ControlTheme x:Key="CloseButton" TargetType="Button">
|
||||
<Setter Property="CornerRadius" Value="6" />
|
||||
<Setter Property="Margin" Value="0, 4" />
|
||||
<Setter Property="Padding" Value="4" />
|
||||
<Setter Property="Height" Value="28" />
|
||||
<Setter Property="Width" Value="28" />
|
||||
<Setter Property="Cursor" Value="Hand" />
|
||||
<Setter Property="VerticalAlignment" Value="Stretch" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border
|
||||
Name="PART_Border"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
Background="Transparent"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<PathIcon
|
||||
Width="12"
|
||||
Height="12"
|
||||
Data="{DynamicResource WindowCloseIconGlyph}"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
||||
<Style Selector="^:pointerover /template/ Border">
|
||||
<Setter Property="Background" Value="{DynamicResource CaptionButtonClosePointeroverBackground}" />
|
||||
</Style>
|
||||
<Style Selector="^:pointerover /template/ PathIcon">
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:pressed /template/ Border">
|
||||
<Setter Property="Background" Value="{DynamicResource CaptionButtonClosePressedBackground}" />
|
||||
</Style>
|
||||
<Style Selector="^:pressed /template/ PathIcon">
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
|
||||
</ResourceDictionary>
|
||||
16
src/Ursa.Themes.Semi/Controls/DisableContainer.axaml
Normal file
16
src/Ursa.Themes.Semi/Controls/DisableContainer.axaml
Normal file
@@ -0,0 +1,16 @@
|
||||
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:u="https://irihi.tech/ursa"
|
||||
xmlns:shapes="clr-namespace:Ursa.Controls.Shapes;assembly=Ursa">
|
||||
<!-- Add Resources Here -->
|
||||
<ControlTheme TargetType="u:DisableContainer" x:Key="{x:Type u:DisableContainer}">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:DisableContainer">
|
||||
<Panel>
|
||||
<ContentPresenter Content="{TemplateBinding Content}"></ContentPresenter>
|
||||
<shapes:PureRectangle Background="Transparent" IsVisible="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content.IsEnabled, Converter={x:Static BoolConverters.Not}}" Cursor="No" ToolTip.Tip="{TemplateBinding DisabledTip}"/>
|
||||
</Panel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
167
src/Ursa.Themes.Semi/Controls/Drawer.axaml
Normal file
167
src/Ursa.Themes.Semi/Controls/Drawer.axaml
Normal file
@@ -0,0 +1,167 @@
|
||||
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:u="https://irihi.tech/ursa">
|
||||
<ControlTheme TargetType="u:CustomDrawerControl" x:Key="{x:Type u:CustomDrawerControl}">
|
||||
<Setter Property="VerticalAlignment" Value="Stretch"></Setter>
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch"></Setter>
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:CustomDrawerControl">
|
||||
<Border Name="PART_Root"
|
||||
Margin="8 -1 -1 -1"
|
||||
Padding="0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Classes="Shadow"
|
||||
ClipToBounds="False"
|
||||
CornerRadius="12 0 0 12"
|
||||
BorderThickness="1 0 0 0"
|
||||
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 CloseButton}" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^[Position=Right] /template/ Border#PART_Root">
|
||||
<Setter Property="Margin" Value="8 0 0 0" />
|
||||
<Setter Property="CornerRadius" Value="12 0 0 12" />
|
||||
<Setter Property="BorderThickness" Value="1 0 0 0" />
|
||||
</Style>
|
||||
<Style Selector="^[Position=Left] /template/ Border#PART_Root">
|
||||
<Setter Property="Margin" Value="0 0 8 0" />
|
||||
<Setter Property="CornerRadius" Value="0 12 12 0" />
|
||||
<Setter Property="BorderThickness" Value="0 0 1 0" />
|
||||
</Style>
|
||||
<Style Selector="^[Position=Top] /template/ Border#PART_Root">
|
||||
<Setter Property="Margin" Value="0 0 0 8" />
|
||||
<Setter Property="CornerRadius" Value="0 0 12 12" />
|
||||
<Setter Property="BorderThickness" Value="0 0 0 1" />
|
||||
</Style>
|
||||
<Style Selector="^[Position=Bottom] /template/ Border#PART_Root">
|
||||
<Setter Property="Margin" Value="0 8 0 0" />
|
||||
<Setter Property="CornerRadius" Value="12 12 0 0" />
|
||||
<Setter Property="BorderThickness" Value="0 1 0 0" />
|
||||
</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="Template">
|
||||
<ControlTemplate TargetType="u:DefaultDrawerControl">
|
||||
<Border Name="PART_Root"
|
||||
Margin="8 -1 -1 -1"
|
||||
Padding="0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Classes="Shadow"
|
||||
ClipToBounds="False"
|
||||
CornerRadius="12 0 0 12"
|
||||
BorderThickness="1 0 0 0"
|
||||
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"
|
||||
Grid.Row="1"
|
||||
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="Bold"
|
||||
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 CloseButton}" />
|
||||
</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>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^[Position=Right] /template/ Border#PART_Root">
|
||||
<Setter Property="Margin" Value="8 0 0 0" />
|
||||
<Setter Property="CornerRadius" Value="12 0 0 12" />
|
||||
<Setter Property="BorderThickness" Value="1 0 0 0" />
|
||||
</Style>
|
||||
<Style Selector="^[Position=Left] /template/ Border#PART_Root">
|
||||
<Setter Property="Margin" Value="0 0 8 0" />
|
||||
<Setter Property="CornerRadius" Value="0 12 12 0" />
|
||||
<Setter Property="BorderThickness" Value="0 0 1 0" />
|
||||
</Style>
|
||||
<Style Selector="^[Position=Top] /template/ Border#PART_Root">
|
||||
<Setter Property="Margin" Value="0 0 0 8" />
|
||||
<Setter Property="CornerRadius" Value="0 0 12 12" />
|
||||
<Setter Property="BorderThickness" Value="0 0 0 1" />
|
||||
</Style>
|
||||
<Style Selector="^[Position=Bottom] /template/ Border#PART_Root">
|
||||
<Setter Property="Margin" Value="0 8 0 0" />
|
||||
<Setter Property="CornerRadius" Value="12 12 0 0" />
|
||||
<Setter Property="BorderThickness" Value="0 1 0 0" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
33
src/Ursa.Themes.Semi/Controls/EnumSelector.axaml
Normal file
33
src/Ursa.Themes.Semi/Controls/EnumSelector.axaml
Normal file
@@ -0,0 +1,33 @@
|
||||
<ResourceDictionary
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:u="https://irihi.tech/ursa">
|
||||
<!-- Add Resources Here -->
|
||||
<ControlTheme x:Key="{x:Type u:EnumSelector}" TargetType="u:EnumSelector">
|
||||
<Setter Property="Width" Value="100" />
|
||||
<Setter Property="HorizontalAlignment" Value="Left"></Setter>
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:EnumSelector">
|
||||
<ComboBox
|
||||
Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Bounds.Width}"
|
||||
Name="PART_ComboBox"
|
||||
ItemsSource="{TemplateBinding Values}"
|
||||
SelectedItem="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SelectedValue, Mode=TwoWay}" />
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^[DisplayDescription=True] /template/ ComboBox">
|
||||
<Setter Property="ItemTemplate">
|
||||
<DataTemplate x:DataType="u:EnumItemTuple">
|
||||
<TextBlock Text="{Binding DisplayName}"></TextBlock>
|
||||
</DataTemplate>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style Selector="^[DisplayDescription=False] /template/ ComboBox">
|
||||
<Setter Property="ItemTemplate">
|
||||
<DataTemplate x:DataType="u:EnumItemTuple">
|
||||
<TextBlock Text="{Binding Value}"></TextBlock>
|
||||
</DataTemplate>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
97
src/Ursa.Themes.Semi/Controls/Form.axaml
Normal file
97
src/Ursa.Themes.Semi/Controls/Form.axaml
Normal file
@@ -0,0 +1,97 @@
|
||||
<ResourceDictionary
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:u="https://irihi.tech/ursa">
|
||||
<!-- Add Resources Here -->
|
||||
<ControlTheme x:Key="{x:Type u:Form}" TargetType="u:Form">
|
||||
<Setter Property="Grid.IsSharedSizeScope" Value="False" />
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:Form">
|
||||
<DataValidationErrors>
|
||||
<ItemsPresenter ItemsPanel="{TemplateBinding ItemsPanel}" />
|
||||
</DataValidationErrors>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^:fixed-width">
|
||||
<Setter Property="Grid.IsSharedSizeScope" Value="True" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:FormGroup}" TargetType="u:FormGroup">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:FormGroup">
|
||||
<StackPanel Margin="0 28 0 0">
|
||||
<ContentPresenter Content="{TemplateBinding Header}" FontWeight="Bold" FontSize="18" />
|
||||
<Rectangle
|
||||
Height="1"
|
||||
Margin="0,8"
|
||||
HorizontalAlignment="Stretch"
|
||||
Fill="{DynamicResource SemiColorBorder}" />
|
||||
<ItemsPresenter ItemsPanel="{TemplateBinding ItemsPanel}" />
|
||||
</StackPanel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:FormItem}" TargetType="u:FormItem">
|
||||
<Setter Property="Margin" Value="0 8" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:FormItem">
|
||||
<StackPanel>
|
||||
<StackPanel
|
||||
Name="PART_LabelPanel"
|
||||
Margin="0,0,0,4"
|
||||
HorizontalAlignment="{TemplateBinding LabelAlignment}"
|
||||
Orientation="Horizontal">
|
||||
<ContentPresenter Content="{TemplateBinding Label}" FontWeight="Bold" />
|
||||
<TextBlock
|
||||
Foreground="{DynamicResource SemiRed6}"
|
||||
IsVisible="{TemplateBinding IsRequired}"
|
||||
Text="*" />
|
||||
</StackPanel>
|
||||
<ContentPresenter Content="{TemplateBinding Content}" />
|
||||
</StackPanel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^:not(:no-label):horizontal">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:FormItem">
|
||||
<Grid RowDefinitions="*, *">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Label" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Border
|
||||
Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
Width="{TemplateBinding LabelWidth}">
|
||||
<StackPanel
|
||||
Name="PART_LabelPanel"
|
||||
Margin="8,8,8,0"
|
||||
HorizontalAlignment="{TemplateBinding LabelAlignment}"
|
||||
Orientation="Horizontal">
|
||||
<ContentPresenter Content="{TemplateBinding Label}" FontWeight="Bold" />
|
||||
<TextBlock
|
||||
Foreground="{DynamicResource SemiRed6}"
|
||||
IsVisible="{TemplateBinding IsRequired}"
|
||||
Text="*" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<ContentPresenter
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Content="{TemplateBinding Content}" />
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style Selector="^:no-label">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:FormItem">
|
||||
<ContentPresenter Content="{TemplateBinding Content}" />
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
287
src/Ursa.Themes.Semi/Controls/IconButton.axaml
Normal file
287
src/Ursa.Themes.Semi/Controls/IconButton.axaml
Normal file
@@ -0,0 +1,287 @@
|
||||
<ResourceDictionary
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:converters="clr-namespace:Ursa.Themes.Semi.Converters"
|
||||
xmlns:u="https://irihi.tech/ursa">
|
||||
<!-- Add Resources Here -->
|
||||
<converters:BooleansToOpacityConverter x:Key="OpacityConverter" />
|
||||
<ControlTheme x:Key="{x:Type u:IconButton}" TargetType="u:IconButton">
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonDefaultBackground}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonDefaultPrimaryForeground}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonDefaultBorderBrush}" />
|
||||
<Setter Property="CornerRadius" Value="{DynamicResource ButtonCornerRadius}" />
|
||||
<Setter Property="BorderThickness" Value="{DynamicResource ButtonBorderThickness}" />
|
||||
<Setter Property="Padding" Value="{DynamicResource ButtonDefaultPadding}" />
|
||||
<Setter Property="RenderTransform" Value="none" />
|
||||
<Setter Property="FontSize" Value="{DynamicResource ButtonDefaultFontSize}" />
|
||||
<Setter Property="FontWeight" Value="{DynamicResource ButtonDefaultFontWeight}" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Center" />
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
<Setter Property="MinHeight" Value="12" />
|
||||
<Setter Property="Cursor" Value="Hand" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:IconButton">
|
||||
<Border
|
||||
Padding="{TemplateBinding Padding}"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
TextElement.FontSize="{TemplateBinding FontSize}"
|
||||
TextElement.FontWeight="{TemplateBinding FontWeight}"
|
||||
UseLayoutRounding="False">
|
||||
<Grid
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
ColumnDefinitions="Auto, Auto"
|
||||
RowDefinitions="Auto, Auto">
|
||||
<Panel
|
||||
Name="PART_IconRoot"
|
||||
Grid.Column="0">
|
||||
<Panel.IsVisible>
|
||||
<MultiBinding Converter="{x:Static BoolConverters.Or}">
|
||||
<Binding Path="IsLoading" RelativeSource="{RelativeSource TemplatedParent}" />
|
||||
<Binding
|
||||
Converter="{x:Static ObjectConverters.IsNotNull}"
|
||||
Path="Icon"
|
||||
RelativeSource="{RelativeSource TemplatedParent}" />
|
||||
</MultiBinding>
|
||||
</Panel.IsVisible>
|
||||
<ContentPresenter
|
||||
Content="{TemplateBinding Icon}"
|
||||
ContentTemplate="{TemplateBinding IconTemplate}"
|
||||
Opacity="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=!IsLoading, Converter={StaticResource OpacityConverter}}" />
|
||||
<u:LoadingIcon
|
||||
Classes="Small"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
IsVisible="{TemplateBinding IsLoading}" />
|
||||
</Panel>
|
||||
<ContentPresenter
|
||||
Name="PART_ContentPresenter"
|
||||
Grid.Column="1"
|
||||
Margin="8 0 0 0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Content="{TemplateBinding Content}" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
||||
<Style Selector="^:pressed">
|
||||
<Setter Property="RenderTransform" Value="scale(0.98)" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^.Primary">
|
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonDefaultPrimaryForeground}" />
|
||||
</Style>
|
||||
<Style Selector="^.Secondary">
|
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonDefaultSecondaryForeground}" />
|
||||
</Style>
|
||||
<Style Selector="^.Tertiary">
|
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonDefaultTertiaryForeground}" />
|
||||
</Style>
|
||||
<Style Selector="^.Success">
|
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonDefaultSuccessForeground}" />
|
||||
</Style>
|
||||
<Style Selector="^.Warning">
|
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonDefaultWarningForeground}" />
|
||||
</Style>
|
||||
<Style Selector="^.Danger">
|
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonDefaultDangerForeground}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:pointerover">
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonDefaultPointeroverBorderBrush}" />
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonDefaultPointeroverBackground}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:pressed">
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonDefaultPressedBorderBrush}" />
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonDefaultPressedBackground}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:disabled">
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonDefaultDisabledBorderBrush}" />
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonDefaultDisabledBackground}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonDefaultDisabledForeground}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:empty[IsLoading=False] /template/ ContentPresenter#PART_ContentPresenter">
|
||||
<Setter Property="Margin" Value="0"></Setter>
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:right">
|
||||
<Style Selector="^ /template/ Panel#PART_IconRoot">
|
||||
<Setter Property="Grid.Column" Value="1" />
|
||||
<Setter Property="Grid.Row" Value="0" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
|
||||
<Setter Property="Grid.Column" Value="0" />
|
||||
<Setter Property="Grid.Row" Value="0" />
|
||||
<Setter Property="Margin" Value="0 0 8 0" />
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:left">
|
||||
<Style Selector="^ /template/ Panel#PART_IconRoot">
|
||||
<Setter Property="Grid.Column" Value="0" />
|
||||
<Setter Property="Grid.Row" Value="0" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
|
||||
<Setter Property="Grid.Column" Value="1" />
|
||||
<Setter Property="Grid.Row" Value="0" />
|
||||
<Setter Property="Margin" Value="8 0 0 0" />
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:top">
|
||||
<Style Selector="^ /template/ Panel#PART_IconRoot">
|
||||
<Setter Property="Grid.Column" Value="0" />
|
||||
<Setter Property="Grid.Row" Value="0" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
|
||||
<Setter Property="Grid.Column" Value="0" />
|
||||
<Setter Property="Grid.Row" Value="1" />
|
||||
<Setter Property="Margin" Value="0 4 0 0" />
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:bottom">
|
||||
<Style Selector="^ /template/ Panel#PART_IconRoot">
|
||||
<Setter Property="Grid.Column" Value="0" />
|
||||
<Setter Property="Grid.Row" Value="1" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
|
||||
<Setter Property="Grid.Column" Value="0" />
|
||||
<Setter Property="Grid.Row" Value="0" />
|
||||
<Setter Property="Margin" Value="0 0 0 4" />
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
<Style Selector="^.Large">
|
||||
<Setter Property="Padding" Value="{DynamicResource ButtonLargePadding}" />
|
||||
</Style>
|
||||
<Style Selector="^.Small">
|
||||
<Setter Property="Padding" Value="{DynamicResource ButtonSmallPadding}" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme
|
||||
x:Key="SolidIconButton"
|
||||
BasedOn="{StaticResource {x:Type u:IconButton}}"
|
||||
TargetType="u:IconButton">
|
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonSolidForeground}" />
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonSolidPrimaryBackground}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonSolidPrimaryBorderBrush}" />
|
||||
|
||||
<Style Selector="^:pointerover">
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonSolidPrimaryPointeroverBackground}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonSolidPrimaryPointeroverBorderBrush}" />
|
||||
</Style>
|
||||
<Style Selector="^:pressed">
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonSolidPrimaryPressedBackground}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonSolidPrimaryPressedBorderBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^.Primary">
|
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonSolidForeground}" />
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonSolidPrimaryBackground}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonSolidPrimaryBorderBrush}" />
|
||||
<Style Selector="^:pointerover">
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonSolidPrimaryPointeroverBackground}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonSolidPrimaryPointeroverBorderBrush}" />
|
||||
</Style>
|
||||
<Style Selector="^:pressed">
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonSolidPrimaryPressedBackground}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonSolidPrimaryPressedBorderBrush}" />
|
||||
</Style>
|
||||
</Style>
|
||||
<Style Selector="^.Secondary">
|
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonSolidForeground}" />
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonSolidSecondaryBackground}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonSolidSecondaryBorderBrush}" />
|
||||
<Style Selector="^:pointerover">
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonSolidSecondaryPointeroverBackground}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonSolidSecondaryPointeroverBorderBrush}" />
|
||||
</Style>
|
||||
<Style Selector="^:pressed">
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonSolidSecondaryPressedBackground}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonSolidSecondaryPressedBorderBrush}" />
|
||||
</Style>
|
||||
</Style>
|
||||
<Style Selector="^.Tertiary">
|
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonSolidForeground}" />
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonSolidTertiaryBackground}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonSolidTertiaryBorderBrush}" />
|
||||
<Style Selector="^:pointerover">
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonSolidTertiaryPointeroverBackground}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonSolidTertiaryPointeroverBorderBrush}" />
|
||||
</Style>
|
||||
<Style Selector="^:pressed">
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonSolidTertiaryPressedBackground}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonSolidTertiaryPressedBorderBrush}" />
|
||||
</Style>
|
||||
</Style>
|
||||
<Style Selector="^.Success">
|
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonSolidForeground}" />
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonSolidSuccessBackground}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonSolidSuccessBorderBrush}" />
|
||||
<Style Selector="^:pointerover">
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonSolidSuccessPointeroverBackground}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonSolidSuccessPointeroverBorderBrush}" />
|
||||
</Style>
|
||||
<Style Selector="^:pressed">
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonSolidSuccessPressedBackground}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonSolidSuccessPressedBorderBrush}" />
|
||||
</Style>
|
||||
</Style>
|
||||
<Style Selector="^.Warning">
|
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonSolidForeground}" />
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonSolidWarningBackground}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonSolidWarningBorderBrush}" />
|
||||
<Style Selector="^:pointerover">
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonSolidWarningPointeroverBackground}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonSolidWarningPointeroverBorderBrush}" />
|
||||
</Style>
|
||||
<Style Selector="^:pressed">
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonSolidWarningPressedBackground}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonSolidWarningPressedBorderBrush}" />
|
||||
</Style>
|
||||
</Style>
|
||||
<Style Selector="^.Danger">
|
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonSolidForeground}" />
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonSolidDangerBackground}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonSolidDangerBorderBrush}" />
|
||||
<Style Selector="^:pointerover">
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonSolidDangerPointeroverBackground}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonSolidDangerPointeroverBorderBrush}" />
|
||||
</Style>
|
||||
<Style Selector="^:pressed">
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonSolidDangerPressedBackground}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonSolidDangerPressedBorderBrush}" />
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:disabled">
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonDefaultDisabledBorderBrush}" />
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonDefaultDisabledBackground}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonDefaultDisabledForeground}" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme
|
||||
x:Key="BorderlessIconButton"
|
||||
BasedOn="{StaticResource {x:Type u:IconButton}}"
|
||||
TargetType="u:IconButton">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderBrush" Value="Transparent" />
|
||||
<Style Selector="^:disabled">
|
||||
<Setter Property="BorderBrush" Value="Transparent" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonDefaultDisabledForeground}" />
|
||||
</Style>
|
||||
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
32
src/Ursa.Themes.Semi/Controls/ImageViewer.axaml
Normal file
32
src/Ursa.Themes.Semi/Controls/ImageViewer.axaml
Normal file
@@ -0,0 +1,32 @@
|
||||
<ResourceDictionary
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:u="https://irihi.tech/ursa">
|
||||
<!-- Add Resources Here -->
|
||||
<ControlTheme x:Key="{x:Type u:ImageViewer}" TargetType="u:ImageViewer">
|
||||
<Setter Property="Background" Value="LightGray" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="{x:Type u:ImageViewer}">
|
||||
<VisualLayerManager Name="{x:Static u:ImageViewer.PART_Layer}">
|
||||
<Border Background="{TemplateBinding Background}" ClipToBounds="True">
|
||||
<Image
|
||||
Name="{x:Static u:ImageViewer.PART_Image}"
|
||||
Source="{TemplateBinding Source}"
|
||||
Stretch="Uniform">
|
||||
<Image.RenderTransform>
|
||||
<TransformGroup>
|
||||
<ScaleTransform ScaleX="{Binding Scale, RelativeSource={RelativeSource TemplatedParent}}" ScaleY="{Binding Scale, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
<TranslateTransform X="{Binding TranslateX, RelativeSource={RelativeSource TemplatedParent}}" Y="{Binding TranslateY, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
<RotateTransform Angle="0" />
|
||||
</TransformGroup>
|
||||
</Image.RenderTransform>
|
||||
</Image>
|
||||
</Border>
|
||||
</VisualLayerManager>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^:moving">
|
||||
<Setter Property="Cursor" Value="Hand" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
@@ -2,17 +2,19 @@
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:converters="using:Avalonia.Controls.Converters"
|
||||
xmlns:ursaConverters="using:Ursa.Converters"
|
||||
xmlns:u="https://irihi.tech/ursa">
|
||||
<converters:PlatformKeyGestureConverter x:Key="KeyGestureConverter" />
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:KeyGestureInput}" TargetType="u:KeyGestureInput">
|
||||
<Setter Property="Width" Value="{DynamicResource KeyGestureInputWidth}" />
|
||||
<Setter Property="Height" Value="{DynamicResource KeyGestureInputHeight}" />
|
||||
<Setter Property="MinWidth" Value="{DynamicResource KeyGestureInputWidth}" />
|
||||
<Setter Property="MinHeight" Value="{DynamicResource KeyGestureInputHeight}" />
|
||||
<Setter Property="Background" Value="{DynamicResource KeyGestureInputBackground}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource KeyGestureInputBorderBrush}" />
|
||||
<Setter Property="BorderThickness" Value="{DynamicResource KeyGestureInputBorderThickness}" />
|
||||
<Setter Property="CornerRadius" Value="{DynamicResource KeyGestureInputCornerRadius}" />
|
||||
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center"></Setter>
|
||||
<Setter Property="Padding" Value="8 0" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:KeyGestureInput">
|
||||
<Border
|
||||
@@ -23,11 +25,43 @@
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<SelectableTextBlock
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Text="{TemplateBinding Gesture,
|
||||
Converter={StaticResource KeyGestureConverter}}" />
|
||||
<Panel VerticalAlignment="Stretch" Margin="{TemplateBinding Padding}">
|
||||
<Grid ColumnDefinitions="Auto, *, Auto" >
|
||||
<ContentPresenter Grid.Column="0"
|
||||
Content="{TemplateBinding InnerLeftContent}"
|
||||
Padding="{TemplateBinding Padding, Converter={x:Static ursaConverters:ThicknessIncludeConverter.Right}}"
|
||||
DockPanel.Dock="Left"
|
||||
VerticalAlignment="Stretch"
|
||||
VerticalContentAlignment="Center"
|
||||
Foreground="{DynamicResource TextBoxInnerForeground}"
|
||||
IsVisible="{Binding Path=InnerLeftContent, RelativeSource={RelativeSource TemplatedParent},
|
||||
Converter={x:Static ObjectConverters.IsNotNull}}" />
|
||||
<ContentPresenter
|
||||
Grid.Column="2"
|
||||
Content="{TemplateBinding InnerRightContent}"
|
||||
DockPanel.Dock="Right"
|
||||
Padding="{TemplateBinding Padding, Converter={x:Static ursaConverters:ThicknessIncludeConverter.Left}}"
|
||||
VerticalAlignment="Stretch"
|
||||
VerticalContentAlignment="Center"
|
||||
Foreground="{DynamicResource TextBoxInnerForeground}"
|
||||
IsVisible="{Binding Path=InnerRightContent, RelativeSource={RelativeSource TemplatedParent},
|
||||
Converter={x:Static ObjectConverters.IsNotNull}}" />
|
||||
<SelectableTextBlock
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Text="{TemplateBinding Gesture,
|
||||
Converter={StaticResource KeyGestureConverter}}" />
|
||||
<Button Grid.Column="0" Grid.ColumnSpan="3"
|
||||
Name="PART_ClearButton"
|
||||
Margin="0,0,8,0"
|
||||
HorizontalAlignment="Right"
|
||||
Command="{Binding $parent[u:KeyGestureInput].Clear}"
|
||||
Focusable="False"
|
||||
IsVisible="False"
|
||||
Theme="{DynamicResource InputClearButton}" />
|
||||
</Grid>
|
||||
</Panel>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
@@ -45,5 +79,13 @@
|
||||
<Setter Property="Background" Value="{DynamicResource KeyGestureInputPressedBackground}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource KeyGestureInputFocusBorderBrush}" />
|
||||
</Style>
|
||||
<Style Selector="^:not(:empty).clearButton, ^:not(:empty).ClearButton">
|
||||
<Style Selector="^:focus /template/ Button#PART_ClearButton">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
</Style>
|
||||
<Style Selector="^:pointerover /template/ Button#PART_ClearButton">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
</Style>
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:converters="clr-namespace:Ursa.Themes.Semi.Converters"
|
||||
xmlns:u="clr-namespace:Ursa.Controls;assembly=Ursa">
|
||||
xmlns:u="clr-namespace:Ursa.Controls;assembly=Ursa"
|
||||
xmlns:shapes="clr-namespace:Ursa.Controls.Shapes;assembly=Ursa">
|
||||
<!-- Add Resources Here -->
|
||||
<converters:BrushToColorConverter x:Key="BrushToColorConverter" />
|
||||
<ControlTheme x:Key="{x:Type u:LoadingIcon}" TargetType="u:LoadingIcon">
|
||||
@@ -12,6 +13,7 @@
|
||||
<Arc
|
||||
Name="PART_Arc"
|
||||
Width="20"
|
||||
IsVisible="{TemplateBinding IsVisible}"
|
||||
Height="20"
|
||||
StartAngle="0"
|
||||
StrokeJoin="Round"
|
||||
@@ -28,7 +30,7 @@
|
||||
</ConicGradientBrush>
|
||||
</Arc.Stroke>
|
||||
<Arc.Styles>
|
||||
<Style Selector="Arc">
|
||||
<Style Selector="Arc[IsVisible=True]">
|
||||
<Style.Animations>
|
||||
<Animation IterationCount="Infinite" Duration="0:0:0.5">
|
||||
<KeyFrame Cue="0%">
|
||||
@@ -66,7 +68,7 @@
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:Loading">
|
||||
<Panel IsVisible="{TemplateBinding IsLoading}">
|
||||
<Border
|
||||
<shapes:PureRectangle
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Background="{TemplateBinding Background}" />
|
||||
|
||||
298
src/Ursa.Themes.Semi/Controls/MessageBox.axaml
Normal file
298
src/Ursa.Themes.Semi/Controls/MessageBox.axaml
Normal file
@@ -0,0 +1,298 @@
|
||||
<ResourceDictionary
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:u="https://irihi.tech/ursa">
|
||||
<!-- Add Resources Here -->
|
||||
<ControlTheme x:Key="{x:Type u:MessageBoxWindow}" TargetType="u:MessageBoxWindow">
|
||||
<Setter Property="Title" Value="{x:Null}" />
|
||||
<Setter Property="Background" Value="{DynamicResource BorderCardBackground}" />
|
||||
<Setter Property="TransparencyBackgroundFallback" Value="{DynamicResource WindowDefaultBackground}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource WindowDefaultForeground}" />
|
||||
<Setter Property="FontSize" Value="{DynamicResource DefaultFontSize}" />
|
||||
<Setter Property="FontFamily" Value="{DynamicResource DefaultFontFamily}" />
|
||||
<Setter Property="Padding" Value="48 24" />
|
||||
<Setter Property="SizeToContent" Value="WidthAndHeight" />
|
||||
<Setter Property="WindowStartupLocation" Value="CenterOwner" />
|
||||
<Setter Property="ExtendClientAreaTitleBarHeightHint" Value="1" />
|
||||
<Setter Property="ExtendClientAreaToDecorationsHint" Value="True" />
|
||||
<Setter Property="ExtendClientAreaChromeHints" Value="SystemChrome" />
|
||||
<Setter Property="SystemDecorations">
|
||||
<OnPlatform>
|
||||
<OnPlatform.Windows>
|
||||
<SystemDecorations>Full</SystemDecorations>
|
||||
</OnPlatform.Windows>
|
||||
<OnPlatform.Default>
|
||||
<SystemDecorations>BorderOnly</SystemDecorations>
|
||||
</OnPlatform.Default>
|
||||
</OnPlatform>
|
||||
</Setter>
|
||||
<Setter Property="CanResize" Value="False" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:MessageBoxWindow">
|
||||
<Panel>
|
||||
<Border Name="PART_TransparencyFallback" IsHitTestVisible="False" />
|
||||
<Border Background="{TemplateBinding Background}" IsHitTestVisible="False" />
|
||||
<Panel Margin="{TemplateBinding WindowDecorationMargin}" Background="Transparent" />
|
||||
<ChromeOverlayLayer />
|
||||
<Grid RowDefinitions="Auto, *, Auto">
|
||||
<Grid
|
||||
Grid.Row="0"
|
||||
Margin="24,24,24,0"
|
||||
ColumnDefinitions="Auto, *, Auto">
|
||||
<PathIcon
|
||||
Name="PART_Icon"
|
||||
Grid.Column="0"
|
||||
Width="24"
|
||||
Height="24"
|
||||
Margin="0,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
IsHitTestVisible="False" />
|
||||
<TextBlock
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="16"
|
||||
FontWeight="Bold"
|
||||
IsHitTestVisible="False"
|
||||
Text="{TemplateBinding Title}"
|
||||
TextTrimming="CharacterEllipsis"
|
||||
TextWrapping="NoWrap" />
|
||||
<Button
|
||||
Name="{x:Static u:MessageBoxWindow.PART_CloseButton}"
|
||||
Grid.Column="2"
|
||||
Theme="{DynamicResource CloseButton}" />
|
||||
</Grid>
|
||||
<Grid
|
||||
Grid.Row="1"
|
||||
MaxWidth="{DynamicResource MessageBoxWindowContentMaxWidth}"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
ColumnDefinitions="Auto, *">
|
||||
<ScrollViewer
|
||||
Grid.Column="1"
|
||||
MaxHeight="300"
|
||||
HorizontalScrollBarVisibility="Disabled"
|
||||
VerticalScrollBarVisibility="Auto">
|
||||
<TextBlock
|
||||
Name="PART_ContentPresenter"
|
||||
VerticalAlignment="Center"
|
||||
Text="{TemplateBinding Content}"
|
||||
TextAlignment="Left"
|
||||
TextWrapping="Wrap" />
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
<StackPanel
|
||||
Grid.Row="2"
|
||||
Margin="24,0,24,24"
|
||||
HorizontalAlignment="Right"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
Name="{x:Static u:MessageBoxWindow.PART_CancelButton}"
|
||||
Margin="8,0,0,0"
|
||||
Classes="Tertiary"
|
||||
Content="{DynamicResource STRING_MENU_DIALOG_CANCEL}" />
|
||||
<Button
|
||||
Name="{x:Static u:MessageBoxWindow.PART_NoButton}"
|
||||
Margin="8,0,0,0"
|
||||
Classes="Danger"
|
||||
Content="{DynamicResource STRING_MENU_DIALOG_NO}"
|
||||
Theme="{DynamicResource SolidButton}" />
|
||||
<Button
|
||||
Name="{x:Static u:MessageBoxWindow.PART_YesButton}"
|
||||
Margin="8,0,0,0"
|
||||
Classes="Primary"
|
||||
Content="{DynamicResource STRING_MENU_DIALOG_YES}"
|
||||
Theme="{DynamicResource SolidButton}" />
|
||||
<Button
|
||||
Name="{x:Static u:MessageBoxWindow.PART_OKButton}"
|
||||
Margin="8,0,0,0"
|
||||
Classes="Primary"
|
||||
Content="{DynamicResource STRING_MENU_DIALOG_OK}"
|
||||
Theme="{DynamicResource SolidButton}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Panel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^[MessageIcon=None] /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="False" />
|
||||
</Style>
|
||||
<Style Selector="^[MessageIcon=Asterisk] /template/ PathIcon#PART_Icon, ^[MessageIcon=Information] /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SemiBlue6}" />
|
||||
<Setter Property="Data" Value="{DynamicResource DialogInformationIconGlyph}" />
|
||||
</Style>
|
||||
<Style Selector="^[MessageIcon=Error] /template/ PathIcon#PART_Icon, ^[MessageIcon=Hand] /template/ PathIcon#PART_Icon, ^[MessageIcon=Stop] /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SemiRed6}" />
|
||||
<Setter Property="Data" Value="{DynamicResource DialogErrorIconGlyph}" />
|
||||
</Style>
|
||||
<Style Selector="^[MessageIcon=Exclamation] /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SemiYellow6}" />
|
||||
<Setter Property="Data" Value="{DynamicResource DialogWarningIconGlyph}" />
|
||||
</Style>
|
||||
<Style Selector="^[MessageIcon=Question] /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SemiBlue6}" />
|
||||
<Setter Property="Data" Value="{DynamicResource DialogQuestionIconGlyph}" />
|
||||
</Style>
|
||||
<Style Selector="^[MessageIcon=Warning] /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SemiOrange6}" />
|
||||
<Setter Property="Data" Value="{DynamicResource DialogWarningIconGlyph}" />
|
||||
</Style>
|
||||
<Style Selector="^[MessageIcon=Success] /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SemiGreen6}" />
|
||||
<Setter Property="Data" Value="{DynamicResource DialogSuccessIconGlyph}" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:MessageBoxControl}" TargetType="u:MessageBoxControl">
|
||||
<Setter Property="CornerRadius" Value="12" />
|
||||
<Setter Property="Padding" Value="48 24" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:MessageBoxControl">
|
||||
<Border
|
||||
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, *, Auto">
|
||||
<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="24"
|
||||
Height="24"
|
||||
Margin="24,24,8,0"
|
||||
VerticalAlignment="Center"
|
||||
IsHitTestVisible="False" />
|
||||
<TextBlock
|
||||
Name="PART_Title"
|
||||
Grid.Column="1"
|
||||
Margin="0,24,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="16"
|
||||
FontWeight="Bold"
|
||||
IsHitTestVisible="False"
|
||||
Text="{TemplateBinding Title}"
|
||||
TextTrimming="CharacterEllipsis"
|
||||
TextWrapping="NoWrap" />
|
||||
<Button
|
||||
Name="{x:Static u:MessageBoxWindow.PART_CloseButton}"
|
||||
Grid.Column="2"
|
||||
Margin="0,24,24,0"
|
||||
Theme="{DynamicResource CloseButton}" />
|
||||
</Grid>
|
||||
<Grid
|
||||
Grid.Row="1"
|
||||
MaxWidth="{DynamicResource MessageBoxWindowContentMaxWidth}"
|
||||
Margin="{TemplateBinding Padding}">
|
||||
<ScrollViewer
|
||||
MaxHeight="300"
|
||||
HorizontalScrollBarVisibility="Disabled"
|
||||
VerticalScrollBarVisibility="Auto">
|
||||
<TextBlock
|
||||
Name="PART_ContentPresenter"
|
||||
VerticalAlignment="Center"
|
||||
Text="{TemplateBinding Content}"
|
||||
TextAlignment="Left"
|
||||
TextWrapping="Wrap" />
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
<StackPanel
|
||||
Grid.Row="2"
|
||||
Margin="24,0,24,24"
|
||||
HorizontalAlignment="Right"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
Name="{x:Static u:MessageBoxControl.PART_CancelButton}"
|
||||
Margin="8,0,0,0"
|
||||
Classes="Tertiary"
|
||||
Content="{DynamicResource STRING_MENU_DIALOG_CANCEL}" />
|
||||
<Button
|
||||
Name="{x:Static u:MessageBoxControl.PART_NoButton}"
|
||||
Margin="8,0,0,0"
|
||||
Classes="Danger"
|
||||
Content="{DynamicResource STRING_MENU_DIALOG_NO}"
|
||||
Theme="{DynamicResource SolidButton}" />
|
||||
<Button
|
||||
Name="{x:Static u:MessageBoxControl.PART_YesButton}"
|
||||
Margin="8,0,0,0"
|
||||
Classes="Primary"
|
||||
Content="{DynamicResource STRING_MENU_DIALOG_YES}"
|
||||
Theme="{DynamicResource SolidButton}" />
|
||||
<Button
|
||||
Name="{x:Static u:MessageBoxControl.PART_OKButton}"
|
||||
Margin="8,0,0,0"
|
||||
Classes="Primary"
|
||||
Content="{DynamicResource STRING_MENU_DIALOG_OK}"
|
||||
Theme="{DynamicResource SolidButton}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^ /template/ Panel#PART_TitleArea">
|
||||
<Setter Property="ContextFlyout">
|
||||
<MenuFlyout>
|
||||
<MenuItem Command="{Binding $parent[u:CustomDialogControl].CloseDialog}" Header="{DynamicResource STRING_MENU_DIALOG_CLOSE}">
|
||||
<MenuItem.Icon>
|
||||
<PathIcon
|
||||
Width="12"
|
||||
Height="12"
|
||||
Data="{DynamicResource WindowCloseIconGlyph}" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</MenuFlyout>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style Selector="^[MessageIcon=None] /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="False" />
|
||||
</Style>
|
||||
<Style Selector="^[MessageIcon=None] /template/ TextBlock#PART_Title">
|
||||
<Setter Property="Margin" Value="24 24 0 0" />
|
||||
</Style>
|
||||
<Style Selector="^[MessageIcon=Asterisk] /template/ PathIcon#PART_Icon, ^[MessageIcon=Information] /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SemiBlue6}" />
|
||||
<Setter Property="Data" Value="{DynamicResource DialogInformationIconGlyph}" />
|
||||
</Style>
|
||||
<Style Selector="^[MessageIcon=Error] /template/ PathIcon#PART_Icon, ^[MessageIcon=Hand] /template/ PathIcon#PART_Icon, ^[MessageIcon=Stop] /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SemiRed6}" />
|
||||
<Setter Property="Data" Value="{DynamicResource DialogErrorIconGlyph}" />
|
||||
</Style>
|
||||
<Style Selector="^[MessageIcon=Exclamation] /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SemiYellow6}" />
|
||||
<Setter Property="Data" Value="{DynamicResource DialogWarningIconGlyph}" />
|
||||
</Style>
|
||||
<Style Selector="^[MessageIcon=Question] /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SemiBlue6}" />
|
||||
<Setter Property="Data" Value="{DynamicResource DialogQuestionIconGlyph}" />
|
||||
</Style>
|
||||
<Style Selector="^[MessageIcon=Warning] /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SemiOrange6}" />
|
||||
<Setter Property="Data" Value="{DynamicResource DialogWarningIconGlyph}" />
|
||||
</Style>
|
||||
<Style Selector="^[MessageIcon=Success] /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SemiGreen6}" />
|
||||
<Setter Property="Data" Value="{DynamicResource DialogSuccessIconGlyph}" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
248
src/Ursa.Themes.Semi/Controls/NavMenu.axaml
Normal file
248
src/Ursa.Themes.Semi/Controls/NavMenu.axaml
Normal file
@@ -0,0 +1,248 @@
|
||||
<ResourceDictionary
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:converters="clr-namespace:Ursa.Themes.Semi.Converters"
|
||||
xmlns:u="https://irihi.tech/ursa">
|
||||
<!-- Add Resources Here -->
|
||||
|
||||
<converters:NavMenuMarginConverter x:Key="NavMarginConverter" />
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:NavMenu}" TargetType="u:NavMenu">
|
||||
<Setter Property="Grid.IsSharedSizeScope" Value="True" />
|
||||
<Setter Property="SubMenuIndent" Value="24" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:NavMenu">
|
||||
<DockPanel LastChildFill="True">
|
||||
<ContentPresenter Content="{TemplateBinding Header}" DockPanel.Dock="Top" />
|
||||
<ContentPresenter Content="{TemplateBinding Footer}" DockPanel.Dock="Bottom" />
|
||||
<ScrollViewer
|
||||
HorizontalAlignment="Center"
|
||||
HorizontalScrollBarVisibility="Disabled"
|
||||
AllowAutoHide="True"
|
||||
Theme="{DynamicResource StaticScrollViewer}"
|
||||
VerticalScrollBarVisibility="Auto">
|
||||
<ScrollViewer.Styles>
|
||||
<Style Selector="ScrollViewer /template/ ScrollBar">
|
||||
<Setter Property="Opacity" Value="0"></Setter>
|
||||
</Style>
|
||||
<Style Selector="ScrollViewer:pointerover">
|
||||
<Style Selector="^ /template/ ScrollBar#PART_HorizontalScrollBar">
|
||||
<Setter Property="Opacity" Value="1" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ ScrollBar#PART_VerticalScrollBar">
|
||||
<Setter Property="Opacity" Value="1" />
|
||||
</Style>
|
||||
</Style>
|
||||
</ScrollViewer.Styles>
|
||||
<ItemsPresenter ItemsPanel="{TemplateBinding ItemsPanel}" />
|
||||
</ScrollViewer>
|
||||
</DockPanel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^:horizontal-collapsed">
|
||||
<Setter Property="Width" Value="{x:Static x:Double.NaN}" />
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTemplate x:Key="DefaultNavMenuItemTemplate" TargetType="u:NavMenuItem">
|
||||
<Grid RowDefinitions="Auto, *">
|
||||
<Border
|
||||
Name="PART_Border"
|
||||
Grid.Row="0"
|
||||
MinHeight="32"
|
||||
Background="{TemplateBinding u:NavMenuItem.Background}"
|
||||
CornerRadius="4"
|
||||
Cursor="Hand">
|
||||
<Grid
|
||||
Name="PART_RootGrid"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center">
|
||||
<Grid.Margin>
|
||||
<MultiBinding Converter="{StaticResource NavMarginConverter}">
|
||||
<Binding Path="SubMenuIndent" RelativeSource="{RelativeSource TemplatedParent}" />
|
||||
<Binding Path="Level" RelativeSource="{RelativeSource TemplatedParent}" />
|
||||
<Binding Path="IsHorizontalCollapsed" RelativeSource="{RelativeSource TemplatedParent}" />
|
||||
</MultiBinding>
|
||||
</Grid.Margin>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Icon" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Expander" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ContentPresenter
|
||||
Name="PART_IconPresenter"
|
||||
Padding="8"
|
||||
HorizontalAlignment="Left"
|
||||
Background="Transparent"
|
||||
Content="{Binding Icon, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
ContentTemplate="{Binding IconTemplate, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
<ContentPresenter
|
||||
Name="PART_HeaderPresenter"
|
||||
Grid.Column="1"
|
||||
Padding="0,8"
|
||||
Background="Transparent"
|
||||
Content="{Binding Header, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
ContentTemplate="{Binding HeaderTemplate, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
<PathIcon
|
||||
Name="PART_ExpanderIcon"
|
||||
Grid.Column="2"
|
||||
Width="8"
|
||||
Height="8"
|
||||
Margin="12,0"
|
||||
Data="{DynamicResource NavigationMenuItemExpandIconGlyph}"
|
||||
Foreground="{DynamicResource NavigationMenuItemExpandIconForeground}">
|
||||
<PathIcon.Transitions>
|
||||
<Transitions>
|
||||
<TransformOperationsTransition Property="RenderTransform" Duration="0.1" />
|
||||
</Transitions>
|
||||
</PathIcon.Transitions>
|
||||
</PathIcon>
|
||||
<Popup
|
||||
Name="PART_Popup"
|
||||
Grid.Column="0"
|
||||
IsLightDismissEnabled="True"
|
||||
Placement="RightEdgeAlignedTop"
|
||||
PlacementTarget="{Binding #PART_Border}">
|
||||
<Border
|
||||
Margin="{DynamicResource NavigationMenuItemFlyoutMargin}"
|
||||
Padding="{DynamicResource MenuFlyoutPadding}"
|
||||
HorizontalAlignment="Stretch"
|
||||
Background="{DynamicResource MenuFlyoutBackground}"
|
||||
BorderBrush="{DynamicResource MenuFlyoutBorderBrush}"
|
||||
BorderThickness="{DynamicResource MenuFlyoutBorderThickness}"
|
||||
BoxShadow="{DynamicResource MenuFlyoutBorderBoxShadow}"
|
||||
CornerRadius="{DynamicResource MenuFlyoutCornerRadius}">
|
||||
<StackPanel Name="PART_OverflowPanel" />
|
||||
</Border>
|
||||
</Popup>
|
||||
</Grid>
|
||||
</Border>
|
||||
<ItemsPresenter
|
||||
Name="PART_ItemsPresenter"
|
||||
Grid.Row="1"
|
||||
Margin="0,4,0,0"
|
||||
VerticalAlignment="Top"
|
||||
Grid.IsSharedSizeScope="True"
|
||||
ItemsPanel="{Binding ItemsPanel, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
RenderTransformOrigin="0.5,0">
|
||||
<ItemsPresenter.Transitions>
|
||||
<Transitions>
|
||||
<DoubleTransition Property="Height" Duration="0.1" />
|
||||
<TransformOperationsTransition Property="RenderTransform" Duration="0.1" />
|
||||
</Transitions>
|
||||
</ItemsPresenter.Transitions>
|
||||
</ItemsPresenter>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
<ControlTheme x:Key="{x:Type u:NavMenuItem}" TargetType="u:NavMenuItem">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
||||
<Setter Property="ItemsPanel">
|
||||
<ItemsPanelTemplate>
|
||||
<u:OverflowStackPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</Setter>
|
||||
<Setter Property="Template" Value="{StaticResource DefaultNavMenuItemTemplate}" />
|
||||
<Style Selector="^:selected">
|
||||
<Setter Property="Background" Value="{DynamicResource NavigationMenuItemSelectedBackground}" />
|
||||
<Style Selector="^:pointerover">
|
||||
<Setter Property="Background" Value="{DynamicResource NavigationMenuItemSelectedBackground}" />
|
||||
</Style>
|
||||
</Style>
|
||||
<Style Selector="^:vertical-collapsed /template/ ItemsPresenter#PART_ItemsPresenter">
|
||||
<Setter Property="Height" Value="0" />
|
||||
<Setter Property="RenderTransform" Value="scale(1,0)" />
|
||||
</Style>
|
||||
<Style Selector="^:vertical-collapsed /template/ PathIcon#PART_ExpanderIcon">
|
||||
<Setter Property="RenderTransform" Value="rotate(180deg)" />
|
||||
</Style>
|
||||
<Style Selector="^:empty /template/ PathIcon#PART_ExpanderIcon">
|
||||
<Setter Property="IsVisible" Value="False" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Border#PART_Border:pointerover">
|
||||
<Setter Property="Background" Value="{DynamicResource NavigationMenuItemPointeroverBackground}" />
|
||||
</Style>
|
||||
<Style Selector="^:horizontal-collapsed:first-level">
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
<Style Selector="^ /template/ Border#PART_Border">
|
||||
<Setter Property="ToolTip.Tip" >
|
||||
<Template>
|
||||
<ContentPresenter Content="{TemplateBinding u:NavMenuItem.Header}" ContentTemplate="{TemplateBinding u:NavMenuItem.HeaderTemplate}"></ContentPresenter>
|
||||
</Template>
|
||||
</Setter>
|
||||
<Setter Property="ToolTip.ShowDelay" Value="0" />
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Border#PART_Border:pointerover">
|
||||
<Setter Property="Background" Value="{DynamicResource NavigationMenuItemPointeroverBackground}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_IconPresenter">
|
||||
<Setter Property="Grid.ColumnSpan" Value="3" />
|
||||
<Setter Property="Margin" Value="0 8" />
|
||||
<Setter Property="HorizontalAlignment" Value="Center" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_HeaderPresenter">
|
||||
<Setter Property="IsVisible" Value="False" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ PathIcon#PART_ExpanderIcon">
|
||||
<Setter Property="IsVisible" Value="False" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ ItemsPresenter#PART_ItemsPresenter">
|
||||
<Setter Property="IsVisible" Value="False" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Grid#PART_RootGrid">
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
</Style>
|
||||
|
||||
</Style>
|
||||
<Style Selector="^:horizontal-collapsed:not(:first-level)">
|
||||
<Style Selector="^ /template/ PathIcon#PART_ExpanderIcon">
|
||||
<Setter Property="RenderTransform" Value="rotate(-90deg)" />
|
||||
</Style>
|
||||
</Style>
|
||||
<Style Selector="^[IsSeparator=True]">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<StackPanel
|
||||
Name="PART_RootPanel"
|
||||
Margin="{DynamicResource NavigationMenuSeparatorMargin}"
|
||||
Cursor="No">
|
||||
<ContentPresenter
|
||||
Name="PART_HeaderPresenter"
|
||||
Margin="{DynamicResource NavigationMenuSeparatorHeaderMargin}"
|
||||
HorizontalAlignment="Left"
|
||||
Content="{TemplateBinding Header}"
|
||||
ContentTemplate="{TemplateBinding HeaderTemplate}"
|
||||
Foreground="{DynamicResource TextBlockQuaternaryForeground}"
|
||||
IsVisible="{TemplateBinding Header,
|
||||
Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||
<ContentPresenter.Styles>
|
||||
<Style Selector="TextBlock">
|
||||
<Setter Property="FontSize" Value="{DynamicResource NavigationMenuSeparatorHeaderFontSize}" />
|
||||
</Style>
|
||||
</ContentPresenter.Styles>
|
||||
</ContentPresenter>
|
||||
<Rectangle
|
||||
Name="PART_SeparatorBorder"
|
||||
Height="{DynamicResource NavigationMenuSeparatorBorderHeight}"
|
||||
Margin="{DynamicResource NavigationMenuSeparatorBorderMargin}"
|
||||
HorizontalAlignment="Stretch"
|
||||
Fill="{DynamicResource SemiColorBorder}" />
|
||||
</StackPanel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^:horizontal-collapsed:first-level">
|
||||
<Setter Property="HorizontalAlignment" Value="Center" />
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_HeaderPresenter">
|
||||
<Setter Property="IsVisible" Value="False" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Rectangle#PART_SeparatorBorder">
|
||||
<Setter Property="HorizontalAlignment" Value="Center" />
|
||||
<Setter Property="Width" Value="12" />
|
||||
</Style>
|
||||
</Style>
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
|
||||
</ResourceDictionary>
|
||||
@@ -1,338 +0,0 @@
|
||||
<ResourceDictionary
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:converters="clr-namespace:Ursa.Themes.Semi.Converters"
|
||||
xmlns:u="https://irihi.tech/ursa">
|
||||
<!-- Add Resources Here -->
|
||||
|
||||
<converters:NavigationMenuItemLevelToMarginConverter x:Key="MarginConverter" Indent="8" />
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:NavigationMenu}" TargetType="u:NavigationMenu">
|
||||
<Setter Property="VerticalAlignment" Value="Stretch" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:NavigationMenu">
|
||||
<Border
|
||||
Name="PART_RootBorder"
|
||||
Width="{DynamicResource NavigationMenuExpandWidth}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<Border.Transitions>
|
||||
<Transitions>
|
||||
<DoubleTransition Property="Width" Duration="0:0:0.1" />
|
||||
</Transitions>
|
||||
</Border.Transitions>
|
||||
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
|
||||
<Grid
|
||||
Name="PART_RootGrid"
|
||||
HorizontalAlignment="Stretch"
|
||||
Background="{TemplateBinding Background}"
|
||||
RowDefinitions="Auto, *, Auto, Auto">
|
||||
<StackPanel
|
||||
Margin="{DynamicResource NavigationMenuHeaderMargin}"
|
||||
HorizontalAlignment="Center"
|
||||
Orientation="Horizontal">
|
||||
<ContentPresenter
|
||||
Name="PART_IconPresenter"
|
||||
Margin="{DynamicResource NavigationMenuIconMargin}"
|
||||
VerticalAlignment="Center"
|
||||
Content="{TemplateBinding Icon}" />
|
||||
<ContentPresenter
|
||||
Name="PART_HeaderPresenter"
|
||||
VerticalAlignment="Center"
|
||||
Content="{TemplateBinding Header}"
|
||||
ContentTemplate="{TemplateBinding HeaderTemplate}" />
|
||||
|
||||
</StackPanel>
|
||||
<ItemsPresenter Grid.Row="1" ItemsPanel="{TemplateBinding ItemsPanel}" />
|
||||
<ContentPresenter
|
||||
Name="PART_FooterPresenter"
|
||||
Grid.Row="2"
|
||||
Content="{TemplateBinding Footer}"
|
||||
ContentTemplate="{TemplateBinding FooterTemplate}" />
|
||||
<ToggleSwitch
|
||||
Name="{x:Static u:NavigationMenu.PART_CloseButton}"
|
||||
Grid.Row="3"
|
||||
Content="Open"
|
||||
IsChecked="{TemplateBinding IsClosed,
|
||||
Mode=TwoWay}"
|
||||
IsVisible="{TemplateBinding ShowCollapseButton}"
|
||||
Theme="{DynamicResource ButtonToggleSwitch}">
|
||||
<ToggleSwitch.OnContent>
|
||||
<PathIcon
|
||||
Width="{DynamicResource NavigationMenuExpandIconWidth}"
|
||||
Height="{DynamicResource NavigationMenuExpandIconHeight}"
|
||||
Data="{DynamicResource NavigationMenuExpandIconGlyph}"
|
||||
Foreground="{DynamicResource ButtonDefaultTertiaryForeground}" />
|
||||
</ToggleSwitch.OnContent>
|
||||
<ToggleSwitch.OffContent>
|
||||
<PathIcon
|
||||
Width="{DynamicResource NavigationMenuExpandIconWidth}"
|
||||
Height="{DynamicResource NavigationMenuExpandIconHeight}"
|
||||
Data="{DynamicResource NavigationMenuExpandIconGlyph}"
|
||||
Foreground="{DynamicResource ButtonDefaultTertiaryForeground}" />
|
||||
</ToggleSwitch.OffContent>
|
||||
</ToggleSwitch>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^:closed">
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_HeaderPresenter">
|
||||
<Setter Property="ContentPresenter.IsVisible" Value="False" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Border#PART_RootBorder">
|
||||
<Setter Property="Border.Width" Value="{DynamicResource NavigationMenuClosedWidth}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_IconPresenter">
|
||||
<Setter Property="Grid.HorizontalAlignment" Value="Center" />
|
||||
</Style>
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:NavigationMenuItem}" TargetType="u:NavigationMenuItem">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:NavigationMenuItem">
|
||||
<Border>
|
||||
<StackPanel>
|
||||
<Border
|
||||
Name="PART_HeaderBorder"
|
||||
Margin="{DynamicResource NavigationMenuItemDefaultMargin}"
|
||||
Padding="{DynamicResource NavigationMenuItemDefaultPadding}"
|
||||
Background="{DynamicResource NavigationMenuItemDefaultBackground}"
|
||||
CornerRadius="{DynamicResource NavigationMenuItemDefaultCornerRadius}">
|
||||
<Grid
|
||||
Name="PART_RootStackPanel"
|
||||
HorizontalAlignment="Stretch"
|
||||
ColumnDefinitions="Auto, Auto, *, Auto">
|
||||
<ContentPresenter
|
||||
Name="PART_IconPresenter"
|
||||
Grid.Column="1"
|
||||
MinWidth="{DynamicResource NavigationMenuItemIconMinWidth}"
|
||||
Content="{TemplateBinding Icon}"
|
||||
ContentTemplate="{TemplateBinding IconTemplate}">
|
||||
<ContentPresenter.Margin>
|
||||
<MultiBinding Converter="{StaticResource MarginConverter}">
|
||||
<Binding Path="Level" RelativeSource="{RelativeSource TemplatedParent}" />
|
||||
<Binding Path="IsClosed" RelativeSource="{RelativeSource TemplatedParent}" />
|
||||
</MultiBinding>
|
||||
</ContentPresenter.Margin>
|
||||
</ContentPresenter>
|
||||
<ContentPresenter
|
||||
Name="PART_HeaderPresenter"
|
||||
Grid.Column="2"
|
||||
Margin="{DynamicResource NavigationMenuItemHeaderMargin}"
|
||||
VerticalAlignment="Center"
|
||||
Background="{TemplateBinding Background}"
|
||||
Content="{TemplateBinding Header}"
|
||||
ContentTemplate="{TemplateBinding HeaderTemplate}">
|
||||
<ContentPresenter.Transitions>
|
||||
<Transitions>
|
||||
<DoubleTransition Property="Opacity" Duration="0:0:0.15" />
|
||||
</Transitions>
|
||||
</ContentPresenter.Transitions>
|
||||
</ContentPresenter>
|
||||
<PathIcon
|
||||
Name="PART_ExpandIcon"
|
||||
Grid.Column="3"
|
||||
Width="{DynamicResource NavigationMenuItemExpandIconWidth}"
|
||||
Height="{DynamicResource NavigationMenuItemExpandIconHeight}"
|
||||
Data="{DynamicResource NavigationMenuItemExpandIconGlyph}"
|
||||
Foreground="{DynamicResource NavigationMenuItemExpandIconForeground}">
|
||||
<PathIcon.Transitions>
|
||||
<Transitions>
|
||||
<TransformOperationsTransition Property="RenderTransform" Duration="0.1" />
|
||||
</Transitions>
|
||||
</PathIcon.Transitions>
|
||||
</PathIcon>
|
||||
</Grid>
|
||||
</Border>
|
||||
<ItemsPresenter Name="PART_ItemsPresenter" ItemsPanel="{TemplateBinding ItemsPanel}">
|
||||
<ItemsPresenter.Transitions>
|
||||
<Transitions>
|
||||
<DoubleTransition Property="Opacity" Duration="0:0:0.15" />
|
||||
</Transitions>
|
||||
</ItemsPresenter.Transitions>
|
||||
</ItemsPresenter>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
||||
<Style Selector="^ /template/ Border#PART_HeaderBorder:pointerover">
|
||||
<Setter Property="Border.Background" Value="{DynamicResource NavigationMenuItemPointeroverBackground}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Border#PART_HeaderBorder:pressed">
|
||||
<Setter Property="Border.Background" Value="{DynamicResource NavigationMenuItemPressedBackground}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:highlighted /template/ ContentPresenter#PART_IconPresenter">
|
||||
<Setter Property="u:NavigationMenuItem.Foreground" Value="{DynamicResource NavigationMenuItemHighlightForeground}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:selected /template/ Border#PART_HeaderBorder">
|
||||
<Setter Property="u:NavigationMenuItem.Background" Value="{DynamicResource NavigationMenuItemSelectedBackground}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:empty:closed:top-level">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:NavigationMenuItem">
|
||||
<Border
|
||||
Name="PART_HeaderBorder"
|
||||
Margin="{DynamicResource NavigationMenuItemDefaultMargin}"
|
||||
Padding="{DynamicResource NavigationMenuItemDefaultPadding}"
|
||||
HorizontalAlignment="Center"
|
||||
Background="{DynamicResource NavigationMenuItemDefaultBackground}"
|
||||
CornerRadius="{DynamicResource NavigationMenuItemDefaultCornerRadius}"
|
||||
ToolTip.ShowDelay="0"
|
||||
ToolTip.Tip="{TemplateBinding Header}">
|
||||
<ContentPresenter
|
||||
Name="PART_IconPresenter"
|
||||
Grid.Column="1"
|
||||
MinWidth="{DynamicResource NavigationMenuItemIconMinWidth}"
|
||||
Margin="{DynamicResource NavigationMenuItemIconMargin}"
|
||||
Content="{TemplateBinding Icon}"
|
||||
ContentTemplate="{TemplateBinding IconTemplate}" />
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^ /template/ Border#PART_HeaderBorder:pointerover">
|
||||
<Setter Property="Border.Background" Value="{DynamicResource NavigationMenuItemPointeroverBackground}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Border#PART_HeaderBorder:pressed">
|
||||
<Setter Property="Border.Background" Value="{DynamicResource NavigationMenuItemPressedBackground}" />
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:not(:empty):closed">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:NavigationMenuItem">
|
||||
<Panel>
|
||||
<Border
|
||||
Name="PART_HeaderBorder"
|
||||
Margin="{DynamicResource NavigationMenuItemDefaultMargin}"
|
||||
Padding="{DynamicResource NavigationMenuItemDefaultPadding}"
|
||||
HorizontalAlignment="Center"
|
||||
Background="{DynamicResource NavigationMenuItemDefaultBackground}"
|
||||
CornerRadius="{DynamicResource NavigationMenuItemDefaultCornerRadius}">
|
||||
<Grid HorizontalAlignment="Stretch" ColumnDefinitions="Auto, *, Auto">
|
||||
<ContentPresenter
|
||||
Name="PART_IconPresenter"
|
||||
Grid.Column="0"
|
||||
MinWidth="{DynamicResource NavigationMenuItemIconMinWidth}"
|
||||
Content="{TemplateBinding Icon}"
|
||||
ContentTemplate="{TemplateBinding IconTemplate}" />
|
||||
<ContentPresenter
|
||||
Name="PART_HeaderPresenter"
|
||||
Grid.Column="1"
|
||||
Margin="{DynamicResource NavigationMenuItemHeaderMargin}"
|
||||
VerticalAlignment="Center"
|
||||
Background="{TemplateBinding Background}"
|
||||
Content="{TemplateBinding Header}"
|
||||
ContentTemplate="{TemplateBinding HeaderTemplate}"
|
||||
IsVisible="{TemplateBinding IsTopLevelMenuItem,
|
||||
Converter={x:Static BoolConverters.Not}}" />
|
||||
<PathIcon
|
||||
Grid.Column="2"
|
||||
Width="{DynamicResource NavigationMenuItemExpandIconWidth}"
|
||||
Height="{DynamicResource NavigationMenuItemExpandIconHeight}"
|
||||
Margin="{DynamicResource NavigationMenuItemExpandIconMargin}"
|
||||
Data="{DynamicResource NavigationMenuItemExpandIconGlyph}"
|
||||
Foreground="{DynamicResource NavigationMenuItemExpandIconForeground}"
|
||||
IsVisible="{TemplateBinding IsTopLevelMenuItem,
|
||||
Converter={x:Static BoolConverters.Not}}"
|
||||
RenderTransform="rotate(-90deg)" />
|
||||
</Grid>
|
||||
</Border>
|
||||
<Popup
|
||||
Name="{x:Static u:NavigationMenuItem.PART_Popup}"
|
||||
IsLightDismissEnabled="True"
|
||||
IsOpen="{TemplateBinding IsPopupOpen,
|
||||
Mode=TwoWay}"
|
||||
Placement="RightEdgeAlignedTop"
|
||||
PlacementTarget="PART_HeaderBorder"
|
||||
WindowManagerAddShadowHint="False">
|
||||
<Border
|
||||
MinWidth="{DynamicResource MenuFlyoutMinWidth}"
|
||||
MinHeight="{DynamicResource MenuFlyoutMinHeight}"
|
||||
MaxWidth="{DynamicResource MenuFlyoutMaxWidth}"
|
||||
MaxHeight="{DynamicResource MenuFlyoutMaxHeight}"
|
||||
Margin="{DynamicResource NavigationMenuItemFlyoutMargin}"
|
||||
Padding="{DynamicResource MenuFlyoutPadding}"
|
||||
HorizontalAlignment="Stretch"
|
||||
Background="{DynamicResource MenuFlyoutBackground}"
|
||||
BorderBrush="{DynamicResource MenuFlyoutBorderBrush}"
|
||||
BorderThickness="{DynamicResource MenuFlyoutBorderThickness}"
|
||||
BoxShadow="{DynamicResource MenuFlyoutBorderBoxShadow}"
|
||||
CornerRadius="{DynamicResource MenuFlyoutCornerRadius}">
|
||||
<ScrollViewer Theme="{DynamicResource MenuScrollViewer}">
|
||||
<ItemsPresenter
|
||||
Name="PART_ItemsPresenter"
|
||||
Grid.IsSharedSizeScope="True"
|
||||
ItemsPanel="{TemplateBinding ItemsPanel}" />
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</Popup>
|
||||
</Panel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^ /template/ Border#PART_HeaderBorder:pointerover">
|
||||
<Setter Property="Border.Background" Value="{DynamicResource NavigationMenuItemPointeroverBackground}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Border#PART_HeaderBorder:pressed">
|
||||
<Setter Property="Border.Background" Value="{DynamicResource NavigationMenuItemPressedBackground}" />
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:not(:closed):collapsed /template/ ItemsPresenter#PART_ItemsPresenter">
|
||||
<Setter Property="ItemsPresenter.Height" Value="{DynamicResource NavigationMenuItemCollapsedHeight}" />
|
||||
<Setter Property="ItemsPresenter.Opacity" Value="{DynamicResource NavigationMenuItemCollapsedOpacity}" />
|
||||
</Style>
|
||||
<Style Selector="^:not(:empty):not(:collapsed) /template/ PathIcon#PART_ExpandIcon">
|
||||
<Setter Property="PathIcon.RenderTransform" Value="rotate(-180deg)" />
|
||||
</Style>
|
||||
<Style Selector="^:empty /template/ PathIcon#PART_ExpandIcon">
|
||||
<Setter Property="PathIcon.IsVisible" Value="False" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:NavigationMenuSeparator}" TargetType="u:NavigationMenuSeparator">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:NavigationMenuSeparator">
|
||||
<StackPanel Name="PART_RootPanel" Margin="{DynamicResource NavigationMenuSeparatorMargin}">
|
||||
<ContentPresenter
|
||||
Name="PART_HeaderPresenter"
|
||||
Margin="{DynamicResource NavigationMenuSeparatorHeaderMargin}"
|
||||
HorizontalAlignment="Left"
|
||||
Content="{TemplateBinding Header}"
|
||||
ContentTemplate="{TemplateBinding HeaderTemplate}"
|
||||
Foreground="{DynamicResource TextBlockQuaternaryForeground}"
|
||||
IsVisible="{TemplateBinding Header,
|
||||
Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||
<ContentPresenter.Styles>
|
||||
<Style Selector="TextBlock">
|
||||
<Setter Property="FontSize" Value="{DynamicResource NavigationMenuSeparatorHeaderFontSize}" />
|
||||
</Style>
|
||||
</ContentPresenter.Styles>
|
||||
</ContentPresenter>
|
||||
<Rectangle
|
||||
Height="{DynamicResource NavigationMenuSeparatorBorderHeight}"
|
||||
Margin="{DynamicResource NavigationMenuSeparatorBorderMargin}"
|
||||
HorizontalAlignment="Stretch"
|
||||
Fill="{DynamicResource SemiColorBorder}" />
|
||||
</StackPanel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^:closed /template/ StackPanel#PART_RootPanel">
|
||||
<Setter Property="StackPanel.HorizontalAlignment" Value="Center" />
|
||||
<Setter Property="StackPanel.Width" Value="{DynamicResource NavigationMenuSeparatorClosedWidth}" />
|
||||
</Style>
|
||||
<Style Selector="^:closed /template/ ContentPresenter#PART_HeaderPresenter">
|
||||
<Setter Property="ContentPresenter.IsVisible" Value="False" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
38
src/Ursa.Themes.Semi/Controls/NumberDisplayer.axaml
Normal file
38
src/Ursa.Themes.Semi/Controls/NumberDisplayer.axaml
Normal file
@@ -0,0 +1,38 @@
|
||||
<ResourceDictionary
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:converters="clr-namespace:Ursa.Converters;assembly=Ursa"
|
||||
xmlns:u="https://irihi.tech/ursa">
|
||||
<!-- Add Resources Here -->
|
||||
<ControlTheme x:Key="{x:Type u:NumberDisplayerBase}" TargetType="u:NumberDisplayerBase">
|
||||
<Setter Property="Duration" Value="0:0:0.2" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:NumberDisplayerBase">
|
||||
<TextBlock
|
||||
FontSize="{TemplateBinding FontSize}"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
FontFamily="{TemplateBinding FontFamily}"
|
||||
Background="{TemplateBinding Background}"
|
||||
FontWeight="{TemplateBinding FontWeight}"
|
||||
FontStyle="{TemplateBinding FontStyle}"
|
||||
FontStretch="{TemplateBinding FontStretch}"
|
||||
Text="{TemplateBinding InternalText, Mode=OneWay}" />
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^[IsSelectable=True]">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:NumberDisplayerBase">
|
||||
<SelectableTextBlock
|
||||
FontSize="{TemplateBinding FontSize}"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
FontFamily="{TemplateBinding FontFamily}"
|
||||
Background="{TemplateBinding Background}"
|
||||
FontWeight="{TemplateBinding FontWeight}"
|
||||
FontStyle="{TemplateBinding FontStyle}"
|
||||
FontStretch="{TemplateBinding FontStretch}"
|
||||
Text="{TemplateBinding InternalText, Mode=OneWay}" />
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
87
src/Ursa.Themes.Semi/Controls/NumericUpDown.axaml
Normal file
87
src/Ursa.Themes.Semi/Controls/NumericUpDown.axaml
Normal file
@@ -0,0 +1,87 @@
|
||||
<ResourceDictionary
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:u="https://irihi.tech/ursa">
|
||||
<!-- Add Resources Here -->
|
||||
|
||||
<ControlTheme x:Key="InputClearButton" TargetType="Button">
|
||||
<Setter Property="Button.Foreground" Value="{DynamicResource TextBoxButtonDefaultForeground}" />
|
||||
<Setter Property="Button.Cursor" Value="Hand" />
|
||||
<Setter Property="Button.Template">
|
||||
<ControlTemplate TargetType="Button">
|
||||
<!-- Background must be transparent or hit test will fail -->
|
||||
<ContentControl Background="Transparent">
|
||||
<PathIcon
|
||||
Width="16"
|
||||
Height="16"
|
||||
Data="{DynamicResource TextBoxClearButtonData}"
|
||||
Foreground="{TemplateBinding Foreground}" />
|
||||
</ContentControl>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^:pointerover">
|
||||
<Setter Property="Foreground" Value="{DynamicResource TextBoxButtonPointeroverForeground}" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:NumericUpDown}" TargetType="{x:Type u:NumericUpDown}">
|
||||
<Setter Property="NumericUpDown.VerticalContentAlignment" Value="Center" />
|
||||
<Setter Property="NumericUpDown.CornerRadius" Value="{DynamicResource NumericUpDownCornerRadius}" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:NumericUpDown">
|
||||
<DataValidationErrors>
|
||||
<ButtonSpinner
|
||||
Name="PART_Spinner"
|
||||
MinWidth="0"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
VerticalContentAlignment="Stretch"
|
||||
AllowSpin="{TemplateBinding AllowSpin}"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}">
|
||||
<Panel>
|
||||
<TextBox
|
||||
Name="PART_TextBox"
|
||||
Height="{TemplateBinding Height}"
|
||||
MinHeight="{DynamicResource NumericUpDownWrapperDefaultHeight}"
|
||||
AcceptsReturn="False"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
DataValidationErrors.Errors="{ReflectionBinding $parent[NumericUpDown].(DataValidationErrors.Errors)}"
|
||||
FontSize="{TemplateBinding FontSize}"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
IsReadOnly="{TemplateBinding IsReadOnly}"
|
||||
TextWrapping="NoWrap"
|
||||
InnerLeftContent="{TemplateBinding InnerLeftContent}"
|
||||
Theme="{DynamicResource NonErrorTextBox}"
|
||||
Watermark="{TemplateBinding Watermark}" />
|
||||
<Panel
|
||||
Name="PART_DragPanel"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Background="Transparent"
|
||||
Cursor="SizeAll"
|
||||
IsVisible="{TemplateBinding AllowDrag}" />
|
||||
<Button
|
||||
Name="PART_ClearButton"
|
||||
Command="{Binding $parent[u:NumericUpDown].Clear}"
|
||||
HorizontalAlignment="Right"
|
||||
Margin="0 0 8 0"
|
||||
IsVisible="False"
|
||||
Focusable="False"
|
||||
Theme="{StaticResource InputClearButton}" />
|
||||
</Panel>
|
||||
</ButtonSpinner>
|
||||
</DataValidationErrors>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
||||
<Style Selector="^.clearButton, ^.ClearButton">
|
||||
<Style Selector="^[IsReadOnly=False]:focus /template/ Button#PART_ClearButton">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
</Style>
|
||||
<Style Selector="^[IsReadOnly=False]:pointerover /template/ Button#PART_ClearButton">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
</Style>
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
228
src/Ursa.Themes.Semi/Controls/RangeSlider.axaml
Normal file
228
src/Ursa.Themes.Semi/Controls/RangeSlider.axaml
Normal file
@@ -0,0 +1,228 @@
|
||||
<ResourceDictionary
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:u="https://irihi.tech/ursa">
|
||||
<!-- Add Resources Here -->
|
||||
<ControlTheme x:Key="{x:Type u:RangeSlider}" TargetType="u:RangeSlider">
|
||||
<Setter Property="Background" Value="{DynamicResource SliderTrackBackground}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SliderTrackForeground}" />
|
||||
<Setter Property="TrackWidth" Value="4" />
|
||||
<Style Selector="^:horizontal">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:RangeSlider">
|
||||
<DataValidationErrors>
|
||||
<Grid
|
||||
x:Name="SliderContainer"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
Background="Transparent"
|
||||
RowDefinitions="Auto,Auto,Auto">
|
||||
<Grid.Styles>
|
||||
<Style Selector="TickBar">
|
||||
<Setter Property="ReservedSpace" Value="{Binding #PART_Track.LowerThumb.Bounds}" />
|
||||
</Style>
|
||||
</Grid.Styles>
|
||||
<TickBar
|
||||
Name="TopTickBar"
|
||||
Grid.Row="0"
|
||||
Height="{DynamicResource SliderTickHorizontalHeight}"
|
||||
Margin="0,0,0,4"
|
||||
VerticalAlignment="Bottom"
|
||||
Fill="{DynamicResource SliderTickForeground}"
|
||||
IsVisible="False"
|
||||
Maximum="{TemplateBinding u:RangeSlider.Maximum}"
|
||||
Minimum="{TemplateBinding u:RangeSlider.Minimum}"
|
||||
Orientation="{TemplateBinding u:RangeSlider.Orientation}"
|
||||
Placement="Top"
|
||||
TickFrequency="{TemplateBinding u:RangeSlider.TickFrequency}"
|
||||
Ticks="{TemplateBinding Ticks}" />
|
||||
<TickBar
|
||||
Name="BottomTickBar"
|
||||
Grid.Row="2"
|
||||
Height="{DynamicResource SliderTickHorizontalHeight}"
|
||||
Margin="0,4,0,0"
|
||||
VerticalAlignment="Top"
|
||||
Fill="{DynamicResource SliderTickForeground}"
|
||||
IsVisible="False"
|
||||
Maximum="{TemplateBinding u:RangeSlider.Maximum}"
|
||||
Minimum="{TemplateBinding u:RangeSlider.Minimum}"
|
||||
Orientation="{TemplateBinding u:RangeSlider.Orientation}"
|
||||
Placement="Bottom"
|
||||
TickFrequency="{TemplateBinding u:RangeSlider.TickFrequency}"
|
||||
Ticks="{TemplateBinding Ticks}" />
|
||||
<u:RangeTrack
|
||||
Name="{x:Static u:RangeSlider.PART_Track}"
|
||||
Grid.Row="1"
|
||||
Cursor="Hand"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Orientation="{Binding Orientation, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
|
||||
LowerValue="{Binding LowerValue, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
|
||||
Maximum="{Binding Maximum, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
|
||||
Minimum="{Binding Minimum, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
|
||||
UpperValue="{Binding UpperValue, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}">
|
||||
<u:RangeTrack.LowerSection>
|
||||
<Border
|
||||
Name="PART_LowerSection"
|
||||
Height="{TemplateBinding TrackWidth}"
|
||||
Background="{TemplateBinding Background}"
|
||||
CornerRadius="100" />
|
||||
</u:RangeTrack.LowerSection>
|
||||
<u:RangeTrack.LowerThumb>
|
||||
<Thumb
|
||||
Width="16"
|
||||
Height="16"
|
||||
Theme="{DynamicResource SliderThumbTheme}" />
|
||||
</u:RangeTrack.LowerThumb>
|
||||
<u:RangeTrack.InnerSection>
|
||||
<Border
|
||||
Name="PART_InnerSection"
|
||||
Height="{TemplateBinding TrackWidth}"
|
||||
Background="{TemplateBinding Foreground}"
|
||||
CornerRadius="100" />
|
||||
</u:RangeTrack.InnerSection>
|
||||
<u:RangeTrack.UpperThumb>
|
||||
<Thumb
|
||||
Width="16"
|
||||
Height="16"
|
||||
Theme="{DynamicResource SliderThumbTheme}" />
|
||||
</u:RangeTrack.UpperThumb>
|
||||
<u:RangeTrack.UpperSection>
|
||||
<Border
|
||||
Name="PART_UpperSection"
|
||||
Height="{TemplateBinding TrackWidth}"
|
||||
Background="{TemplateBinding Background}"
|
||||
CornerRadius="100" />
|
||||
</u:RangeTrack.UpperSection>
|
||||
</u:RangeTrack>
|
||||
</Grid>
|
||||
</DataValidationErrors>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style Selector="^:vertical">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:RangeSlider">
|
||||
<DataValidationErrors>
|
||||
<Grid
|
||||
x:Name="SliderContainer"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
Background="{DynamicResource SliderContainerBackground}"
|
||||
ColumnDefinitions="Auto,Auto,Auto">
|
||||
<Grid.Styles>
|
||||
<Style Selector="TickBar">
|
||||
<Setter Property="ReservedSpace" Value="{Binding #PART_Track.LowerThumb.Bounds}" />
|
||||
</Style>
|
||||
</Grid.Styles>
|
||||
<TickBar
|
||||
Name="LeftTickBar"
|
||||
Grid.Column="0"
|
||||
Width="{DynamicResource SliderTickVerticalWidth}"
|
||||
Margin="0,0,4,0"
|
||||
HorizontalAlignment="Right"
|
||||
Fill="{DynamicResource SliderTickForeground}"
|
||||
IsVisible="False"
|
||||
Maximum="{TemplateBinding u:RangeSlider.Maximum}"
|
||||
Minimum="{TemplateBinding u:RangeSlider.Minimum}"
|
||||
Orientation="{TemplateBinding u:RangeSlider.Orientation}"
|
||||
Placement="Left"
|
||||
TickFrequency="{TemplateBinding u:RangeSlider.TickFrequency}"
|
||||
Ticks="{TemplateBinding Ticks}" />
|
||||
<TickBar
|
||||
Name="RightTickBar"
|
||||
Grid.Column="2"
|
||||
Width="{DynamicResource SliderTickVerticalWidth}"
|
||||
Margin="4,0,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
Fill="{DynamicResource SliderTickForeground}"
|
||||
IsVisible="False"
|
||||
Maximum="{TemplateBinding u:RangeSlider.Maximum}"
|
||||
Minimum="{TemplateBinding u:RangeSlider.Minimum}"
|
||||
Orientation="{TemplateBinding u:RangeSlider.Orientation}"
|
||||
Placement="Right"
|
||||
TickFrequency="{TemplateBinding u:RangeSlider.TickFrequency}"
|
||||
Ticks="{TemplateBinding Ticks}" />
|
||||
<u:RangeTrack
|
||||
Name="{x:Static u:RangeSlider.PART_Track}"
|
||||
Cursor="Hand"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Orientation="{Binding Orientation, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
|
||||
LowerValue="{Binding LowerValue, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
|
||||
Maximum="{Binding Maximum, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
|
||||
Minimum="{Binding Minimum, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
|
||||
UpperValue="{Binding UpperValue, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}">
|
||||
<u:RangeTrack.LowerSection>
|
||||
<Border
|
||||
Name="PART_LowerSection"
|
||||
Width="{TemplateBinding TrackWidth}"
|
||||
Background="{TemplateBinding Background}"
|
||||
CornerRadius="100" />
|
||||
</u:RangeTrack.LowerSection>
|
||||
<u:RangeTrack.LowerThumb>
|
||||
<Thumb
|
||||
Width="16"
|
||||
Height="16"
|
||||
Theme="{DynamicResource SliderThumbTheme}" />
|
||||
</u:RangeTrack.LowerThumb>
|
||||
<u:RangeTrack.InnerSection>
|
||||
<Border
|
||||
Name="PART_InnerSection"
|
||||
Width="{TemplateBinding TrackWidth}"
|
||||
Background="{TemplateBinding Foreground}"
|
||||
CornerRadius="100" />
|
||||
</u:RangeTrack.InnerSection>
|
||||
<u:RangeTrack.UpperThumb>
|
||||
<Thumb
|
||||
Width="16"
|
||||
Height="16"
|
||||
Theme="{DynamicResource SliderThumbTheme}" />
|
||||
</u:RangeTrack.UpperThumb>
|
||||
<u:RangeTrack.UpperSection>
|
||||
<Border
|
||||
Name="PART_UpperSection"
|
||||
Width="{TemplateBinding TrackWidth}"
|
||||
Background="{TemplateBinding Background}"
|
||||
CornerRadius="100" />
|
||||
</u:RangeTrack.UpperSection>
|
||||
</u:RangeTrack>
|
||||
</Grid>
|
||||
</DataValidationErrors>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style Selector="^[TickPlacement=TopLeft] /template/ TickBar#LeftTickBar, ^[TickPlacement=Outside] /template/ TickBar#LeftTickBar">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^[TickPlacement=TopLeft] /template/ TickBar#TopTickBar, ^[TickPlacement=Outside] /template/ TickBar#TopTickBar">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^[TickPlacement=BottomRight] /template/ TickBar#BottomTickBar, ^[TickPlacement=Outside] /template/ TickBar#BottomTickBar">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^[TickPlacement=BottomRight] /template/ TickBar#RightTickBar, ^[TickPlacement=Outside] /template/ TickBar#RightTickBar">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:error /template/ Thumb#thumb">
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource DataValidationErrorsSelectedBorderBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:disabled">
|
||||
<Style Selector="^ /template/ Border#PART_InnerSection">
|
||||
<Setter Property="Background" Value="{DynamicResource SliderTrackDisabledForeground}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^ /template/ Border#PART_UpperSection, ^ /template/ Border#PART_LowerSection">
|
||||
<Setter Property="Background" Value="{DynamicResource SliderTrackDisabledBackground}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^ /template/ Thumb">
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource SliderThumbDisabledBorderBrush}" />
|
||||
</Style>
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
61
src/Ursa.Themes.Semi/Controls/SelectionList.axaml
Normal file
61
src/Ursa.Themes.Semi/Controls/SelectionList.axaml
Normal file
@@ -0,0 +1,61 @@
|
||||
<ResourceDictionary
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:u="https://irihi.tech/ursa">
|
||||
<ControlTheme x:Key="{x:Type u:SelectionList}" TargetType="u:SelectionList">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="Indicator">
|
||||
<Template>
|
||||
<Border
|
||||
Margin="2"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Background="{DynamicResource SemiBlue1}"
|
||||
Theme="{DynamicResource CardBorder}" />
|
||||
</Template>
|
||||
</Setter>
|
||||
<Setter Property="ListBox.Template">
|
||||
<ControlTemplate TargetType="u:SelectionList">
|
||||
<Border
|
||||
Name="border"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
ClipToBounds="{TemplateBinding ClipToBounds}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<Panel>
|
||||
<ContentPresenter Name="{x:Static u:SelectionList.PART_Indicator}" Content="{TemplateBinding Indicator}" />
|
||||
<ItemsPresenter
|
||||
Name="PART_ItemsPresenter"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
ItemsPanel="{TemplateBinding ItemsPanel}" />
|
||||
</Panel>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:SelectionListItem}" TargetType="u:SelectionListItem">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Left" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Center"/>
|
||||
<Setter Property="Padding" Value="8" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:SelectionListItem">
|
||||
<ContentPresenter
|
||||
Name="PART_ContentPresenter"
|
||||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
Background="{TemplateBinding Background}"
|
||||
Content="{TemplateBinding Content}"
|
||||
FontWeight="{TemplateBinding FontWeight}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
Foreground="{TemplateBinding Foreground}" />
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^:selected">
|
||||
<Setter Property="FontWeight" Value="Bold" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
30
src/Ursa.Themes.Semi/Controls/ThemeSelector.axaml
Normal file
30
src/Ursa.Themes.Semi/Controls/ThemeSelector.axaml
Normal file
@@ -0,0 +1,30 @@
|
||||
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:u="https://irihi.tech/ursa">
|
||||
<!-- Add Resources Here -->
|
||||
<ControlTheme TargetType="u:ThemeToggleButton" x:Key="{x:Type u:ThemeToggleButton}">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:ThemeToggleButton">
|
||||
<ToggleSwitch
|
||||
Padding="4"
|
||||
Name="{x:Static u:ThemeToggleButton.PART_ThemeToggleButton}"
|
||||
Theme="{DynamicResource ButtonToggleSwitch}">
|
||||
<ToggleSwitch.OnContent>
|
||||
<PathIcon
|
||||
Width="16"
|
||||
Height="16"
|
||||
Data="{DynamicResource ThemeSelectorButtonLightGlyph}"
|
||||
Foreground="{DynamicResource ButtonDefaultTertiaryForeground}" />
|
||||
</ToggleSwitch.OnContent>
|
||||
<ToggleSwitch.OffContent>
|
||||
<PathIcon
|
||||
Width="16"
|
||||
Height="16"
|
||||
Data="{DynamicResource ThemeSelectorButtonDarkGlyph}"
|
||||
Foreground="{DynamicResource ButtonDefaultTertiaryForeground}" />
|
||||
</ToggleSwitch.OffContent>
|
||||
</ToggleSwitch>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
@@ -6,9 +6,9 @@
|
||||
<Design.PreviewWith>
|
||||
<StackPanel Width="100" Spacing="20">
|
||||
<u:Timeline>
|
||||
<u:TimelineItem Content="Hello" Time="2022-01-01" />
|
||||
<u:TimelineItem Content="World" Time="2022-02-01" />
|
||||
<u:TimelineItem Content="!" Time="2022-03-01" />
|
||||
<u:TimelineItem Content="Hello" />
|
||||
<u:TimelineItem Content="World" />
|
||||
<u:TimelineItem Content="!" />
|
||||
<u:TimelineItem />
|
||||
</u:Timeline>
|
||||
</StackPanel>
|
||||
@@ -32,98 +32,166 @@
|
||||
WarningBrush="{DynamicResource WarningTimelineIconForeground}" />
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:TimelineItem}" TargetType="u:TimelineItem">
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
<Setter Property="VerticalAlignment" Value="Top" />
|
||||
<Setter Property="u:TimelineItem.Template">
|
||||
<ControlTemplate TargetType="u:TimelineItem">
|
||||
<Grid ColumnDefinitions="Auto, *" RowDefinitions="*, Auto, *">
|
||||
<Grid
|
||||
Name="PART_RootGrid"
|
||||
ColumnDefinitions="Auto, Auto, Auto"
|
||||
RowDefinitions="Auto, Auto, Auto">
|
||||
<!-- Icon and Axis -->
|
||||
<Grid
|
||||
Name="PART_IconAxisRoot"
|
||||
Grid.Row="0"
|
||||
Grid.RowSpan="2"
|
||||
Grid.Column="0"
|
||||
RowDefinitions="Auto, Auto, *">
|
||||
<Rectangle
|
||||
Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
Width="1"
|
||||
Height="8"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Top"
|
||||
Classes="start"
|
||||
Fill="{DynamicResource TimelineLineBrush}" />
|
||||
<Panel Grid.Row="1">
|
||||
<Ellipse
|
||||
Name="PART_Indicator"
|
||||
Width="8"
|
||||
Height="8"
|
||||
Margin="2"
|
||||
Grid.RowSpan="3"
|
||||
Grid.Column="1"
|
||||
RowDefinitions="Auto, *">
|
||||
<Panel Grid.Row="0" Name="{x:Static u:TimelineItem.PART_Icon}">
|
||||
<ContentPresenter
|
||||
Margin="8"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Top"
|
||||
Fill="{DynamicResource DefaultTimelineIconForeground}" />
|
||||
VerticalAlignment="Center"
|
||||
Content="{TemplateBinding Icon}"
|
||||
ContentTemplate="{TemplateBinding IconTemplate}" />
|
||||
<Ellipse
|
||||
Name="PART_DefaultIcon"
|
||||
Width="12"
|
||||
Height="12"
|
||||
Margin="8"
|
||||
IsVisible="False"
|
||||
Fill="Gray" />
|
||||
</Panel>
|
||||
<Rectangle
|
||||
Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
Width="1"
|
||||
Grid.Row="1"
|
||||
Width="2"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Stretch"
|
||||
Classes="end"
|
||||
Fill="{DynamicResource TimelineLineBrush}" />
|
||||
</Grid>
|
||||
<Rectangle
|
||||
Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
Width="1"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Stretch"
|
||||
Classes="end"
|
||||
Fill="{DynamicResource TimelineLineBrush}" />
|
||||
<ContentPresenter
|
||||
Name="{x:Static u:TimelineItem.PART_Header}"
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Bottom"
|
||||
Foreground="Gray">
|
||||
<ContentPresenter.Content>
|
||||
Grid.Column="2"
|
||||
Margin="8,4"
|
||||
VerticalAlignment="Top"
|
||||
Content="{TemplateBinding Header}"
|
||||
ContentTemplate="{TemplateBinding HeaderTemplate}"
|
||||
FontSize="14"
|
||||
Foreground="{DynamicResource SemiGrey9}" />
|
||||
<ContentPresenter
|
||||
Name="{x:Static u:TimelineItem.PART_Content}"
|
||||
Grid.Row="1"
|
||||
Grid.Column="2"
|
||||
Margin="8,2"
|
||||
VerticalAlignment="Top"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
TextElement.FontSize="12"
|
||||
TextElement.Foreground="Gray" />
|
||||
<TextBlock
|
||||
Name="{x:Static u:TimelineItem.PART_Time}"
|
||||
Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
Margin="8,2"
|
||||
VerticalAlignment="Top"
|
||||
FontSize="12"
|
||||
Foreground="Gray"
|
||||
TextWrapping="Wrap">
|
||||
<TextBlock.Text>
|
||||
<MultiBinding Converter="{StaticResource FormatConverter}">
|
||||
<Binding Path="Time" RelativeSource="{RelativeSource TemplatedParent}" />
|
||||
<Binding Path="TimeFormat" RelativeSource="{RelativeSource TemplatedParent}" />
|
||||
</MultiBinding>
|
||||
</ContentPresenter.Content>
|
||||
</ContentPresenter>
|
||||
<ContentPresenter
|
||||
Name="content"
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Margin="0,0,0,16"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}" />
|
||||
</TextBlock.Text>
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^:first /template/ Rectangle.start">
|
||||
<Setter Property="Rectangle.Fill" Value="Transparent" />
|
||||
</Style>
|
||||
<Style Selector="^:last /template/ Rectangle.end">
|
||||
<Setter Property="Rectangle.Fill" Value="Transparent" />
|
||||
</Style>
|
||||
<Style Selector="^:none /template/ Ellipse#PART_Indicator">
|
||||
<Setter Property="Ellipse.Fill" Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=u:TimelineItem}, Path=IconForeground}" />
|
||||
<Style Selector="^:empty-icon /template/ Ellipse#PART_DefaultIcon">
|
||||
<Setter Property="IsVisible" Value="True"/>
|
||||
</Style>
|
||||
<Style Selector="^:not(:none):default /template/ Ellipse#PART_Indicator">
|
||||
<Setter Property="Ellipse.Fill" Value="{DynamicResource DefaultTimelineIconForeground}" />
|
||||
<Style Selector="^:empty-icon[Type=Default] /template/ Ellipse#PART_DefaultIcon">
|
||||
<Setter Property="Fill" Value="{DynamicResource SemiGrey6}"/>
|
||||
</Style>
|
||||
<Style Selector="^:not(:none):ongoing /template/ Ellipse#PART_Indicator">
|
||||
<Setter Property="Ellipse.Fill" Value="{DynamicResource OngoingTimelineIconForeground}" />
|
||||
<Style Selector="^:empty-icon[Type=Error] /template/ Ellipse#PART_DefaultIcon">
|
||||
<Setter Property="Fill" Value="{DynamicResource SemiRed6}"/>
|
||||
</Style>
|
||||
<Style Selector="^:not(:none):success /template/ Ellipse#PART_Indicator">
|
||||
<Setter Property="Ellipse.Fill" Value="{DynamicResource SuccessTimelineIconForeground}" />
|
||||
<Style Selector="^:empty-icon[Type=Ongoing] /template/ Ellipse#PART_DefaultIcon">
|
||||
<Setter Property="Fill" Value="{DynamicResource SemiBlue6}"/>
|
||||
</Style>
|
||||
<Style Selector="^:not(:none):warning /template/ Ellipse#PART_Indicator">
|
||||
<Setter Property="Ellipse.Fill" Value="{DynamicResource WarningTimelineIconForeground}" />
|
||||
<Style Selector="^:empty-icon[Type=Success] /template/ Ellipse#PART_DefaultIcon">
|
||||
<Setter Property="Fill" Value="{DynamicResource SemiGreen6}"/>
|
||||
</Style>
|
||||
<Style Selector="^:not(:none):error /template/ Ellipse#PART_Indicator">
|
||||
<Setter Property="Ellipse.Fill" Value="{DynamicResource ErrorTimelineIconForeground}" />
|
||||
<Style Selector="^:empty-icon[Type=Warning] /template/ Ellipse#PART_DefaultIcon">
|
||||
<Setter Property="Fill" Value="{DynamicResource SemiOrange6}"/>
|
||||
</Style>
|
||||
<Style Selector="^:all-left">
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_Header">
|
||||
<Setter Property="Grid.Row" Value="0" />
|
||||
<Setter Property="Grid.Column" Value="2" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Left" />
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_Content">
|
||||
<Setter Property="Grid.Row" Value="1" />
|
||||
<Setter Property="Grid.Column" Value="2" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Left" />
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ TextBlock#PART_Time">
|
||||
<Setter Property="Grid.Row" Value="2" />
|
||||
<Setter Property="Grid.Column" Value="2" />
|
||||
<Setter Property="TextAlignment" Value="Left" />
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
<Setter Property="Margin" Value="8 2 8 12"></Setter>
|
||||
</Style>
|
||||
</Style>
|
||||
<Style Selector="^:all-right">
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_Header">
|
||||
<Setter Property="Grid.Row" Value="0" />
|
||||
<Setter Property="Grid.Column" Value="0" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Right" />
|
||||
<Setter Property="HorizontalAlignment" Value="Right" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_Content">
|
||||
<Setter Property="Grid.Row" Value="1" />
|
||||
<Setter Property="Grid.Column" Value="0" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Right" />
|
||||
<Setter Property="HorizontalAlignment" Value="Right" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ TextBlock#PART_Time">
|
||||
<Setter Property="Grid.Row" Value="2" />
|
||||
<Setter Property="Grid.Column" Value="0" />
|
||||
<Setter Property="TextAlignment" Value="Right" />
|
||||
<Setter Property="HorizontalAlignment" Value="Right" />
|
||||
<Setter Property="Margin" Value="8 2 8 12"></Setter>
|
||||
</Style>
|
||||
</Style>
|
||||
<Style Selector="^:separate">
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_Header">
|
||||
<Setter Property="Grid.Row" Value="0" />
|
||||
<Setter Property="Grid.Column" Value="2" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Left" />
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_Content">
|
||||
<Setter Property="Grid.Row" Value="1" />
|
||||
<Setter Property="Grid.Column" Value="2" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Left" />
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
<Setter Property="Margin" Value="8 2 8 12"></Setter>
|
||||
</Style>
|
||||
<Style Selector="^ /template/ TextBlock#PART_Time">
|
||||
<Setter Property="Grid.Row" Value="0" />
|
||||
<Setter Property="Grid.Column" Value="0" />
|
||||
<Setter Property="TextAlignment" Value="Right" />
|
||||
<Setter Property="HorizontalAlignment" Value="Right" />
|
||||
</Style>
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
|
||||
137
src/Ursa.Themes.Semi/Controls/ToolBar.axaml
Normal file
137
src/Ursa.Themes.Semi/Controls/ToolBar.axaml
Normal file
@@ -0,0 +1,137 @@
|
||||
<ResourceDictionary
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:u="https://irihi.tech/ursa">
|
||||
<!-- Add Resources Here -->
|
||||
<ControlTheme x:Key="ToolBarExpandToggleButton" TargetType="ToggleButton">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<ContentPresenter
|
||||
x:Name="PART_ContentPresenter"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
RecognizesAccessKey="True"
|
||||
TextElement.FontSize="{TemplateBinding FontSize}"
|
||||
TextElement.FontWeight="{TemplateBinding FontWeight}"
|
||||
UseLayoutRounding="False" />
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</ControlTheme>
|
||||
<ControlTheme x:Key="{x:Type u:ToolBar}" TargetType="u:ToolBar">
|
||||
<Setter Property="HorizontalAlignment" Value="Left"/>
|
||||
<Setter Property="VerticalAlignment" Value="Top"/>
|
||||
<Setter Property="ItemsPanel">
|
||||
<ItemsPanelTemplate>
|
||||
<u:ToolBarPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</Setter>
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:ToolBar">
|
||||
<Border
|
||||
Padding="2"
|
||||
Margin="0"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalAlignment}"
|
||||
CornerRadius="4"
|
||||
Theme="{DynamicResource CardBorder}">
|
||||
<DockPanel LastChildFill="True">
|
||||
<ContentPresenter
|
||||
Name="PART_Header"
|
||||
Margin="8,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Content="{TemplateBinding Header}"
|
||||
ContentTemplate="{TemplateBinding HeaderTemplate}"
|
||||
DockPanel.Dock="Left"
|
||||
Foreground="{DynamicResource SemiColorText2}"
|
||||
IsVisible="{TemplateBinding Header,
|
||||
Converter={x:Static ObjectConverters.IsNotNull}}" />
|
||||
<Panel Name="PART_PopupButtonPanel" DockPanel.Dock="Right">
|
||||
<ToggleButton
|
||||
Name="button"
|
||||
Padding="8,0"
|
||||
VerticalAlignment="Stretch"
|
||||
IsVisible="False"
|
||||
Theme="{DynamicResource ToolBarExpandToggleButton}">
|
||||
<PathIcon
|
||||
Name="PART_Icon"
|
||||
Height="12"
|
||||
Foreground="{DynamicResource SemiColorText2}"
|
||||
Data="{DynamicResource ToolBarHorizontalMoreGlyph}" />
|
||||
</ToggleButton>
|
||||
<Popup
|
||||
IsLightDismissEnabled="True"
|
||||
IsOpen="{Binding #button.IsChecked, Mode=TwoWay}"
|
||||
Placement="{TemplateBinding PopupPlacement}"
|
||||
PlacementTarget="{Binding #button}">
|
||||
<Border Padding="2" Theme="{DynamicResource CardBorder}">
|
||||
<StackPanel Name="{x:Static u:ToolBar.PART_OverflowPanel}" />
|
||||
</Border>
|
||||
</Popup>
|
||||
</Panel>
|
||||
<ItemsPresenter
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
ItemsPanel="{TemplateBinding ItemsPanel}" />
|
||||
</DockPanel>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^[Orientation=Horizontal]">
|
||||
<Setter Property="PopupPlacement" Value="BottomEdgeAlignedLeft" />
|
||||
</Style>
|
||||
<Style Selector="^[Orientation=Vertical]">
|
||||
<Setter Property="PopupPlacement" Value="RightEdgeAlignedTop" />
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_Header">
|
||||
<Setter Property="DockPanel.Dock" Value="Top" />
|
||||
<Setter Property="HorizontalAlignment" Value="Center" />
|
||||
<Setter Property="VerticalAlignment" Value="Top" />
|
||||
<Setter Property="Margin" Value="0 8" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Panel#PART_PopupButtonPanel">
|
||||
<Setter Property="DockPanel.Dock" Value="Bottom" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ ToggleButton#button">
|
||||
<Setter Property="Padding" Value="0 8" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="Data" Value="{DynamicResource ToolBarVerticalMoreGlyph}" />
|
||||
<Setter Property="Width" Value="12" />
|
||||
<Setter Property="Height" Value="{x:Static x:Double.NaN}" />
|
||||
</Style>
|
||||
</Style>
|
||||
<Style Selector="^:overflow /template/ ToggleButton#button">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:ToolBarSeparator}" TargetType="u:ToolBarSeparator">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Rectangle
|
||||
Name="PART_Rect"
|
||||
Margin="4"
|
||||
Fill="{DynamicResource SemiColorBorder}" />
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^ /template/ Rectangle#PART_Rect">
|
||||
<Setter Property="Width" Value="1" />
|
||||
<Setter Property="VerticalAlignment" Value="Stretch" />
|
||||
<Setter Property="HorizontalAlignment" Value="Center" />
|
||||
</Style>
|
||||
<Style Selector="^:vertical /template/ Rectangle#PART_Rect">
|
||||
<Setter Property="Height" Value="1" />
|
||||
<Setter Property="Width" Value="{x:Static x:Double.NaN}" />
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
38
src/Ursa.Themes.Semi/Controls/TwoTonePathIcon.axaml
Normal file
38
src/Ursa.Themes.Semi/Controls/TwoTonePathIcon.axaml
Normal file
@@ -0,0 +1,38 @@
|
||||
<ResourceDictionary
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:u="https://irihi.tech/ursa">
|
||||
<!-- Add Resources Here -->
|
||||
<ControlTheme x:Key="{x:Type u:TwoTonePathIcon}" TargetType="u:TwoTonePathIcon">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="Height" Value="{DynamicResource IconElementThemeHeight}" />
|
||||
<Setter Property="Width" Value="{DynamicResource IconElementThemeWidth}" />
|
||||
<Setter Property="StrokeThickness" Value="0.4" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SemiBlue2}" />
|
||||
<Setter Property="StrokeBrush" Value="{DynamicResource SemiBlue6}" />
|
||||
<Setter Property="ActiveForeground" Value="{DynamicResource SemiBlue6}" />
|
||||
<Setter Property="ActiveStrokeBrush" Value="{DynamicResource SemiBlue6}" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:TwoTonePathIcon">
|
||||
<Border Background="{TemplateBinding Background}">
|
||||
<Panel>
|
||||
<Viewbox Width="{TemplateBinding Width}" Height="{TemplateBinding Height}">
|
||||
<Path
|
||||
Name="PART_Fill"
|
||||
Data="{TemplateBinding Data}"
|
||||
StrokeThickness="{TemplateBinding StrokeThickness}"
|
||||
StrokeJoin="Round"
|
||||
Fill="{TemplateBinding Foreground}"
|
||||
Stroke="{TemplateBinding StrokeBrush}"
|
||||
Stretch="Uniform" />
|
||||
</Viewbox>
|
||||
</Panel>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^:active /template/ Path#PART_Fill">
|
||||
<Setter Property="Fill" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ActiveForeground}" />
|
||||
<Setter Property="Stroke" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ActiveStrokeBrush}" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
@@ -4,15 +4,32 @@
|
||||
<ResourceInclude Source="Badge.axaml" />
|
||||
<ResourceInclude Source="Banner.axaml" />
|
||||
<ResourceInclude Source="ButtonGroup.axaml" />
|
||||
<ResourceInclude Source="ControlClassesInput.axaml" />
|
||||
<ResourceInclude Source="Dialog.axaml" />
|
||||
<ResourceInclude Source="DialogShared.axaml" />
|
||||
<ResourceInclude Source="DisableContainer.axaml" />
|
||||
<ResourceInclude Source="Divider.axaml" />
|
||||
<ResourceInclude Source="Drawer.axaml" />
|
||||
<ResourceInclude Source="DualBadge.axaml" />
|
||||
<ResourceInclude Source="EnumSelector.axaml" />
|
||||
<ResourceInclude Source="Form.axaml" />
|
||||
<ResourceInclude Source="IconButton.axaml" />
|
||||
<ResourceInclude Source="ImageViewer.axaml" />
|
||||
<ResourceInclude Source="IPv4Box.axaml" />
|
||||
<ResourceInclude Source="KeyGestureInput.axaml" />
|
||||
<ResourceInclude Source="Loading.axaml" />
|
||||
<ResourceInclude Source="Navigation.axaml" />
|
||||
<ResourceInclude Source="MessageBox.axaml" />
|
||||
<ResourceInclude Source="NavMenu.axaml" />
|
||||
<ResourceInclude Source="NumericUpDown.axaml" />
|
||||
<ResourceInclude Source="NumberDisplayer.axaml" />
|
||||
<ResourceInclude Source="Pagination.axaml" />
|
||||
<ResourceInclude Source="RangeSlider.axaml" />
|
||||
<ResourceInclude Source="SelectionList.axaml" />
|
||||
<ResourceInclude Source="TagInput.axaml" />
|
||||
<ResourceInclude Source="ThemeSelector.axaml" />
|
||||
<ResourceInclude Source="Timeline.axaml" />
|
||||
<ResourceInclude Source="Skeleton.axaml" />
|
||||
<ResourceInclude Source="TwoTonePathIcon.axaml" />
|
||||
<ResourceInclude Source="ToolBar.axaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
using System.Globalization;
|
||||
using Avalonia.Data.Converters;
|
||||
|
||||
namespace Ursa.Themes.Semi.Converters;
|
||||
|
||||
public class BooleansToOpacityConverter: IValueConverter
|
||||
{
|
||||
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is bool b)
|
||||
{
|
||||
return b? 1.0: 0.0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
17
src/Ursa.Themes.Semi/Converters/NavMenuMarginConverter.cs
Normal file
17
src/Ursa.Themes.Semi/Converters/NavMenuMarginConverter.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.Globalization;
|
||||
using Avalonia;
|
||||
using Avalonia.Data.Converters;
|
||||
|
||||
namespace Ursa.Themes.Semi.Converters;
|
||||
|
||||
public class NavMenuMarginConverter: IMultiValueConverter
|
||||
{
|
||||
public object? Convert(IList<object?> values, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
if (values[0] is double indent && values[1] is int level && values[2] is bool b)
|
||||
{
|
||||
return b ? new Thickness() : new Thickness(indent * (level-1), 0, 0, 0);
|
||||
}
|
||||
return AvaloniaProperty.UnsetValue;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,4 @@
|
||||
<Styles xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<Design.PreviewWith>
|
||||
<Border Padding="20">
|
||||
<!-- Add Controls for Previewer Here -->
|
||||
</Border>
|
||||
</Design.PreviewWith>
|
||||
<Styles x:Class="Ursa.Themes.Semi.SemiTheme" xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<Styles.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
@@ -13,11 +8,11 @@
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceInclude Source="../Controls/_index.axaml" />
|
||||
<ResourceInclude Source="Themes/Shared/_index.axaml" />
|
||||
<ResourceInclude Source="Locale/zh-cn.axaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Styles.Resources>
|
||||
|
||||
<StyleInclude Source="../Styles/_index.axaml" />
|
||||
|
||||
<!-- Add Styles Here -->
|
||||
</Styles>
|
||||
|
||||
57
src/Ursa.Themes.Semi/Index.axaml.cs
Normal file
57
src/Ursa.Themes.Semi/Index.axaml.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using System.Globalization;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Markup.Xaml.Styling;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.Styling;
|
||||
|
||||
namespace Ursa.Themes.Semi;
|
||||
|
||||
public class SemiTheme: Styles
|
||||
{
|
||||
private static readonly Dictionary<CultureInfo, string> _localeToResource = new()
|
||||
{
|
||||
{ new CultureInfo("zh-CN"), "avares://Ursa.Themes.Semi/Locale/zh-CN.axaml" },
|
||||
{ new CultureInfo("en-US"), "avares://Ursa.Themes.Semi/Locale/en-US.axaml" },
|
||||
};
|
||||
|
||||
private readonly IServiceProvider? sp;
|
||||
public SemiTheme(IServiceProvider? provider = null)
|
||||
{
|
||||
sp = provider;
|
||||
AvaloniaXamlLoader.Load(provider, this);
|
||||
}
|
||||
|
||||
private CultureInfo? _locale;
|
||||
public CultureInfo? Locale
|
||||
{
|
||||
get => _locale;
|
||||
set
|
||||
{
|
||||
_locale = value;
|
||||
var resource = TryGetLocaleResource(value);
|
||||
var d = AvaloniaXamlLoader.Load(sp, new Uri(resource)) as ResourceDictionary;
|
||||
if (d is null) return;
|
||||
foreach (var kv in d)
|
||||
{
|
||||
this.Resources.Add(kv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string TryGetLocaleResource(CultureInfo? locale)
|
||||
{
|
||||
if (locale is null)
|
||||
{
|
||||
return _localeToResource[new CultureInfo("zh-CN")];
|
||||
}
|
||||
|
||||
if (_localeToResource.TryGetValue(locale, out var resource))
|
||||
{
|
||||
return resource;
|
||||
}
|
||||
return _localeToResource[new CultureInfo("zh-CN")];
|
||||
}
|
||||
}
|
||||
13
src/Ursa.Themes.Semi/Locale/en-us.axaml
Normal file
13
src/Ursa.Themes.Semi/Locale/en-us.axaml
Normal file
@@ -0,0 +1,13 @@
|
||||
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<!-- Add Resources Here -->
|
||||
<x:String x:Key="STRING_MENU_BRING_TO_FRONT">Bring to Front</x:String>
|
||||
<x:String x:Key="STRING_MENU_BRING_FORWARD">Bring Forward</x:String>
|
||||
<x:String x:Key="STRING_MENU_SEND_BACKWARD">Send Backward</x:String>
|
||||
<x:String x:Key="STRING_MENU_SEND_TO_BACK">Send to Back</x:String>
|
||||
<x:String x:Key="STRING_MENU_DIALOG_OK">OK</x:String>
|
||||
<x:String x:Key="STRING_MENU_DIALOG_CANCEL">Cancel</x:String>
|
||||
<x:String x:Key="STRING_MENU_DIALOG_YES">Yes</x:String>
|
||||
<x:String x:Key="STRING_MENU_DIALOG_NO">No</x:String>
|
||||
<x:String x:Key="STRING_MENU_DIALOG_CLOSE">Close</x:String>
|
||||
</ResourceDictionary>
|
||||
13
src/Ursa.Themes.Semi/Locale/zh-cn.axaml
Normal file
13
src/Ursa.Themes.Semi/Locale/zh-cn.axaml
Normal file
@@ -0,0 +1,13 @@
|
||||
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<!-- Add Resources Here -->
|
||||
<x:String x:Key="STRING_MENU_BRING_TO_FRONT">置于顶层</x:String>
|
||||
<x:String x:Key="STRING_MENU_BRING_FORWARD">上移一层</x:String>
|
||||
<x:String x:Key="STRING_MENU_SEND_BACKWARD">下移一层</x:String>
|
||||
<x:String x:Key="STRING_MENU_SEND_TO_BACK">置于底层</x:String>
|
||||
<x:String x:Key="STRING_MENU_DIALOG_OK">确认</x:String>
|
||||
<x:String x:Key="STRING_MENU_DIALOG_CANCEL">取消</x:String>
|
||||
<x:String x:Key="STRING_MENU_DIALOG_YES">是</x:String>
|
||||
<x:String x:Key="STRING_MENU_DIALOG_NO">否</x:String>
|
||||
<x:String x:Key="STRING_MENU_DIALOG_CLOSE">关闭</x:String>
|
||||
</ResourceDictionary>
|
||||
@@ -42,15 +42,15 @@
|
||||
<Style Selector="u|ButtonGroup.Tertiary Button">
|
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonGroupDefaultTertiaryForeground}" />
|
||||
</Style>
|
||||
<Style Selector="u|ButtonGroup.Success Button">
|
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonGroupDefaultSuccessForeground}" />
|
||||
</Style>
|
||||
<Style Selector="u|ButtonGroup.Warning Button">
|
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonGroupDefaultWarningForeground}" />
|
||||
</Style>
|
||||
<Style Selector="u|ButtonGroup.Danger Button">
|
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonGroupDefaultDangerForeground}" />
|
||||
</Style>
|
||||
<Style Selector="u|ButtonGroup.Success Button">
|
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonGroupDefaultSuccessForeground}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="u|ButtonGroup.Solid.Primary">
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonGroupSolidPrimaryBackground}" />
|
||||
@@ -61,15 +61,15 @@
|
||||
<Style Selector="u|ButtonGroup.Solid.Tertiary">
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonGroupSolidTertiaryBackground}" />
|
||||
</Style>
|
||||
<Style Selector="u|ButtonGroup.Solid.Success">
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonGroupSolidSuccessBackground}" />
|
||||
</Style>
|
||||
<Style Selector="u|ButtonGroup.Solid.Warning">
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonGroupSolidWarningBackground}" />
|
||||
</Style>
|
||||
<Style Selector="u|ButtonGroup.Solid.Danger">
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonGroupSolidDangerBackground}" />
|
||||
</Style>
|
||||
<Style Selector="u|ButtonGroup.Solid.Success">
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonGroupSolidSuccessBackground}" />
|
||||
</Style>
|
||||
<Style Selector="u|ButtonGroup.Solid Button">
|
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonGroupSolidForeground}" />
|
||||
</Style>
|
||||
@@ -100,6 +100,14 @@
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonGroupSolidTertiaryPressedBackground}" />
|
||||
</Style>
|
||||
</Style>
|
||||
<Style Selector="u|ButtonGroup.Solid.Success Button">
|
||||
<Style Selector="^:pointerover">
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonGroupSolidSuccessPointeroverBackground}" />
|
||||
</Style>
|
||||
<Style Selector="^:pressed">
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonGroupSolidSuccessPressedBackground}" />
|
||||
</Style>
|
||||
</Style>
|
||||
<Style Selector="u|ButtonGroup.Solid.Warning Button">
|
||||
<Style Selector="^:pointerover">
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonGroupSolidWarningPointeroverBackground}" />
|
||||
@@ -116,13 +124,5 @@
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonGroupSolidDangerPressedBackground}" />
|
||||
</Style>
|
||||
</Style>
|
||||
<Style Selector="u|ButtonGroup.Solid.Success Button">
|
||||
<Style Selector="^:pointerover">
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonGroupSolidSuccessPointeroverBackground}" />
|
||||
</Style>
|
||||
<Style Selector="^:pressed">
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonGroupSolidSuccessPressedBackground}" />
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
</Styles>
|
||||
|
||||
26
src/Ursa.Themes.Semi/Styles/ToolBar.axaml
Normal file
26
src/Ursa.Themes.Semi/Styles/ToolBar.axaml
Normal file
@@ -0,0 +1,26 @@
|
||||
<Styles xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:u="https://irihi.tech/ursa">
|
||||
<Design.PreviewWith>
|
||||
<Border Padding="20">
|
||||
<!-- Add Controls for Previewer Here -->
|
||||
</Border>
|
||||
</Design.PreviewWith>
|
||||
<Style Selector="u|ToolBar Button">
|
||||
<Setter Property="Theme" Value="{DynamicResource BorderlessButton}"></Setter>
|
||||
<Setter Property="FontWeight" Value="Regular" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SemiColorText0}"></Setter>
|
||||
</Style>
|
||||
<Style Selector="u|ToolBar CheckBox">
|
||||
<Setter Property="Margin" Value="8 0" />
|
||||
</Style>
|
||||
<Style Selector="u|ToolBar ToggleButton">
|
||||
<Setter Property="FontWeight" Value="Regular" />
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
<Setter Property="Foreground" Value="{DynamicResource SemiColorText0}"/>
|
||||
</Style>
|
||||
<Style Selector="u|ToolBar ComboBox">
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
||||
</Style>
|
||||
<!-- Add Styles Here -->
|
||||
</Styles>
|
||||
@@ -6,5 +6,6 @@
|
||||
</Design.PreviewWith>
|
||||
<StyleInclude Source="ButtonGroup.axaml" />
|
||||
<StyleInclude Source="Skeleton.axaml" />
|
||||
<StyleInclude Source="ToolBar.axaml"/>
|
||||
<!-- Add Styles Here -->
|
||||
</Styles>
|
||||
|
||||
@@ -1,10 +1,33 @@
|
||||
<ResourceDictionary xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<!-- Add Resources Here -->
|
||||
<SolidColorBrush x:Key="BadgeBorderBrush" Opacity="0.08" Color="White" />
|
||||
<SolidColorBrush x:Key="BadgeForeground" Color="White" />
|
||||
<SolidColorBrush x:Key="BadgeBorderBrush" Color="#1C1F23" />
|
||||
<SolidColorBrush x:Key="BadgeForeground" Color="#1C1F23" />
|
||||
<!-- Solid -->
|
||||
<SolidColorBrush x:Key="BadgePrimaryBadgeBackground" Color="#FF54A9FF" />
|
||||
<SolidColorBrush x:Key="BadgeSecondaryBadgeBackground" Color="#FF40B4F3" />
|
||||
<SolidColorBrush x:Key="BadgeTertiaryBadgeBackground" Color="#FF888D92" />
|
||||
<SolidColorBrush x:Key="BadgeWarningBadgeBackground" Color="#FFFFAE43" />
|
||||
<SolidColorBrush x:Key="BadgeDangerBadgeBackground" Color="#FFFC725A" />
|
||||
</ResourceDictionary>
|
||||
<SolidColorBrush x:Key="BadgeSuccessBadgeBackground" Color="#FF5DC264" />
|
||||
<!-- Light -->
|
||||
<SolidColorBrush x:Key="BadgeLightPrimaryBadgeForeground" Color="#FF54A9FF" />
|
||||
<SolidColorBrush x:Key="BadgeLightPrimaryBadgeBackground" Color="#FF003D8F" />
|
||||
<SolidColorBrush x:Key="BadgeLightSecondaryBadgeForeground" Color="#FF40B4F3" />
|
||||
<SolidColorBrush x:Key="BadgeLightSecondaryBadgeBackground" Color="#FF004B83" />
|
||||
<SolidColorBrush x:Key="BadgeLightTertiaryBadgeForeground" Color="#FF888D92" />
|
||||
<SolidColorBrush x:Key="BadgeLightTertiaryBadgeBackground" Color="#FF2E3238" />
|
||||
<SolidColorBrush x:Key="BadgeLightWarningBadgeForeground" Color="#FFFFAE43" />
|
||||
<SolidColorBrush x:Key="BadgeLightWarningBadgeBackground" Color="#FF7E3100" />
|
||||
<SolidColorBrush x:Key="BadgeLightDangerBadgeForeground" Color="#FFFC725A" />
|
||||
<SolidColorBrush x:Key="BadgeLightDangerBadgeBackground" Color="#FF8E0805" />
|
||||
<SolidColorBrush x:Key="BadgeLightSuccessBadgeForeground" Color="#FF5DC264" />
|
||||
<SolidColorBrush x:Key="BadgeLightSuccessBadgeBackground" Color="#FF1B5924" />
|
||||
<!-- Inverted -->
|
||||
<SolidColorBrush x:Key="BadgeInvertedBadgeBackground" Color="#1C1F23" />
|
||||
|
||||
<SolidColorBrush x:Key="BadgeInvertedPrimaryBadgeForeground" Color="#FF54A9FF" />
|
||||
<SolidColorBrush x:Key="BadgeInvertedSecondaryBadgeForeground" Color="#FF40B4F3" />
|
||||
<SolidColorBrush x:Key="BadgeInvertedTertiaryBadgeForeground" Color="#FF888D92" />
|
||||
<SolidColorBrush x:Key="BadgeInvertedWarningBadgeForeground" Color="#FFFFAE43" />
|
||||
<SolidColorBrush x:Key="BadgeInvertedDangerBadgeForeground" Color="#FFFC725A" />
|
||||
<SolidColorBrush x:Key="BadgeInvertedSuccessBadgeForeground" Color="#FF5DC264" />
|
||||
</ResourceDictionary>
|
||||
@@ -2,12 +2,12 @@
|
||||
<!-- Add Resources Here -->
|
||||
<SolidColorBrush x:Key="BannerInformationBackground" Color="#FF053170" />
|
||||
<SolidColorBrush x:Key="BannerInformationBorderBrush" Color="#FF54A9FF" />
|
||||
<SolidColorBrush x:Key="BannerSuccessBackground" Color="#FF123C19" />
|
||||
<SolidColorBrush x:Key="BannerSuccessBorderBrush" Color="#FF5DC264" />
|
||||
<SolidColorBrush x:Key="BannerWarningBackground" Color="#FF551F03" />
|
||||
<SolidColorBrush x:Key="BannerWarningBorderBrush" Color="#FFFFAE43" />
|
||||
<SolidColorBrush x:Key="BannerErrorBackground" Color="#FF6C090B" />
|
||||
<SolidColorBrush x:Key="BannerErrorBorderBrush" Color="#FFFC725A" />
|
||||
<SolidColorBrush x:Key="BannerSuccessBackground" Color="#FF123C19" />
|
||||
<SolidColorBrush x:Key="BannerSuccessBorderBrush" Color="#FF5DC264" />
|
||||
|
||||
<SolidColorBrush x:Key="BannerCloseButtonForeground" Opacity="0.6" Color="#FFF9F9F9" />
|
||||
</ResourceDictionary>
|
||||
|
||||
5
src/Ursa.Themes.Semi/Themes/Dark/Dialog.axaml
Normal file
5
src/Ursa.Themes.Semi/Themes/Dark/Dialog.axaml
Normal file
@@ -0,0 +1,5 @@
|
||||
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<!-- Add Resources Here -->
|
||||
<SolidColorBrush x:Key="OverlayDialogMaskBrush" Color="#FFA7ABB0" Opacity="0.2"></SolidColorBrush>
|
||||
</ResourceDictionary>
|
||||
@@ -4,6 +4,7 @@
|
||||
<MergeResourceInclude Source="Badge.axaml" />
|
||||
<MergeResourceInclude Source="Banner.axaml" />
|
||||
<MergeResourceInclude Source="ButtonGroup.axaml" />
|
||||
<MergeResourceInclude Source="Dialog.axaml" />
|
||||
<MergeResourceInclude Source="Divider.axaml" />
|
||||
<MergeResourceInclude Source="DualBadge.axaml" />
|
||||
<MergeResourceInclude Source="IPv4Box.axaml" />
|
||||
|
||||
@@ -1,10 +1,33 @@
|
||||
<ResourceDictionary xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<!-- Add Resources Here -->
|
||||
<SolidColorBrush x:Key="BadgeBorderBrush" Opacity="0.08" Color="#1C1F23" />
|
||||
<SolidColorBrush x:Key="BadgeBorderBrush" Color="White"/>
|
||||
<SolidColorBrush x:Key="BadgeForeground" Color="White" />
|
||||
<!-- Solid -->
|
||||
<SolidColorBrush x:Key="BadgePrimaryBadgeBackground" Color="#0077F0" />
|
||||
<SolidColorBrush x:Key="BadgeSecondaryBadgeBackground" Color="#0095EE" />
|
||||
<SolidColorBrush x:Key="BadgeTertiaryBadgeBackground" Color="#6B7075" />
|
||||
<SolidColorBrush x:Key="BadgeWarningBadgeBackground" Color="#FC8800" />
|
||||
<SolidColorBrush x:Key="BadgeDangerBadgeBackground" Color="#F93920" />
|
||||
</ResourceDictionary>
|
||||
<SolidColorBrush x:Key="BadgeSuccessBadgeBackground" Color="#3BB346" />
|
||||
<!-- Light -->
|
||||
<SolidColorBrush x:Key="BadgeLightPrimaryBadgeForeground" Color="#0077FA" />
|
||||
<SolidColorBrush x:Key="BadgeLightPrimaryBadgeBackground" Color="#D4ECFF" />
|
||||
<SolidColorBrush x:Key="BadgeLightSecondaryBadgeForeground" Color="#0095EE" />
|
||||
<SolidColorBrush x:Key="BadgeLightSecondaryBadgeBackground" Color="#CEEEFC" />
|
||||
<SolidColorBrush x:Key="BadgeLightTertiaryBadgeForeground" Color="#6B7075" />
|
||||
<SolidColorBrush x:Key="BadgeLightTertiaryBadgeBackground" Color="#E6E8EA" />
|
||||
<SolidColorBrush x:Key="BadgeLightWarningBadgeForeground" Color="#FC8800" />
|
||||
<SolidColorBrush x:Key="BadgeLightWarningBadgeBackground" Color="#FFEFD0" />
|
||||
<SolidColorBrush x:Key="BadgeLightDangerBadgeForeground" Color="#F93920" />
|
||||
<SolidColorBrush x:Key="BadgeLightDangerBadgeBackground" Color="#FEE0D5" />
|
||||
<SolidColorBrush x:Key="BadgeLightSuccessBadgeForeground" Color="#3BB346" />
|
||||
<SolidColorBrush x:Key="BadgeLightSuccessBadgeBackground" Color="#D0F0D1" />
|
||||
<!-- Inverted -->
|
||||
<SolidColorBrush x:Key="BadgeInvertedBadgeBackground" Color="White" />
|
||||
|
||||
<SolidColorBrush x:Key="BadgeInvertedPrimaryBadgeForeground" Color="#0077F0" />
|
||||
<SolidColorBrush x:Key="BadgeInvertedSecondaryBadgeForeground" Color="#0095EE" />
|
||||
<SolidColorBrush x:Key="BadgeInvertedTertiaryBadgeForeground" Color="#6B7075" />
|
||||
<SolidColorBrush x:Key="BadgeInvertedWarningBadgeForeground" Color="#FC8800" />
|
||||
<SolidColorBrush x:Key="BadgeInvertedDangerBadgeForeground" Color="#F93920" />
|
||||
<SolidColorBrush x:Key="BadgeInvertedSuccessBadgeForeground" Color="#3BB346" />
|
||||
</ResourceDictionary>
|
||||
@@ -2,12 +2,12 @@
|
||||
<!-- Add Resources Here -->
|
||||
<SolidColorBrush x:Key="BannerInformationBackground" Color="#EAF5FF" />
|
||||
<SolidColorBrush x:Key="BannerInformationBorderBrush" Color="#0077FA" />
|
||||
<SolidColorBrush x:Key="BannerSuccessBackground" Color="#ECF7EC" />
|
||||
<SolidColorBrush x:Key="BannerSuccessBorderBrush" Color="#3BB346" />
|
||||
<SolidColorBrush x:Key="BannerWarningBackground" Color="#FFF8EA" />
|
||||
<SolidColorBrush x:Key="BannerWarningBorderBrush" Color="#FC8800" />
|
||||
<SolidColorBrush x:Key="BannerErrorBackground" Color="#FEF2ED" />
|
||||
<SolidColorBrush x:Key="BannerErrorBorderBrush" Color="#F93920" />
|
||||
<SolidColorBrush x:Key="BannerSuccessBackground" Color="#ECF7EC" />
|
||||
<SolidColorBrush x:Key="BannerSuccessBorderBrush" Color="#3BB346" />
|
||||
|
||||
<SolidColorBrush x:Key="BannerCloseButtonForeground" Opacity="0.62" Color="#1C1F23" />
|
||||
</ResourceDictionary>
|
||||
|
||||
5
src/Ursa.Themes.Semi/Themes/Light/Dialog.axaml
Normal file
5
src/Ursa.Themes.Semi/Themes/Light/Dialog.axaml
Normal file
@@ -0,0 +1,5 @@
|
||||
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<!-- Add Resources Here -->
|
||||
<SolidColorBrush x:Key="OverlayDialogMaskBrush" Color="#FF555B61" Opacity="0.2"></SolidColorBrush>
|
||||
</ResourceDictionary>
|
||||
@@ -4,6 +4,7 @@
|
||||
<MergeResourceInclude Source="Badge.axaml" />
|
||||
<MergeResourceInclude Source="Banner.axaml" />
|
||||
<MergeResourceInclude Source="ButtonGroup.axaml" />
|
||||
<MergeResourceInclude Source="Dialog.axaml" />
|
||||
<MergeResourceInclude Source="Divider.axaml" />
|
||||
<MergeResourceInclude Source="DualBadge.axaml" />
|
||||
<MergeResourceInclude Source="IPv4Box.axaml" />
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
<ResourceDictionary xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<!-- Add Resources Here -->
|
||||
<x:Double x:Key="BadgeHeight">18</x:Double>
|
||||
<ResourceDictionary
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:common="clr-namespace:Ursa.Common;assembly=Ursa">
|
||||
<x:Double x:Key="BadgeMinWidth">18</x:Double>
|
||||
<x:Double x:Key="BadgeMinHeight">18</x:Double>
|
||||
<x:Double x:Key="BadgeDotWidth">8</x:Double>
|
||||
<x:Double x:Key="BadgeDotHeight">8</x:Double>
|
||||
<Thickness x:Key="BadgePadding">6,0</Thickness>
|
||||
<Thickness x:Key="BadgeBorderThickness">1</Thickness>
|
||||
<x:Double x:Key="BadgeFontSize">8</x:Double>
|
||||
</ResourceDictionary>
|
||||
<x:Double x:Key="BadgeFontSize">10</x:Double>
|
||||
<CornerRadius x:Key="BadgeCornerRadius">100</CornerRadius>
|
||||
<common:CornerPosition x:Key="BadgeCornerPosition">TopRight</common:CornerPosition>
|
||||
</ResourceDictionary>
|
||||
@@ -1,9 +1,9 @@
|
||||
<ResourceDictionary xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<!-- Add Resources Here -->
|
||||
<PathGeometry x:Key="BannerInformationIconGeometry">M12 23C18.0751 23 23 18.0751 23 12C23 5.92487 18.0751 1 12 1C5.92487 1 1 5.92487 1 12C1 18.0751 5.92487 23 12 23ZM14 7C14 8.10457 13.1046 9 12 9C10.8954 9 10 8.10457 10 7C10 5.89543 10.8954 5 12 5C13.1046 5 14 5.89543 14 7ZM9 10.75C9 10.3358 9.33579 10 9.75 10H12.5C13.0523 10 13.5 10.4477 13.5 11V16.5H14.25C14.6642 16.5 15 16.8358 15 17.25C15 17.6642 14.6642 18 14.25 18H9.75C9.33579 18 9 17.6642 9 17.25C9 16.8358 9.33579 16.5 9.75 16.5H10.5V11.5H9.75C9.33579 11.5 9 11.1642 9 10.75Z</PathGeometry>
|
||||
<PathGeometry x:Key="BannerSuccessIconGeometry">M23 12C23 18.0751 18.0751 23 12 23C5.92487 23 1 18.0751 1 12C1 5.92487 5.92487 1 12 1C18.0751 1 23 5.92487 23 12ZM13.5 17.5C13.5 16.6716 12.8284 16 12 16C11.1716 16 10.5 16.6716 10.5 17.5C10.5 18.3284 11.1716 19 12 19C12.8284 19 13.5 18.3284 13.5 17.5ZM12 5C10.9138 5 10.0507 5.91244 10.1109 6.99692L10.4168 12.5023C10.4635 13.3426 11.1584 14 12 14C12.8416 14 13.5365 13.3426 13.5832 12.5023L13.8891 6.99692C13.9493 5.91244 13.0862 5 12 5Z</PathGeometry>
|
||||
<PathGeometry x:Key="BannerWarningIconGeometry">M12 23C18.0751 23 23 18.0751 23 12C23 5.92487 18.0751 1 12 1C5.92487 1 1 5.92487 1 12C1 18.0751 5.92487 23 12 23ZM17.8831 9.82235L11.6854 17.4112C11.4029 17.7806 10.965 17.9981 10.5 18C10.035 18.0019 9.59533 17.788 9.30982 17.421L5.81604 13.4209C5.30744 12.767 5.42524 11.8246 6.07916 11.316C6.73308 10.8074 7.67549 10.9252 8.1841 11.5791L10.4838 14.0439L15.5 8C16.0032 7.34193 16.9446 7.21641 17.6027 7.71964C18.2608 8.22287 18.3863 9.16428 17.8831 9.82235Z</PathGeometry>
|
||||
<PathGeometry x:Key="BannerErrorIconGeometry">M10.2268 2.3986L1.52616 19.0749C0.831449 20.4064 1.79747 22 3.29933 22H20.7007C22.2025 22 23.1686 20.4064 22.4739 19.0749L13.7732 2.3986C13.0254 0.965441 10.9746 0.965442 10.2268 2.3986ZM13.1415 14.0101C13.0603 14.5781 12.5739 15 12.0001 15C11.4263 15 10.9398 14.5781 10.8586 14.0101L10.2829 9.97992C10.1336 8.93495 10.9445 8.00002 12.0001 8.00002C13.0556 8.00002 13.8665 8.93495 13.7172 9.97992L13.1415 14.0101ZM13.5001 18.5C13.5001 19.3284 12.8285 20 12.0001 20C11.1716 20 10.5001 19.3284 10.5001 18.5C10.5001 17.6716 11.1716 17 12.0001 17C12.8285 17 13.5001 17.6716 13.5001 18.5Z</PathGeometry>
|
||||
<PathGeometry x:Key="BannerSuccessIconGeometry">M23 12C23 18.0751 18.0751 23 12 23C5.92487 23 1 18.0751 1 12C1 5.92487 5.92487 1 12 1C18.0751 1 23 5.92487 23 12ZM13.5 17.5C13.5 16.6716 12.8284 16 12 16C11.1716 16 10.5 16.6716 10.5 17.5C10.5 18.3284 11.1716 19 12 19C12.8284 19 13.5 18.3284 13.5 17.5ZM12 5C10.9138 5 10.0507 5.91244 10.1109 6.99692L10.4168 12.5023C10.4635 13.3426 11.1584 14 12 14C12.8416 14 13.5365 13.3426 13.5832 12.5023L13.8891 6.99692C13.9493 5.91244 13.0862 5 12 5Z</PathGeometry>
|
||||
<PathGeometry x:Key="BannerCloseIconGeometry">M 17.6568 19.7782 C 18.2426 20.3639 19.1924 20.3639 19.7782 19.7782 C 20.3639 19.1924 20.3639 18.2426 19.7782 17.6568 L 14.1213 12 L 19.7782 6.34313 C 20.3639 5.75734 20.3639 4.8076 19.7782 4.22181 C 19.1924 3.63602 18.2426 3.63602 17.6568 4.22181 L 12 9.87866 L 6.34313 4.22181 C 5.75734 3.63602 4.8076 3.63602 4.22181 4.22181 C 3.63602 4.8076 3.63602 5.75734 4.22181 6.34313 L 9.87866 12 L 4.22181 17.6568 C 3.63602 18.2426 3.63602 19.1924 4.22181 19.7782 C 4.8076 20.3639 5.75734 20.3639 6.34313 19.7782 L 12 14.1213 L 17.6568 19.7782 Z</PathGeometry>
|
||||
|
||||
<CornerRadius x:Key="BannerCornerRadius">3</CornerRadius>
|
||||
|
||||
8
src/Ursa.Themes.Semi/Themes/Shared/Dialog.axaml
Normal file
8
src/Ursa.Themes.Semi/Themes/Shared/Dialog.axaml
Normal file
@@ -0,0 +1,8 @@
|
||||
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<!-- Add Resources Here -->
|
||||
<StreamGeometry x:Key="DialogArrangeBringForwardGlyph">M2,2H16V16H2V2M22,8V22H8V18H10V20H20V10H18V8H22Z</StreamGeometry>
|
||||
<StreamGeometry x:Key="DialogArrangeBringToFrontGlyph">M2,2H11V6H9V4H4V9H6V11H2V2M22,13V22H13V18H15V20H20V15H18V13H22M8,8H16V16H8V8Z</StreamGeometry>
|
||||
<StreamGeometry x:Key="DialogArrangeSendBackwardGlyph">M2,2H16V16H2V2M22,8V22H8V18H18V8H22M4,4V14H14V4H4Z</StreamGeometry>
|
||||
<StreamGeometry x:Key="DialogArrangeSendToBackGlyph">M2,2H11V11H2V2M9,4H4V9H9V4M22,13V22H13V13H22M15,20H20V15H15V20M16,8V11H13V8H16M11,16H8V13H11V16Z</StreamGeometry>
|
||||
</ResourceDictionary>
|
||||
8
src/Ursa.Themes.Semi/Themes/Shared/DialogShared.axaml
Normal file
8
src/Ursa.Themes.Semi/Themes/Shared/DialogShared.axaml
Normal file
@@ -0,0 +1,8 @@
|
||||
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<StreamGeometry x:Key="DialogQuestionIconGlyph">M12 23C18.0751 23 23 18.0751 23 12C23 5.92487 18.0751 1 12 1C5.92487 1 1 5.92487 1 12C1 18.0751 5.92487 23 12 23ZM11.8281 14.6094C10.9688 14.6094 10.5391 14.0723 10.5391 13.3691C10.5391 12.3242 11.0566 11.6504 12.2676 10.7324C12.2894 10.7158 12.3111 10.6993 12.3326 10.6829C13.1573 10.0555 13.7324 9.61807 13.7324 8.82812C13.7324 7.93945 12.9023 7.42188 11.9746 7.42188C11.2129 7.42188 10.627 7.70508 10.168 8.30078C9.83594 8.64258 9.57227 8.82812 9.12305 8.82812C8.38086 8.82812 8 8.31055 8 7.71484C8 7.10938 8.3418 6.49414 8.87891 6.02539C9.60156 5.40039 10.7539 5 12.2773 5C14.9922 5 16.8965 6.33789 16.8965 8.64258C16.8965 10.3223 15.8906 11.1328 14.709 11.9531C13.9082 12.5391 13.5273 12.8809 13.2246 13.5742L13.2238 13.5756C12.8922 14.1609 12.638 14.6094 11.8281 14.6094ZM11.8086 18.7695C10.8711 18.7695 10.0996 18.1641 10.0996 17.2266C10.0996 16.2891 10.8711 15.6836 11.8086 15.6836C12.7461 15.6836 13.5078 16.2891 13.5078 17.2266C13.5078 18.1641 12.7461 18.7695 11.8086 18.7695Z</StreamGeometry>
|
||||
<StreamGeometry x:Key="DialogInformationIconGlyph">M12 23C18.0751 23 23 18.0751 23 12C23 5.92487 18.0751 1 12 1C5.92487 1 1 5.92487 1 12C1 18.0751 5.92487 23 12 23ZM14 7C14 8.10457 13.1046 9 12 9C10.8954 9 10 8.10457 10 7C10 5.89543 10.8954 5 12 5C13.1046 5 14 5.89543 14 7ZM9 10.75C9 10.3358 9.33579 10 9.75 10H12.5C13.0523 10 13.5 10.4477 13.5 11V16.5H14.25C14.6642 16.5 15 16.8358 15 17.25C15 17.6642 14.6642 18 14.25 18H9.75C9.33579 18 9 17.6642 9 17.25C9 16.8358 9.33579 16.5 9.75 16.5H10.5V11.5H9.75C9.33579 11.5 9 11.1642 9 10.75Z</StreamGeometry>
|
||||
<StreamGeometry x:Key="DialogWarningIconGlyph">M10.2268 2.3986L1.52616 19.0749C0.831449 20.4064 1.79747 22 3.29933 22H20.7007C22.2025 22 23.1686 20.4064 22.4739 19.0749L13.7732 2.3986C13.0254 0.965441 10.9746 0.965442 10.2268 2.3986ZM13.1415 14.0101C13.0603 14.5781 12.5739 15 12.0001 15C11.4263 15 10.9398 14.5781 10.8586 14.0101L10.2829 9.97992C10.1336 8.93495 10.9445 8.00002 12.0001 8.00002C13.0556 8.00002 13.8665 8.93495 13.7172 9.97992L13.1415 14.0101ZM13.5001 18.5C13.5001 19.3284 12.8285 20 12.0001 20C11.1716 20 10.5001 19.3284 10.5001 18.5C10.5001 17.6716 11.1716 17 12.0001 17C12.8285 17 13.5001 17.6716 13.5001 18.5Z</StreamGeometry>
|
||||
<StreamGeometry x:Key="DialogErrorIconGlyph">M12 23C18.0751 23 23 18.0751 23 12C23 5.92487 18.0751 1 12 1C5.92487 1 1 5.92487 1 12C1 18.0751 5.92487 23 12 23ZM17.0352 16.8626C16.4597 17.4585 15.5101 17.4751 14.9142 16.8996L12.0368 14.121L9.25822 16.9984C8.68274 17.5943 7.73314 17.6109 7.13722 17.0354C6.5413 16.4599 6.52472 15.5103 7.1002 14.9144L9.87883 12.037L7.00147 9.2584C6.40555 8.68293 6.38897 7.73332 6.96445 7.1374C7.53992 6.54148 8.48953 6.52491 9.08545 7.10038L11.9628 9.87901L14.7414 7.00165C15.3169 6.40573 16.2665 6.38916 16.8624 6.96463C17.4584 7.54011 17.4749 8.48971 16.8995 9.08563L14.1208 11.963L16.9982 14.7416C17.5941 15.3171 17.6107 16.2667 17.0352 16.8626Z</StreamGeometry>
|
||||
<StreamGeometry x:Key="DialogSuccessIconGlyph">M12 23C18.0751 23 23 18.0751 23 12C23 5.92487 18.0751 1 12 1C5.92487 1 1 5.92487 1 12C1 18.0751 5.92487 23 12 23ZM17.8831 9.82235L11.6854 17.4112C11.4029 17.7806 10.965 17.9981 10.5 18C10.035 18.0019 9.59533 17.788 9.30982 17.421L5.81604 13.4209C5.30744 12.767 5.42524 11.8246 6.07916 11.316C6.73308 10.8074 7.67549 10.9252 8.1841 11.5791L10.4838 14.0439L15.5 8C16.0032 7.34193 16.9446 7.21641 17.6027 7.71964C18.2608 8.22287 18.3863 9.16428 17.8831 9.82235Z</StreamGeometry>
|
||||
</ResourceDictionary>
|
||||
3
src/Ursa.Themes.Semi/Themes/Shared/MessageBox.axaml
Normal file
3
src/Ursa.Themes.Semi/Themes/Shared/MessageBox.axaml
Normal file
@@ -0,0 +1,3 @@
|
||||
<ResourceDictionary xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<x:Double x:Key="MessageBoxWindowContentMaxWidth">300</x:Double>
|
||||
</ResourceDictionary>
|
||||
6
src/Ursa.Themes.Semi/Themes/Shared/ThemeSelector.axaml
Normal file
6
src/Ursa.Themes.Semi/Themes/Shared/ThemeSelector.axaml
Normal file
@@ -0,0 +1,6 @@
|
||||
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<!-- Add Resources Here -->
|
||||
<StreamGeometry x:Key="ThemeSelectorButtonDarkGlyph">M12 23C18.0751 23 23 18.0751 23 12C23 5.92487 18.0751 1 12 1C5.92487 1 1 5.92487 1 12C1 18.0751 5.92487 23 12 23ZM17 15C17.476 15 17.9408 14.9525 18.3901 14.862C17.296 17.3011 14.8464 19 12 19C8.13401 19 5 15.866 5 12C5 8.60996 7.40983 5.78277 10.6099 5.13803C10.218 6.01173 10 6.98041 10 8C10 11.866 13.134 15 17 15Z</StreamGeometry>
|
||||
<StreamGeometry x:Key="ThemeSelectorButtonLightGlyph">M3.55 19.09L4.96 20.5L6.76 18.71L5.34 17.29M12 6C8.69 6 6 8.69 6 12S8.69 18 12 18 18 15.31 18 12C18 8.68 15.31 6 12 6M20 13H23V11H20M17.24 18.71L19.04 20.5L20.45 19.09L18.66 17.29M20.45 5L19.04 3.6L17.24 5.39L18.66 6.81M13 1H11V4H13M6.76 5.39L4.96 3.6L3.55 5L5.34 6.81L6.76 5.39M1 13H4V11H1M13 20H11V23H13</StreamGeometry>
|
||||
</ResourceDictionary>
|
||||
6
src/Ursa.Themes.Semi/Themes/Shared/ToolBar.axaml
Normal file
6
src/Ursa.Themes.Semi/Themes/Shared/ToolBar.axaml
Normal file
@@ -0,0 +1,6 @@
|
||||
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<!-- Add Resources Here -->
|
||||
<StreamGeometry x:Key="ToolBarHorizontalMoreGlyph">M12,16A2,2 0 0,1 14,18A2,2 0 0,1 12,20A2,2 0 0,1 10,18A2,2 0 0,1 12,16M12,10A2,2 0 0,1 14,12A2,2 0 0,1 12,14A2,2 0 0,1 10,12A2,2 0 0,1 12,10M12,4A2,2 0 0,1 14,6A2,2 0 0,1 12,8A2,2 0 0,1 10,6A2,2 0 0,1 12,4Z</StreamGeometry>
|
||||
<StreamGeometry x:Key="ToolBarVerticalMoreGlyph">M16,12A2,2 0 0,1 18,10A2,2 0 0,1 20,12A2,2 0 0,1 18,14A2,2 0 0,1 16,12M10,12A2,2 0 0,1 12,10A2,2 0 0,1 14,12A2,2 0 0,1 12,14A2,2 0 0,1 10,12M4,12A2,2 0 0,1 6,10A2,2 0 0,1 8,12A2,2 0 0,1 6,14A2,2 0 0,1 4,12Z</StreamGeometry>
|
||||
</ResourceDictionary>
|
||||
@@ -4,13 +4,18 @@
|
||||
<MergeResourceInclude Source="Badge.axaml" />
|
||||
<MergeResourceInclude Source="Banner.axaml" />
|
||||
<MergeResourceInclude Source="ButtonGroup.axaml" />
|
||||
<MergeResourceInclude Source="Dialog.axaml" />
|
||||
<MergeResourceInclude Source="DialogShared.axaml" />
|
||||
<MergeResourceInclude Source="Divider.axaml" />
|
||||
<MergeResourceInclude Source="DualBadge.axaml" />
|
||||
<MergeResourceInclude Source="IPv4Box.axaml" />
|
||||
<MergeResourceInclude Source="KeyGestureInput.axaml" />
|
||||
<MergeResourceInclude Source="MessageBox.axaml" />
|
||||
<MergeResourceInclude Source="NavigationMenu.axaml" />
|
||||
<MergeResourceInclude Source="Pagination.axaml" />
|
||||
<MergeResourceInclude Source="TagInput.axaml" />
|
||||
<MergeResourceInclude Source="Skeleton.axaml" />
|
||||
<MergeResourceInclude Source="ThemeSelector.axaml" />
|
||||
<MergeResourceInclude Source="ToolBar.axaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>11</LangVersion>
|
||||
<Version>0.1.0-beta20230702</Version>
|
||||
<Version>0.2.0-beta20240213</Version>
|
||||
<Authors>IRIHI Technology Co., Ltd.</Authors>
|
||||
<PackageId>Irihi.Ursa.Themes.Semi</PackageId>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -3,3 +3,4 @@ using Avalonia.Metadata;
|
||||
[assembly:XmlnsPrefix("https://irihi.tech/ursa", "u")]
|
||||
[assembly:XmlnsDefinition("https://irihi.tech/ursa", "Ursa")]
|
||||
[assembly:XmlnsDefinition("https://irihi.tech/ursa", "Ursa.Controls")]
|
||||
[assembly:XmlnsDefinition("https://irihi.tech/ursa", "Ursa.Controls.Shapes")]
|
||||
9
src/Ursa/Common/Position.cs
Normal file
9
src/Ursa/Common/Position.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace Ursa.Common;
|
||||
|
||||
public enum Position
|
||||
{
|
||||
Left,
|
||||
Top,
|
||||
Right,
|
||||
Bottom,
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Presenters;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Media;
|
||||
@@ -10,18 +9,14 @@ using Ursa.Common;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
[TemplatePart(PART_ContentPresenter, typeof(ContentPresenter))]
|
||||
[TemplatePart(PART_BadgeContainer, typeof(Border))]
|
||||
[TemplatePart(PART_BadgeContentPresenter, typeof(ContentPresenter))]
|
||||
public class Badge: ContentControl
|
||||
public class Badge: HeaderedContentControl
|
||||
{
|
||||
public const string PART_ContentPresenter = "PART_ContentPresenter";
|
||||
public const string PART_BadgeContainer = "PART_BadgeContainer";
|
||||
public const string PART_BadgeContentPresenter = "PART_BadgeContentPresenter";
|
||||
|
||||
private ContentPresenter? _content;
|
||||
public const string PART_HeaderPresenter = "PART_HeaderPresenter";
|
||||
|
||||
private Border? _badgeContainer;
|
||||
private ContentPresenter? _badgeContent;
|
||||
|
||||
public static readonly StyledProperty<ControlTheme> BadgeThemeProperty = AvaloniaProperty.Register<Badge, ControlTheme>(
|
||||
nameof(BadgeTheme));
|
||||
@@ -39,14 +34,6 @@ public class Badge: ContentControl
|
||||
set => SetValue(DotProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<object?> BadgeContentProperty = AvaloniaProperty.Register<Badge, object?>(
|
||||
nameof(BadgeContent));
|
||||
public object? BadgeContent
|
||||
{
|
||||
get => GetValue(BadgeContentProperty);
|
||||
set => SetValue(BadgeContentProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<CornerPosition> CornerPositionProperty = AvaloniaProperty.Register<Badge, CornerPosition>(
|
||||
nameof(CornerPosition));
|
||||
public CornerPosition CornerPosition
|
||||
@@ -63,17 +50,24 @@ public class Badge: ContentControl
|
||||
set => SetValue(OverflowCountProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<double> BadgeFontSizeProperty = AvaloniaProperty.Register<Badge, double>(
|
||||
nameof(BadgeFontSize));
|
||||
|
||||
public double BadgeFontSize
|
||||
{
|
||||
get => GetValue(BadgeFontSizeProperty);
|
||||
set => SetValue(BadgeFontSizeProperty, value);
|
||||
}
|
||||
|
||||
static Badge()
|
||||
{
|
||||
BadgeContentProperty.Changed.AddClassHandler<Badge>((badge, args) => badge.UpdateBadgePosition());
|
||||
HeaderProperty.Changed.AddClassHandler<Badge>((badge, args) => badge.UpdateBadgePosition());
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
_content = e.NameScope.Find<ContentPresenter>(PART_ContentPresenter);
|
||||
_badgeContainer = e.NameScope.Find<Border>(PART_BadgeContainer);
|
||||
_badgeContent = e.NameScope.Find<ContentPresenter>(PART_BadgeContentPresenter);
|
||||
}
|
||||
|
||||
protected override void OnLoaded(RoutedEventArgs e)
|
||||
@@ -92,7 +86,7 @@ public class Badge: ContentControl
|
||||
{
|
||||
var vertical = CornerPosition is CornerPosition.BottomLeft or CornerPosition.BottomRight ? 1 : -1;
|
||||
var horizontal = CornerPosition is CornerPosition.TopRight or CornerPosition.BottomRight ? 1 : -1;
|
||||
if (_badgeContainer is not null && _content?.Child is not null)
|
||||
if (_badgeContainer is not null && base.Presenter?.Child is not null)
|
||||
{
|
||||
_badgeContainer.RenderTransform = new TransformGroup()
|
||||
{
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
using System.Net.Http.Headers;
|
||||
using Avalonia;
|
||||
using Avalonia.Collections;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Metadata;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public class ButtonGroup: ItemsControl
|
||||
{
|
||||
protected override bool NeedsContainerOverride(object? item, int index, out object? recycleKey)
|
||||
{
|
||||
recycleKey = null;
|
||||
return item is not Button;
|
||||
}
|
||||
|
||||
protected override Control CreateContainerForItemOverride(object? item, int index, object? recycleKey)
|
||||
{
|
||||
return new Button();
|
||||
}
|
||||
}
|
||||
71
src/Ursa/Controls/Buttons/ButtonGroup.cs
Normal file
71
src/Ursa/Controls/Buttons/ButtonGroup.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
using System.Net.Http.Headers;
|
||||
using Avalonia;
|
||||
using Avalonia.Collections;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Metadata;
|
||||
using Irihi.Avalonia.Shared.Helpers;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public class ButtonGroup: ItemsControl
|
||||
{
|
||||
public static readonly StyledProperty<IBinding?> CommandBindingProperty = AvaloniaProperty.Register<ButtonGroup, IBinding?>(
|
||||
nameof(CommandBinding));
|
||||
|
||||
[AssignBinding]
|
||||
[InheritDataTypeFromItems(nameof(ItemsSource))]
|
||||
public IBinding? CommandBinding
|
||||
{
|
||||
get => GetValue(CommandBindingProperty);
|
||||
set => SetValue(CommandBindingProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IBinding?> CommandParameterBindingProperty = AvaloniaProperty.Register<ButtonGroup, IBinding?>(
|
||||
nameof(CommandParameterBinding));
|
||||
|
||||
[AssignBinding]
|
||||
[InheritDataTypeFromItems(nameof(ItemsSource))]
|
||||
public IBinding? CommandParameterBinding
|
||||
{
|
||||
get => GetValue(CommandParameterBindingProperty);
|
||||
set => SetValue(CommandParameterBindingProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IBinding?> ContentBindingProperty = AvaloniaProperty.Register<ButtonGroup, IBinding?>(
|
||||
nameof(ContentBinding));
|
||||
|
||||
[AssignBinding]
|
||||
[InheritDataTypeFromItems(nameof(ItemsSource))]
|
||||
public IBinding? ContentBinding
|
||||
{
|
||||
get => GetValue(ContentBindingProperty);
|
||||
set => SetValue(ContentBindingProperty, value);
|
||||
}
|
||||
|
||||
|
||||
protected override bool NeedsContainerOverride(object? item, int index, out object? recycleKey)
|
||||
{
|
||||
recycleKey = null;
|
||||
return item is not Button;
|
||||
}
|
||||
|
||||
protected override Control CreateContainerForItemOverride(object? item, int index, object? recycleKey)
|
||||
{
|
||||
return new Button();
|
||||
}
|
||||
|
||||
protected override void PrepareContainerForItemOverride(Control container, object? item, int index)
|
||||
{
|
||||
base.PrepareContainerForItemOverride(container, item, index);
|
||||
if(container is Button button)
|
||||
{
|
||||
button.TryBind(Button.CommandProperty, CommandBinding);
|
||||
button.TryBind(Button.CommandParameterProperty, CommandParameterBinding);
|
||||
button.TryBind(ContentControl.ContentProperty, ContentBinding);
|
||||
button.TryBind(ContentControl.ContentTemplateProperty, this[!ItemTemplateProperty]);
|
||||
}
|
||||
}
|
||||
}
|
||||
91
src/Ursa/Controls/Buttons/IconButton.cs
Normal file
91
src/Ursa/Controls/Buttons/IconButton.cs
Normal file
@@ -0,0 +1,91 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Controls.Templates;
|
||||
using Avalonia.Layout;
|
||||
using Ursa.Common;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
[PseudoClasses(PC_Right, PC_Left, PC_Top, PC_Bottom, PC_Empty)]
|
||||
public class IconButton: Button
|
||||
{
|
||||
public const string PC_Right = ":right";
|
||||
public const string PC_Left = ":left";
|
||||
public const string PC_Top = ":top";
|
||||
public const string PC_Bottom = ":bottom";
|
||||
public const string PC_Empty = ":empty";
|
||||
|
||||
public static readonly StyledProperty<object?> IconProperty = AvaloniaProperty.Register<IconButton, object?>(
|
||||
nameof(Icon));
|
||||
|
||||
public object? Icon
|
||||
{
|
||||
get => GetValue(IconProperty);
|
||||
set => SetValue(IconProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IDataTemplate?> IconTemplateProperty = AvaloniaProperty.Register<IconButton, IDataTemplate?>(
|
||||
nameof(IconTemplate));
|
||||
|
||||
public IDataTemplate? IconTemplate
|
||||
{
|
||||
get => GetValue(IconTemplateProperty);
|
||||
set => SetValue(IconTemplateProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<bool> IsLoadingProperty = AvaloniaProperty.Register<IconButton, bool>(
|
||||
nameof(IsLoading));
|
||||
|
||||
public bool IsLoading
|
||||
{
|
||||
get => GetValue(IsLoadingProperty);
|
||||
set => SetValue(IsLoadingProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<Position> IconPlacementProperty = AvaloniaProperty.Register<IconButton, Position>(
|
||||
nameof(IconPlacement), defaultValue: Position.Left);
|
||||
|
||||
public Position IconPlacement
|
||||
{
|
||||
get => GetValue(IconPlacementProperty);
|
||||
set => SetValue(IconPlacementProperty, value);
|
||||
}
|
||||
|
||||
static IconButton()
|
||||
{
|
||||
IconPlacementProperty.Changed.AddClassHandler<IconButton, Position>((o, e) =>
|
||||
{
|
||||
o.SetPlacement(e.NewValue.Value, o.Icon);
|
||||
});
|
||||
IconProperty.Changed.AddClassHandler<IconButton, object?>((o, e) =>
|
||||
{
|
||||
o.SetPlacement(o.IconPlacement, e.NewValue.Value);
|
||||
});
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
SetPlacement(IconPlacement, Icon);
|
||||
}
|
||||
|
||||
private void SetPlacement(Position placement, object? icon)
|
||||
{
|
||||
if (icon is null)
|
||||
{
|
||||
PseudoClasses.Set(PC_Empty, true);
|
||||
PseudoClasses.Set(PC_Left, false);
|
||||
PseudoClasses.Set(PC_Right, false);
|
||||
PseudoClasses.Set(PC_Top, false);
|
||||
PseudoClasses.Set(PC_Bottom, false);
|
||||
return;
|
||||
}
|
||||
PseudoClasses.Set(PC_Empty, false);
|
||||
PseudoClasses.Set(PC_Left, placement == Position.Left);
|
||||
PseudoClasses.Set(PC_Right, placement == Position.Right);
|
||||
PseudoClasses.Set(PC_Top, placement == Position.Top);
|
||||
PseudoClasses.Set(PC_Bottom, placement == Position.Bottom);
|
||||
}
|
||||
}
|
||||
177
src/Ursa/Controls/ControlClassesInput/ControlClassesInput.cs
Normal file
177
src/Ursa/Controls/ControlClassesInput/ControlClassesInput.cs
Normal file
@@ -0,0 +1,177 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using Avalonia;
|
||||
using Avalonia.Collections;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public class ControlClassesInput: TemplatedControl
|
||||
{
|
||||
LinkedList<List<string>> _history = new();
|
||||
LinkedList<List<string>> _undoHistory = new();
|
||||
private bool _disableHistory = false;
|
||||
|
||||
public int CountOfHistoricalRecord { get; set; } = 10;
|
||||
|
||||
public static readonly StyledProperty<Control?> TargetProperty = AvaloniaProperty.Register<ControlClassesInput, Control?>(
|
||||
nameof(Target));
|
||||
|
||||
public Control? Target
|
||||
{
|
||||
get => GetValue(TargetProperty);
|
||||
set => SetValue(TargetProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<string> SeparatorProperty =
|
||||
TagInput.SeparatorProperty.AddOwner<ControlClassesInput>();
|
||||
|
||||
public string Separator
|
||||
{
|
||||
get => GetValue(SeparatorProperty);
|
||||
set => SetValue(SeparatorProperty, value);
|
||||
}
|
||||
|
||||
|
||||
private ObservableCollection<string> _targetClasses;
|
||||
|
||||
internal static readonly DirectProperty<ControlClassesInput, ObservableCollection<string>> TargetClassesProperty = AvaloniaProperty.RegisterDirect<ControlClassesInput, ObservableCollection<string>>(
|
||||
nameof(TargetClasses), o => o.TargetClasses, (o, v) => o.TargetClasses = v);
|
||||
|
||||
internal ObservableCollection<string> TargetClasses
|
||||
{
|
||||
get => _targetClasses;
|
||||
set => SetAndRaise(TargetClassesProperty, ref _targetClasses, value);
|
||||
}
|
||||
|
||||
public static readonly AttachedProperty<ControlClassesInput?> SourceProperty =
|
||||
AvaloniaProperty.RegisterAttached<ControlClassesInput, StyledElement, ControlClassesInput?>("Source");
|
||||
|
||||
public static void SetSource(StyledElement obj, ControlClassesInput value) => obj.SetValue(SourceProperty, value);
|
||||
public static ControlClassesInput? GetSource(StyledElement obj) => obj.GetValue(SourceProperty);
|
||||
|
||||
static ControlClassesInput()
|
||||
{
|
||||
TargetClassesProperty.Changed.AddClassHandler<ControlClassesInput, ObservableCollection<string>>((o,e)=>o.OnClassesChanged(e));
|
||||
SourceProperty.Changed.AddClassHandler<StyledElement, ControlClassesInput?>(HandleSourceChange);
|
||||
}
|
||||
|
||||
public ControlClassesInput()
|
||||
{
|
||||
TargetClasses = new ObservableCollection<string>();
|
||||
//TargetClasses.CollectionChanged += InccOnCollectionChanged;
|
||||
}
|
||||
|
||||
private List<StyledElement> _targets = new();
|
||||
|
||||
private static void HandleSourceChange(StyledElement arg1, AvaloniaPropertyChangedEventArgs<ControlClassesInput?> arg2)
|
||||
{
|
||||
var newControl = arg2.NewValue.Value;
|
||||
if (newControl is null) return;
|
||||
newControl._targets.Add(arg1);
|
||||
var oldControl = arg2.OldValue.Value;
|
||||
if (oldControl is not null)
|
||||
{
|
||||
newControl._targets.Remove(oldControl);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnClassesChanged(AvaloniaPropertyChangedEventArgs<ObservableCollection<string>?> args)
|
||||
{
|
||||
var newValue = args.NewValue.Value;
|
||||
if (newValue is null)
|
||||
{
|
||||
SaveHistory(new List<string>(), true);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
var classes = newValue.Where(a => !string.IsNullOrWhiteSpace(a)).Distinct().ToList();
|
||||
SaveHistory(classes, true);
|
||||
if (newValue is INotifyCollectionChanged incc)
|
||||
{
|
||||
incc.CollectionChanged+=InccOnCollectionChanged;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void InccOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
if(_disableHistory) return;
|
||||
SaveHistory(TargetClasses?.ToList() ?? new List<string>(), true);
|
||||
}
|
||||
|
||||
private void SaveHistory(List<string> strings, bool fromInput)
|
||||
{
|
||||
_history.AddLast(strings);
|
||||
_undoHistory.Clear();
|
||||
if (_history.Count > CountOfHistoricalRecord)
|
||||
{
|
||||
_history.RemoveFirst();
|
||||
}
|
||||
SetClassesToTarget(fromInput);
|
||||
}
|
||||
|
||||
private void SetClassesToTarget(bool fromInput)
|
||||
{
|
||||
List<string> strings;
|
||||
if (_history.Count == 0)
|
||||
{
|
||||
strings = new List<string>();
|
||||
}
|
||||
else
|
||||
{
|
||||
strings = _history.Last.Value;
|
||||
}
|
||||
|
||||
if (!fromInput)
|
||||
{
|
||||
SetCurrentValue(TargetClassesProperty, new ObservableCollection<string>(strings));
|
||||
}
|
||||
if (Target is not null)
|
||||
{
|
||||
Target.Classes.Replace(strings);
|
||||
}
|
||||
foreach (var target in _targets)
|
||||
{
|
||||
target.Classes.Replace(strings);
|
||||
}
|
||||
}
|
||||
|
||||
public void UnDo()
|
||||
{
|
||||
var node = _history.Last;
|
||||
_history.RemoveLast();
|
||||
_undoHistory.AddFirst(node);
|
||||
_disableHistory = true;
|
||||
TargetClasses.Clear();
|
||||
foreach (var value in _history.Last.Value)
|
||||
{
|
||||
TargetClasses.Add(value);
|
||||
}
|
||||
_disableHistory = false;
|
||||
SetClassesToTarget(false);
|
||||
}
|
||||
|
||||
public void Redo()
|
||||
{
|
||||
var node = _undoHistory.First;
|
||||
_undoHistory.RemoveFirst();
|
||||
_history.AddLast(node);
|
||||
_disableHistory = true;
|
||||
TargetClasses.Clear();
|
||||
foreach (var value in _history.Last.Value)
|
||||
{
|
||||
TargetClasses.Add(value);
|
||||
}
|
||||
_disableHistory = false;
|
||||
SetClassesToTarget(false);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
SaveHistory(new List<string>(), false);
|
||||
}
|
||||
}
|
||||
40
src/Ursa/Controls/Dialog/CustomDialogControl.cs
Normal file
40
src/Ursa/Controls/Dialog/CustomDialogControl.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Input.GestureRecognizers;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Threading;
|
||||
using Irihi.Avalonia.Shared.Contracts;
|
||||
using Ursa.Common;
|
||||
using Ursa.Controls.OverlayShared;
|
||||
using Ursa.EventArgs;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public class CustomDialogControl: DialogControlBase
|
||||
{
|
||||
internal bool IsCloseButtonVisible { get; set; }
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
if (_closeButton is not null)
|
||||
{
|
||||
_closeButton.IsVisible = IsCloseButtonVisible;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
if (DataContext is IDialogContext context)
|
||||
{
|
||||
context.Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
OnElementClosing(this, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
141
src/Ursa/Controls/Dialog/DefaultDialogControl.cs
Normal file
141
src/Ursa/Controls/Dialog/DefaultDialogControl.cs
Normal file
@@ -0,0 +1,141 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Irihi.Avalonia.Shared.Contracts;
|
||||
using Irihi.Avalonia.Shared.Helpers;
|
||||
using Ursa.Common;
|
||||
using Ursa.EventArgs;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
[TemplatePart(PART_OKButton, typeof(Button))]
|
||||
[TemplatePart(PART_CancelButton, typeof(Button))]
|
||||
[TemplatePart(PART_YesButton, typeof(Button))]
|
||||
[TemplatePart(PART_NoButton, typeof(Button))]
|
||||
public class DefaultDialogControl: DialogControlBase
|
||||
{
|
||||
public const string PART_OKButton = "PART_OKButton";
|
||||
public const string PART_CancelButton = "PART_CancelButton";
|
||||
public const string PART_YesButton = "PART_YesButton";
|
||||
public const string PART_NoButton = "PART_NoButton";
|
||||
|
||||
private Button? _okButton;
|
||||
private Button? _cancelButton;
|
||||
private Button? _yesButton;
|
||||
private Button? _noButton;
|
||||
|
||||
public static readonly StyledProperty<string?> TitleProperty = AvaloniaProperty.Register<DefaultDialogControl, string?>(
|
||||
nameof(Title));
|
||||
|
||||
public string? Title
|
||||
{
|
||||
get => GetValue(TitleProperty);
|
||||
set => SetValue(TitleProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<DialogButton> ButtonsProperty = AvaloniaProperty.Register<DefaultDialogControl, DialogButton>(
|
||||
nameof(Buttons));
|
||||
|
||||
public DialogButton Buttons
|
||||
{
|
||||
get => GetValue(ButtonsProperty);
|
||||
set => SetValue(ButtonsProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<DialogMode> ModeProperty = AvaloniaProperty.Register<DefaultDialogControl, DialogMode>(
|
||||
nameof(Mode));
|
||||
|
||||
public DialogMode Mode
|
||||
{
|
||||
get => GetValue(ModeProperty);
|
||||
set => SetValue(ModeProperty, value);
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
Button.ClickEvent.RemoveHandler(DefaultButtonsClose, _okButton, _cancelButton, _yesButton, _noButton);
|
||||
_okButton = e.NameScope.Find<Button>(PART_OKButton);
|
||||
_cancelButton = e.NameScope.Find<Button>(PART_CancelButton);
|
||||
_yesButton = e.NameScope.Find<Button>(PART_YesButton);
|
||||
_noButton = e.NameScope.Find<Button>(PART_NoButton);
|
||||
Button.ClickEvent.AddHandler(DefaultButtonsClose, _okButton, _cancelButton, _yesButton, _noButton);
|
||||
SetButtonVisibility();
|
||||
}
|
||||
|
||||
|
||||
private void SetButtonVisibility()
|
||||
{
|
||||
bool isCloseButtonVisible = DataContext is IDialogContext || Buttons != DialogButton.YesNo;
|
||||
Button.IsVisibleProperty.SetValue(isCloseButtonVisible, _closeButton);
|
||||
switch (Buttons)
|
||||
{
|
||||
case DialogButton.None:
|
||||
Button.IsVisibleProperty.SetValue(false, _okButton, _cancelButton, _yesButton, _noButton);
|
||||
break;
|
||||
case DialogButton.OK:
|
||||
Button.IsVisibleProperty.SetValue(true, _okButton);
|
||||
Button.IsVisibleProperty.SetValue(false, _cancelButton, _yesButton, _noButton);
|
||||
break;
|
||||
case DialogButton.OKCancel:
|
||||
Button.IsVisibleProperty.SetValue(true, _okButton, _cancelButton);
|
||||
Button.IsVisibleProperty.SetValue(false, _yesButton, _noButton);
|
||||
break;
|
||||
case DialogButton.YesNo:
|
||||
Button.IsVisibleProperty.SetValue(false, _okButton, _cancelButton);
|
||||
Button.IsVisibleProperty.SetValue(true, _yesButton, _noButton);
|
||||
break;
|
||||
case DialogButton.YesNoCancel:
|
||||
Button.IsVisibleProperty.SetValue(false, _okButton);
|
||||
Button.IsVisibleProperty.SetValue(true, _cancelButton, _yesButton, _noButton);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void DefaultButtonsClose(object sender, RoutedEventArgs args)
|
||||
{
|
||||
if (sender is Button button)
|
||||
{
|
||||
if (button == _okButton)
|
||||
{
|
||||
OnElementClosing(this, DialogResult.OK);
|
||||
}
|
||||
else if (button == _cancelButton)
|
||||
{
|
||||
OnElementClosing(this, DialogResult.Cancel);
|
||||
}
|
||||
else if (button == _yesButton)
|
||||
{
|
||||
OnElementClosing(this, DialogResult.Yes);
|
||||
}
|
||||
else if (button == _noButton)
|
||||
{
|
||||
OnElementClosing(this, DialogResult.No);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
if (DataContext is IDialogContext context)
|
||||
{
|
||||
context.Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
DialogResult result = Buttons switch
|
||||
{
|
||||
DialogButton.None => DialogResult.None,
|
||||
DialogButton.OK => DialogResult.OK,
|
||||
DialogButton.OKCancel => DialogResult.Cancel,
|
||||
DialogButton.YesNo => DialogResult.No,
|
||||
DialogButton.YesNoCancel => DialogResult.Cancel,
|
||||
_ => DialogResult.None
|
||||
};
|
||||
OnElementClosing(this, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
148
src/Ursa/Controls/Dialog/DefaultDialogWindow.cs
Normal file
148
src/Ursa/Controls/Dialog/DefaultDialogWindow.cs
Normal file
@@ -0,0 +1,148 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Interactivity;
|
||||
using Irihi.Avalonia.Shared.Contracts;
|
||||
using Irihi.Avalonia.Shared.Helpers;
|
||||
using Ursa.Common;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
[TemplatePart(PART_YesButton, typeof(Button))]
|
||||
[TemplatePart(PART_NoButton, typeof(Button))]
|
||||
[TemplatePart(PART_OKButton, typeof(Button))]
|
||||
[TemplatePart(PART_CancelButton, typeof(Button))]
|
||||
public class DefaultDialogWindow: DialogWindow
|
||||
{
|
||||
protected override Type StyleKeyOverride { get; } = typeof(DefaultDialogWindow);
|
||||
|
||||
public const string PART_YesButton = "PART_YesButton";
|
||||
public const string PART_NoButton = "PART_NoButton";
|
||||
public const string PART_OKButton = "PART_OKButton";
|
||||
public const string PART_CancelButton = "PART_CancelButton";
|
||||
|
||||
private Button? _yesButton;
|
||||
private Button? _noButton;
|
||||
private Button? _okButton;
|
||||
private Button? _cancelButton;
|
||||
|
||||
public static readonly StyledProperty<DialogButton> ButtonsProperty = AvaloniaProperty.Register<DefaultDialogWindow, DialogButton>(
|
||||
nameof(Buttons));
|
||||
|
||||
public DialogButton Buttons
|
||||
{
|
||||
get => GetValue(ButtonsProperty);
|
||||
set => SetValue(ButtonsProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<DialogMode> ModeProperty = AvaloniaProperty.Register<DefaultDialogWindow, DialogMode>(
|
||||
nameof(Mode));
|
||||
|
||||
public DialogMode Mode
|
||||
{
|
||||
get => GetValue(ModeProperty);
|
||||
set => SetValue(ModeProperty, value);
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
Button.ClickEvent.RemoveHandler(OnDefaultClose, _okButton, _cancelButton, _yesButton, _noButton);
|
||||
_okButton = e.NameScope.Find<Button>(PART_OKButton);
|
||||
_cancelButton = e.NameScope.Find<Button>(PART_CancelButton);
|
||||
_yesButton = e.NameScope.Find<Button>(PART_YesButton);
|
||||
_noButton = e.NameScope.Find<Button>(PART_NoButton);
|
||||
Button.ClickEvent.AddHandler(OnDefaultClose, _okButton, _cancelButton, _yesButton, _noButton);
|
||||
SetButtonVisibility();
|
||||
}
|
||||
|
||||
private void OnDefaultClose(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender == _yesButton)
|
||||
{
|
||||
Close(DialogResult.Yes);
|
||||
return;
|
||||
}
|
||||
if(sender == _noButton)
|
||||
{
|
||||
Close(DialogResult.No);
|
||||
return;
|
||||
}
|
||||
if(sender == _okButton)
|
||||
{
|
||||
Close(DialogResult.OK);
|
||||
return;
|
||||
}
|
||||
if(sender == _cancelButton)
|
||||
{
|
||||
Close(DialogResult.Cancel);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetButtonVisibility()
|
||||
{
|
||||
bool closeButtonVisible = DataContext is IDialogContext || Buttons != DialogButton.YesNo;
|
||||
SetVisibility(_closeButton, closeButtonVisible);
|
||||
switch (Buttons)
|
||||
{
|
||||
case DialogButton.None:
|
||||
SetVisibility(_okButton, false);
|
||||
SetVisibility(_cancelButton, false);
|
||||
SetVisibility(_yesButton, false);
|
||||
SetVisibility(_noButton, false);
|
||||
break;
|
||||
case DialogButton.OK:
|
||||
SetVisibility(_okButton, true);
|
||||
SetVisibility(_cancelButton, false);
|
||||
SetVisibility(_yesButton, false);
|
||||
SetVisibility(_noButton, false);
|
||||
break;
|
||||
case DialogButton.OKCancel:
|
||||
SetVisibility(_okButton, true);
|
||||
SetVisibility(_cancelButton, true);
|
||||
SetVisibility(_yesButton, false);
|
||||
SetVisibility(_noButton, false);
|
||||
break;
|
||||
case DialogButton.YesNo:
|
||||
SetVisibility(_okButton, false);
|
||||
SetVisibility(_cancelButton, false);
|
||||
SetVisibility(_yesButton, true);
|
||||
SetVisibility(_noButton, true);
|
||||
break;
|
||||
case DialogButton.YesNoCancel:
|
||||
SetVisibility(_okButton, false);
|
||||
SetVisibility(_cancelButton, true);
|
||||
SetVisibility(_yesButton, true);
|
||||
SetVisibility(_noButton, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetVisibility(Button? button, bool visible)
|
||||
{
|
||||
if (button is not null) button.IsVisible = visible;
|
||||
}
|
||||
|
||||
protected internal override void OnCloseButtonClicked(object sender, RoutedEventArgs args)
|
||||
{
|
||||
if (DataContext is IDialogContext context)
|
||||
{
|
||||
context.Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
DialogResult result = Buttons switch
|
||||
{
|
||||
DialogButton.None => DialogResult.None,
|
||||
DialogButton.OK => DialogResult.OK,
|
||||
DialogButton.OKCancel => DialogResult.Cancel,
|
||||
DialogButton.YesNo => DialogResult.No,
|
||||
DialogButton.YesNoCancel => DialogResult.Cancel,
|
||||
_ => DialogResult.None
|
||||
};
|
||||
Close(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
237
src/Ursa/Controls/Dialog/Dialog.cs
Normal file
237
src/Ursa/Controls/Dialog/Dialog.cs
Normal file
@@ -0,0 +1,237 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Controls.Shapes;
|
||||
using Avalonia.Media;
|
||||
using Ursa.Common;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public static class Dialog
|
||||
{
|
||||
/// <summary>
|
||||
/// Show a Window Dialog that with all content fully customized. And the owner of the dialog is specified.
|
||||
/// </summary>
|
||||
/// <param name="vm">Dialog ViewModel instance</param>
|
||||
/// <param name="owner"></param>
|
||||
/// <param name="options"></param>
|
||||
/// <typeparam name="TView"></typeparam>
|
||||
/// <typeparam name="TViewModel"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static void ShowCustom<TView, TViewModel>(TViewModel? vm, Window? owner = null, DialogOptions? options = null)
|
||||
where TView: Control, new()
|
||||
{
|
||||
var window = new DialogWindow
|
||||
{
|
||||
Content = new TView(),
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureDialogWindow(window, options);
|
||||
owner ??= GetMainWindow();
|
||||
if (owner is null)
|
||||
{
|
||||
window.Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
window.Show(owner);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show a Window Dialog that with all content fully customized. And the owner of the dialog is specified.
|
||||
/// </summary>
|
||||
/// <param name="view">View to show in Dialog Window</param>
|
||||
/// <param name="vm">ViewModel</param>
|
||||
/// <param name="owner">Owner Window</param>
|
||||
/// <param name="options">Dialog options to configure the window. </param>
|
||||
public static void ShowCustom(Control view, object? vm, Window? owner = null, DialogOptions? options = null)
|
||||
{
|
||||
var window = new DialogWindow
|
||||
{
|
||||
Content = view,
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureDialogWindow(window, options);
|
||||
owner ??= GetMainWindow();
|
||||
if (owner is null)
|
||||
{
|
||||
window.Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
window.Show(owner);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show a Modal Dialog Window with default style.
|
||||
/// </summary>
|
||||
/// <param name="vm"></param>
|
||||
/// <param name="owner"></param>
|
||||
/// <param name="options"></param>
|
||||
/// <typeparam name="TView"></typeparam>
|
||||
/// <typeparam name="TViewModel"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static Task<DialogResult> ShowModal<TView, TViewModel>(TViewModel vm, Window? owner = null,
|
||||
DialogOptions? options = null)
|
||||
where TView: Control, new()
|
||||
{
|
||||
var window = new DefaultDialogWindow
|
||||
{
|
||||
Content = new TView(),
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureDefaultDialogWindow(window, options);
|
||||
owner ??= GetMainWindow();
|
||||
if (owner is null)
|
||||
{
|
||||
window.Show();
|
||||
return Task.FromResult(DialogResult.None);
|
||||
}
|
||||
return window.ShowDialog<DialogResult>(owner);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show a Modal Dialog Window with default style.
|
||||
/// </summary>
|
||||
/// <param name="view"></param>
|
||||
/// <param name="vm"></param>
|
||||
/// <param name="owner"></param>
|
||||
/// <param name="options"></param>
|
||||
/// <returns></returns>
|
||||
public static Task<DialogResult> ShowModal(Control view, object? vm, Window? owner = null, DialogOptions? options = null)
|
||||
{
|
||||
var window = new DefaultDialogWindow
|
||||
{
|
||||
Content = view,
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureDefaultDialogWindow(window, options);
|
||||
owner ??= GetMainWindow();
|
||||
if (owner is null)
|
||||
{
|
||||
window.Show();
|
||||
return Task.FromResult(DialogResult.None);
|
||||
}
|
||||
return window.ShowDialog<DialogResult>(owner);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show a Modal Dialog Window with all content fully customized.
|
||||
/// </summary>
|
||||
/// <param name="vm"></param>
|
||||
/// <param name="owner"></param>
|
||||
/// <param name="options"></param>
|
||||
/// <typeparam name="TView"></typeparam>
|
||||
/// <typeparam name="TViewModel"></typeparam>
|
||||
/// <typeparam name="TResult"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static Task<TResult?> ShowCustomModal<TView, TViewModel, TResult>(TViewModel vm, Window? owner = null,
|
||||
DialogOptions? options = null)
|
||||
where TView: Control, new()
|
||||
{
|
||||
var window = new DialogWindow
|
||||
{
|
||||
Content = new TView(),
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureDialogWindow(window, options);
|
||||
owner ??= GetMainWindow();
|
||||
if (owner is null)
|
||||
{
|
||||
window.Show();
|
||||
return Task.FromResult(default(TResult));
|
||||
}
|
||||
return window.ShowDialog<TResult?>(owner);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show a Modal Dialog Window with all content fully customized.
|
||||
/// </summary>
|
||||
/// <param name="view"></param>
|
||||
/// <param name="vm"></param>
|
||||
/// <param name="owner"></param>
|
||||
/// <param name="options"></param>
|
||||
/// <typeparam name="TResult"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static Task<TResult?> ShowCustomModal<TResult>(Control view, object? vm, Window? owner = null,
|
||||
DialogOptions? options = null)
|
||||
{
|
||||
var window = new DialogWindow
|
||||
{
|
||||
Content = view,
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureDialogWindow(window, options);
|
||||
owner ??= GetMainWindow();
|
||||
if (owner is null)
|
||||
{
|
||||
window.Show();
|
||||
return Task.FromResult(default(TResult));
|
||||
}
|
||||
return window.ShowDialog<TResult?>(owner);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the main window of the application as default owner of the dialog.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static Window? GetMainWindow()
|
||||
{
|
||||
var lifetime = Application.Current?.ApplicationLifetime;
|
||||
return lifetime is IClassicDesktopStyleApplicationLifetime { MainWindow: { } w } ? w : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attach options to dialog window.
|
||||
/// </summary>
|
||||
/// <param name="window"></param>
|
||||
/// <param name="options"></param>
|
||||
private static void ConfigureDialogWindow(DialogWindow window, DialogOptions? options)
|
||||
{
|
||||
if (options is null)
|
||||
{
|
||||
options = new DialogOptions();
|
||||
}
|
||||
window.WindowStartupLocation = options.StartupLocation;
|
||||
window.Title = options.Title;
|
||||
window.IsCloseButtonVisible = options.IsCloseButtonVisible;
|
||||
if (options.StartupLocation == WindowStartupLocation.Manual)
|
||||
{
|
||||
if (options.Position is not null)
|
||||
{
|
||||
window.Position = options.Position.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attach options to default dialog window.
|
||||
/// </summary>
|
||||
/// <param name="window"></param>
|
||||
/// <param name="options"></param>
|
||||
private static void ConfigureDefaultDialogWindow(DefaultDialogWindow window, DialogOptions? options)
|
||||
{
|
||||
options ??= DialogOptions.Default;
|
||||
window.WindowStartupLocation = options.StartupLocation;
|
||||
window.Title = options.Title;
|
||||
window.Buttons = options.Button;
|
||||
window.Mode = options.Mode;
|
||||
if (options.StartupLocation == WindowStartupLocation.Manual)
|
||||
{
|
||||
if (options.Position is not null)
|
||||
{
|
||||
window.Position = options.Position.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
187
src/Ursa/Controls/Dialog/DialogControlBase.cs
Normal file
187
src/Ursa/Controls/Dialog/DialogControlBase.cs
Normal file
@@ -0,0 +1,187 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.LogicalTree;
|
||||
using Irihi.Avalonia.Shared.Helpers;
|
||||
using Ursa.Common;
|
||||
using Ursa.Controls.OverlayShared;
|
||||
using Ursa.EventArgs;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
[TemplatePart(PART_CloseButton, typeof(Button))]
|
||||
[TemplatePart(PART_TitleArea, typeof(Panel))]
|
||||
[PseudoClasses(PC_Modal)]
|
||||
public abstract class DialogControlBase : OverlayFeedbackElement
|
||||
{
|
||||
public const string PART_CloseButton = "PART_CloseButton";
|
||||
public const string PART_TitleArea = "PART_TitleArea";
|
||||
public const string PC_Modal = ":modal";
|
||||
|
||||
internal HorizontalPosition HorizontalAnchor { get; set; } = HorizontalPosition.Center;
|
||||
internal VerticalPosition VerticalAnchor { get; set; } = VerticalPosition.Center;
|
||||
internal HorizontalPosition ActualHorizontalAnchor { get; set; }
|
||||
internal VerticalPosition ActualVerticalAnchor { get; set; }
|
||||
internal double? HorizontalOffset { get; set; }
|
||||
internal double? VerticalOffset { get; set; }
|
||||
internal double? HorizontalOffsetRatio { get; set; }
|
||||
internal double? VerticalOffsetRatio { get; set; }
|
||||
internal bool CanLightDismiss { get; set; }
|
||||
internal bool CanDragMove { get; set; }
|
||||
|
||||
protected internal Button? _closeButton;
|
||||
private Panel? _titleArea;
|
||||
|
||||
#region Layer Management
|
||||
|
||||
public static readonly RoutedEvent<DialogLayerChangeEventArgs> LayerChangedEvent =
|
||||
RoutedEvent.Register<CustomDialogControl, DialogLayerChangeEventArgs>(
|
||||
nameof(LayerChanged), RoutingStrategies.Bubble);
|
||||
|
||||
public event EventHandler<DialogLayerChangeEventArgs> LayerChanged
|
||||
{
|
||||
add => AddHandler(LayerChangedEvent, value);
|
||||
remove => RemoveHandler(LayerChangedEvent, value);
|
||||
}
|
||||
|
||||
public void UpdateLayer(object? o)
|
||||
{
|
||||
if (o is DialogLayerChangeType t)
|
||||
{
|
||||
RaiseEvent(new DialogLayerChangeEventArgs(LayerChangedEvent, t));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region DragMove AttachedPropert
|
||||
|
||||
public static readonly AttachedProperty<bool> CanDragMoveProperty =
|
||||
AvaloniaProperty.RegisterAttached<DialogControlBase, InputElement, bool>("CanDragMove");
|
||||
|
||||
public static void SetCanDragMove(InputElement obj, bool value) => obj.SetValue(CanDragMoveProperty, value);
|
||||
public static bool GetCanDragMove(InputElement obj) => obj.GetValue(CanDragMoveProperty);
|
||||
|
||||
private static void OnCanDragMoveChanged(InputElement arg1, AvaloniaPropertyChangedEventArgs<bool> arg2)
|
||||
{
|
||||
if (arg2.NewValue.Value)
|
||||
{
|
||||
arg1.AddHandler(PointerPressedEvent, OnPointerPressed, RoutingStrategies.Bubble);
|
||||
arg1.AddHandler(PointerMovedEvent, OnPointerMoved, RoutingStrategies.Bubble);
|
||||
arg1.AddHandler(PointerReleasedEvent, OnPointerReleased, RoutingStrategies.Bubble);
|
||||
}
|
||||
else
|
||||
{
|
||||
arg1.RemoveHandler(PointerPressedEvent, OnPointerPressed);
|
||||
arg1.RemoveHandler(PointerMovedEvent, OnPointerMoved);
|
||||
arg1.RemoveHandler(PointerReleasedEvent, OnPointerReleased);
|
||||
}
|
||||
|
||||
void OnPointerPressed(InputElement sender, PointerPressedEventArgs e)
|
||||
{
|
||||
if (sender.FindLogicalAncestorOfType<DialogControlBase>() is { } dialog)
|
||||
{
|
||||
e.Source = dialog;
|
||||
}
|
||||
}
|
||||
|
||||
void OnPointerMoved(InputElement sender, PointerEventArgs e)
|
||||
{
|
||||
if (sender.FindLogicalAncestorOfType<DialogControlBase>() is { } dialog)
|
||||
{
|
||||
e.Source = dialog;
|
||||
}
|
||||
}
|
||||
|
||||
void OnPointerReleased(InputElement sender, PointerReleasedEventArgs e)
|
||||
{
|
||||
if (sender.FindLogicalAncestorOfType<DialogControlBase>() is { } dialog)
|
||||
{
|
||||
e.Source = dialog;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Close AttachedProperty
|
||||
|
||||
public static readonly AttachedProperty<bool> CanCloseProperty =
|
||||
AvaloniaProperty.RegisterAttached<DialogControlBase, InputElement, bool>("CanClose");
|
||||
|
||||
public static void SetCanClose(InputElement obj, bool value) => obj.SetValue(CanCloseProperty, value);
|
||||
public static bool GetCanClose(InputElement obj) => obj.GetValue(CanCloseProperty);
|
||||
private static void OnCanCloseChanged(InputElement arg1, AvaloniaPropertyChangedEventArgs<bool> arg2)
|
||||
{
|
||||
if (arg2.NewValue.Value)
|
||||
{
|
||||
arg1.AddHandler(PointerPressedEvent, OnPointerPressed, RoutingStrategies.Bubble);
|
||||
}
|
||||
void OnPointerPressed(InputElement sender, PointerPressedEventArgs e)
|
||||
{
|
||||
if (sender.FindLogicalAncestorOfType<DialogControlBase>() is { } dialog)
|
||||
{
|
||||
dialog.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
static DialogControlBase()
|
||||
{
|
||||
CanDragMoveProperty.Changed.AddClassHandler<InputElement, bool>(OnCanDragMoveChanged);
|
||||
CanCloseProperty.Changed.AddClassHandler<InputElement, bool>(OnCanCloseChanged);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
_titleArea = e.NameScope.Find<Panel>(PART_TitleArea);
|
||||
if (CanDragMove)
|
||||
{
|
||||
_titleArea?.RemoveHandler(PointerMovedEvent, OnTitlePointerMove);
|
||||
_titleArea?.RemoveHandler(PointerPressedEvent, OnTitlePointerPressed);
|
||||
_titleArea?.RemoveHandler(PointerReleasedEvent, OnTitlePointerRelease);
|
||||
|
||||
_titleArea?.AddHandler(PointerMovedEvent, OnTitlePointerMove, RoutingStrategies.Bubble);
|
||||
_titleArea?.AddHandler(PointerPressedEvent, OnTitlePointerPressed, RoutingStrategies.Bubble);
|
||||
_titleArea?.AddHandler(PointerReleasedEvent, OnTitlePointerRelease, RoutingStrategies.Bubble);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_titleArea is not null) _titleArea.IsHitTestVisible = false;
|
||||
}
|
||||
|
||||
Button.ClickEvent.RemoveHandler(OnCloseButtonClick, _closeButton);
|
||||
_closeButton = e.NameScope.Find<Button>(PART_CloseButton);
|
||||
Button.ClickEvent.AddHandler(OnCloseButtonClick, _closeButton);
|
||||
}
|
||||
|
||||
private void OnTitlePointerPressed(InputElement sender, PointerPressedEventArgs e)
|
||||
{
|
||||
e.Source = this;
|
||||
}
|
||||
|
||||
private void OnTitlePointerMove(InputElement sender, PointerEventArgs e)
|
||||
{
|
||||
e.Source = this;
|
||||
}
|
||||
|
||||
private void OnTitlePointerRelease(InputElement sender, PointerReleasedEventArgs e)
|
||||
{
|
||||
e.Source = this;
|
||||
}
|
||||
|
||||
private void OnCloseButtonClick(object sender, RoutedEventArgs args) => Close();
|
||||
|
||||
internal void SetAsModal(bool modal)
|
||||
{
|
||||
PseudoClasses.Set(PC_Modal, modal);
|
||||
}
|
||||
}
|
||||
25
src/Ursa/Controls/Dialog/DialogLayerChangeEventArgs.cs
Normal file
25
src/Ursa/Controls/Dialog/DialogLayerChangeEventArgs.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using Avalonia.Interactivity;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public class DialogLayerChangeEventArgs: RoutedEventArgs
|
||||
{
|
||||
public DialogLayerChangeType ChangeType { get; }
|
||||
|
||||
public DialogLayerChangeEventArgs(DialogLayerChangeType type)
|
||||
{
|
||||
ChangeType = type;
|
||||
}
|
||||
public DialogLayerChangeEventArgs(RoutedEvent routedEvent, DialogLayerChangeType type): base(routedEvent)
|
||||
{
|
||||
ChangeType = type;
|
||||
}
|
||||
}
|
||||
|
||||
public enum DialogLayerChangeType
|
||||
{
|
||||
BringForward,
|
||||
SendBackward,
|
||||
BringToFront,
|
||||
SendToBack
|
||||
}
|
||||
78
src/Ursa/Controls/Dialog/DialogWindow.cs
Normal file
78
src/Ursa/Controls/Dialog/DialogWindow.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Irihi.Avalonia.Shared.Contracts;
|
||||
using Irihi.Avalonia.Shared.Helpers;
|
||||
using Ursa.Common;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
[TemplatePart(PART_CloseButton, typeof(Button))]
|
||||
[TemplatePart(PART_TitleArea, typeof(Panel))]
|
||||
public class DialogWindow: Window
|
||||
{
|
||||
public const string PART_CloseButton = "PART_CloseButton";
|
||||
public const string PART_TitleArea = "PART_TitleArea";
|
||||
protected override Type StyleKeyOverride { get; } = typeof(DialogWindow);
|
||||
|
||||
protected internal Button? _closeButton;
|
||||
private Panel? _titleArea;
|
||||
|
||||
internal bool IsCloseButtonVisible { get; set; }
|
||||
|
||||
static DialogWindow()
|
||||
{
|
||||
DataContextProperty.Changed.AddClassHandler<DialogWindow, object?>((o, e) => o.OnDataContextChange(e));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
Button.ClickEvent.RemoveHandler(OnCloseButtonClicked, _closeButton);
|
||||
_titleArea?.RemoveHandler(PointerPressedEvent, OnTitlePointerPressed);
|
||||
_closeButton = e.NameScope.Find<Button>(PART_CloseButton);
|
||||
Button.IsVisibleProperty.SetValue(IsCloseButtonVisible, _closeButton);
|
||||
Button.ClickEvent.AddHandler(OnCloseButtonClicked, _closeButton);
|
||||
_titleArea = e.NameScope.Find<Panel>(PART_TitleArea);
|
||||
_titleArea?.AddHandler(PointerPressedEvent, OnTitlePointerPressed, RoutingStrategies.Bubble);
|
||||
|
||||
}
|
||||
|
||||
private void OnContextRequestClose(object? sender, object? args)
|
||||
{
|
||||
Close(args);
|
||||
}
|
||||
|
||||
protected internal virtual void OnCloseButtonClicked(object sender, RoutedEventArgs args)
|
||||
{
|
||||
if (DataContext is IDialogContext context)
|
||||
{
|
||||
context.Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
Close(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTitlePointerPressed(object sender, PointerPressedEventArgs e)
|
||||
{
|
||||
this.BeginMoveDrag(e);
|
||||
}
|
||||
}
|
||||
29
src/Ursa/Controls/Dialog/Options/DialogOptions.cs
Normal file
29
src/Ursa/Controls/Dialog/Options/DialogOptions.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public class DialogOptions
|
||||
{
|
||||
internal static DialogOptions Default { get; } = new DialogOptions();
|
||||
/// <summary>
|
||||
/// The Startup Location of DialogWindow. Default is <see cref="WindowStartupLocation.CenterOwner"/>
|
||||
/// </summary>
|
||||
public WindowStartupLocation StartupLocation { get; set; } = WindowStartupLocation.CenterOwner;
|
||||
/// <summary>
|
||||
/// The Position of DialogWindow startup location if <see cref="StartupLocation"/> is <see cref="WindowStartupLocation.Manual"/>
|
||||
/// </summary>
|
||||
public PixelPoint? Position { get; set; }
|
||||
/// <summary>
|
||||
/// Title of DialogWindow, Default is null
|
||||
/// </summary>
|
||||
public string? Title { get; set; }
|
||||
/// <summary>
|
||||
/// DialogWindow's Mode, Default is <see cref="DialogMode.None"/>
|
||||
/// </summary>
|
||||
public DialogMode Mode { get; set; } = DialogMode.None;
|
||||
|
||||
public DialogButton Button { get; set; } = DialogButton.OKCancel;
|
||||
|
||||
public bool IsCloseButtonVisible { get; set; } = true;
|
||||
}
|
||||
48
src/Ursa/Controls/Dialog/Options/OverlayDialogOptions.cs
Normal file
48
src/Ursa/Controls/Dialog/Options/OverlayDialogOptions.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public enum HorizontalPosition
|
||||
{
|
||||
Left,
|
||||
Center,
|
||||
Right
|
||||
}
|
||||
|
||||
public enum VerticalPosition
|
||||
{
|
||||
Top,
|
||||
Center,
|
||||
Bottom
|
||||
}
|
||||
|
||||
public class OverlayDialogOptions
|
||||
{
|
||||
internal static OverlayDialogOptions Default { get; } = new OverlayDialogOptions();
|
||||
public HorizontalPosition HorizontalAnchor { get; set; } = HorizontalPosition.Center;
|
||||
public VerticalPosition VerticalAnchor { get; set; } = VerticalPosition.Center;
|
||||
/// <summary>
|
||||
/// This attribute is only used when HorizontalAnchor is not Center
|
||||
/// </summary>
|
||||
public double? HorizontalOffset { get; set; } = null;
|
||||
/// <summary>
|
||||
/// This attribute is only used when VerticalAnchor is not Center
|
||||
/// </summary>
|
||||
public double? VerticalOffset { get; set; } = null;
|
||||
/// <summary>
|
||||
/// Only works for DefaultDialogControl
|
||||
/// </summary>
|
||||
public DialogMode Mode { get; set; } = DialogMode.None;
|
||||
/// <summary>
|
||||
/// Only works for DefaultDialogControl
|
||||
/// </summary>
|
||||
public DialogButton Buttons { get; set; } = DialogButton.OKCancel;
|
||||
/// <summary>
|
||||
/// Only works for DefaultDialogControl
|
||||
/// </summary>
|
||||
public string? Title { get; set; } = null;
|
||||
/// <summary>
|
||||
/// Only works for CustomDialogControl
|
||||
/// </summary>
|
||||
public bool ShowCloseButton { get; set; } = true;
|
||||
public bool CanLightDismiss { get; set; }
|
||||
public bool CanDragMove { get; set; } = true;
|
||||
}
|
||||
216
src/Ursa/Controls/Dialog/OverlayDialog.cs
Normal file
216
src/Ursa/Controls/Dialog/OverlayDialog.cs
Normal file
@@ -0,0 +1,216 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Ursa.Common;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public static class OverlayDialog
|
||||
{
|
||||
public static void Show<TView, TViewModel>(TViewModel vm, string? hostId = null,
|
||||
OverlayDialogOptions? options = null)
|
||||
where TView : Control, new()
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return;
|
||||
var t = new DefaultDialogControl()
|
||||
{
|
||||
Content = new TView(){ DataContext = vm },
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureDefaultDialogControl(t, options);
|
||||
host.AddDialog(t);
|
||||
}
|
||||
|
||||
public static void Show(Control control, object? vm, string? hostId = null,
|
||||
OverlayDialogOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return;
|
||||
var t = new DefaultDialogControl()
|
||||
{
|
||||
Content = control,
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureDefaultDialogControl(t, options);
|
||||
host.AddDialog(t);
|
||||
|
||||
}
|
||||
|
||||
public static void Show(object? vm, string? hostId = null, OverlayDialogOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return;
|
||||
var view = host.GetDataTemplate(vm)?.Build(vm);
|
||||
if (view is null) view = new ContentControl();
|
||||
view.DataContext = vm;
|
||||
var t = new DefaultDialogControl()
|
||||
{
|
||||
Content = view,
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureDefaultDialogControl(t, options);
|
||||
host.AddDialog(t);
|
||||
}
|
||||
|
||||
public static void ShowCustom<TView, TViewModel>(TViewModel vm, string? hostId = null,
|
||||
OverlayDialogOptions? options = null)
|
||||
where TView: Control, new()
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return;
|
||||
var t = new CustomDialogControl()
|
||||
{
|
||||
Content = new TView(),
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureCustomDialogControl(t, options);
|
||||
host.AddDialog(t);
|
||||
}
|
||||
|
||||
public static void ShowCustom(Control control, object? vm, string? hostId = null,
|
||||
OverlayDialogOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return;
|
||||
var t = new CustomDialogControl()
|
||||
{
|
||||
Content = control,
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureCustomDialogControl(t, options);
|
||||
host.AddDialog(t);
|
||||
}
|
||||
|
||||
public static void ShowCustom(object? vm, string? hostId = null,
|
||||
OverlayDialogOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return;
|
||||
var view = host.GetDataTemplate(vm)?.Build(vm);
|
||||
if (view is null) view = new ContentControl() { Padding = new Thickness(24) };
|
||||
view.DataContext = vm;
|
||||
var t = new CustomDialogControl()
|
||||
{
|
||||
Content = view,
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureCustomDialogControl(t, options);
|
||||
host.AddDialog(t);
|
||||
}
|
||||
|
||||
public static Task<DialogResult> ShowModal<TView, TViewModel>(TViewModel vm, string? hostId = null,
|
||||
OverlayDialogOptions? options = null, CancellationToken? token = default)
|
||||
where TView: Control, new()
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return Task.FromResult(DialogResult.None);
|
||||
var t = new DefaultDialogControl()
|
||||
{
|
||||
Content = new TView(),
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureDefaultDialogControl(t, options);
|
||||
host.AddModalDialog(t);
|
||||
return t.ShowAsync<DialogResult>(token);
|
||||
}
|
||||
|
||||
public static Task<DialogResult> ShowModal(Control control, object? vm, string? hostId = null,
|
||||
OverlayDialogOptions? options = null, CancellationToken? token = default)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return Task.FromResult(DialogResult.None);
|
||||
var t = new DefaultDialogControl()
|
||||
{
|
||||
Content = control,
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureDefaultDialogControl(t, options);
|
||||
host.AddModalDialog(t);
|
||||
return t.ShowAsync<DialogResult>(token);
|
||||
}
|
||||
|
||||
public static Task<TResult?> ShowCustomModal<TView, TViewModel, TResult>(TViewModel vm, string? hostId = null,
|
||||
OverlayDialogOptions? options = null, CancellationToken? token = default)
|
||||
where TView: Control, new()
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return Task.FromResult(default(TResult));
|
||||
var t = new CustomDialogControl()
|
||||
{
|
||||
Content = new TView(),
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureCustomDialogControl(t, options);
|
||||
host.AddModalDialog(t);
|
||||
return t.ShowAsync<TResult?>(token);
|
||||
}
|
||||
|
||||
public static Task<TResult?> ShowCustomModal<TResult>(Control control, object? vm, string? hostId = null,
|
||||
OverlayDialogOptions? options = null, CancellationToken? token = default)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return Task.FromResult(default(TResult));
|
||||
var t = new CustomDialogControl()
|
||||
{
|
||||
Content = control,
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureCustomDialogControl(t, options);
|
||||
host.AddModalDialog(t);
|
||||
return t.ShowAsync<TResult?>(token);
|
||||
}
|
||||
|
||||
public static Task<TResult?> ShowCustomModal<TResult>(object? vm, string? hostId = null,
|
||||
OverlayDialogOptions? options = null, CancellationToken? token = default)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return Task.FromResult(default(TResult));
|
||||
var view = host.GetDataTemplate(vm)?.Build(vm);
|
||||
if (view is null) view = new ContentControl() { Padding = new Thickness(24) };
|
||||
view.DataContext = vm;
|
||||
var t = new CustomDialogControl()
|
||||
{
|
||||
Content = view,
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureCustomDialogControl(t, options);
|
||||
host.AddModalDialog(t);
|
||||
return t.ShowAsync<TResult?>(token);
|
||||
}
|
||||
|
||||
private static void ConfigureCustomDialogControl(CustomDialogControl control, OverlayDialogOptions? options)
|
||||
{
|
||||
options ??= OverlayDialogOptions.Default;
|
||||
control.HorizontalAnchor = options.HorizontalAnchor;
|
||||
control.VerticalAnchor = options.VerticalAnchor;
|
||||
control.ActualHorizontalAnchor = options.HorizontalAnchor;
|
||||
control.ActualVerticalAnchor = options.VerticalAnchor;
|
||||
control.HorizontalOffset =
|
||||
control.HorizontalAnchor == HorizontalPosition.Center ? null : options.HorizontalOffset;
|
||||
control.VerticalOffset =
|
||||
options.VerticalAnchor == VerticalPosition.Center ? null : options.VerticalOffset;
|
||||
control.IsCloseButtonVisible = options.ShowCloseButton;
|
||||
control.CanLightDismiss = options.CanLightDismiss;
|
||||
control.CanDragMove = options.CanDragMove;
|
||||
}
|
||||
|
||||
private static void ConfigureDefaultDialogControl(DefaultDialogControl control, OverlayDialogOptions? options)
|
||||
{
|
||||
if (options is null) options = new OverlayDialogOptions();
|
||||
control.HorizontalAnchor = options.HorizontalAnchor;
|
||||
control.VerticalAnchor = options.VerticalAnchor;
|
||||
control.ActualHorizontalAnchor = options.HorizontalAnchor;
|
||||
control.ActualVerticalAnchor = options.VerticalAnchor;
|
||||
control.HorizontalOffset =
|
||||
control.HorizontalAnchor == HorizontalPosition.Center ? null : options.HorizontalOffset;
|
||||
control.VerticalOffset =
|
||||
options.VerticalAnchor == VerticalPosition.Center ? null : options.VerticalOffset;
|
||||
control.Mode = options.Mode;
|
||||
control.Buttons = options.Buttons;
|
||||
control.Title = options.Title;
|
||||
control.CanLightDismiss = options.CanLightDismiss;
|
||||
control.CanDragMove = options.CanDragMove;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
29
src/Ursa/Controls/DisableContainer/DisableContainer.cs
Normal file
29
src/Ursa/Controls/DisableContainer/DisableContainer.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Metadata;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public class DisableContainer: TemplatedControl
|
||||
{
|
||||
public static readonly StyledProperty<InputElement?> ContentProperty = AvaloniaProperty.Register<DisableContainer, InputElement?>(
|
||||
nameof(Content));
|
||||
|
||||
[Content]
|
||||
public InputElement? Content
|
||||
{
|
||||
get => GetValue(ContentProperty);
|
||||
set => SetValue(ContentProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<object?> DisabledTipProperty = AvaloniaProperty.Register<DisableContainer, object?>(
|
||||
nameof(DisabledTip));
|
||||
|
||||
public object? DisabledTip
|
||||
{
|
||||
get => GetValue(DisabledTipProperty);
|
||||
set => SetValue(DisabledTipProperty, value);
|
||||
}
|
||||
}
|
||||
55
src/Ursa/Controls/DisableContainer/DisabledAdorner.cs
Normal file
55
src/Ursa/Controls/DisableContainer/DisabledAdorner.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Data.Converters;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Media;
|
||||
using Ursa.Controls.Shapes;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public class DisabledAdorner
|
||||
{
|
||||
public static readonly AttachedProperty<bool> IsEnabledProperty =
|
||||
AvaloniaProperty.RegisterAttached<DisabledAdorner, InputElement, bool>("IsEnabled");
|
||||
|
||||
public static void SetIsEnabled(InputElement obj, bool value) => obj.SetValue(IsEnabledProperty, value);
|
||||
public static bool GetIsEnabled(InputElement obj) => obj.GetValue(IsEnabledProperty);
|
||||
|
||||
public static readonly AttachedProperty<object?> DisabledTipProperty =
|
||||
AvaloniaProperty.RegisterAttached<DisabledAdorner, InputElement, object?>("DisabledTip");
|
||||
|
||||
public static void SetDisabledTip(InputElement obj, object? value) => obj.SetValue(DisabledTipProperty, value);
|
||||
public static object? GetDisabledTip(InputElement obj) => obj.GetValue(DisabledTipProperty);
|
||||
|
||||
static DisabledAdorner()
|
||||
{
|
||||
IsEnabledProperty.Changed.AddClassHandler<InputElement, bool>(OnIsEnabledChanged);
|
||||
}
|
||||
|
||||
private static void OnIsEnabledChanged(InputElement arg1, AvaloniaPropertyChangedEventArgs<bool> arg2)
|
||||
{
|
||||
if (arg2.NewValue.Value)
|
||||
{
|
||||
var pureRectangle = new Border()
|
||||
{
|
||||
Background = Brushes.Transparent,
|
||||
IsHitTestVisible = true,
|
||||
HorizontalAlignment = HorizontalAlignment.Stretch,
|
||||
VerticalAlignment = VerticalAlignment.Stretch,
|
||||
Cursor = new Cursor(StandardCursorType.No),
|
||||
[!ToolTip.TipProperty] = arg1[!DisabledTipProperty],
|
||||
};
|
||||
var binding = arg1.GetObservable(InputElement.IsEnabledProperty, converter: (a) => !a).ToBinding();
|
||||
pureRectangle.Bind(Visual.IsVisibleProperty, binding);
|
||||
AdornerLayer.SetAdorner(arg1, pureRectangle);
|
||||
}
|
||||
else
|
||||
{
|
||||
AdornerLayer.SetAdorner(arg1, null);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
28
src/Ursa/Controls/Drawer/CustomDrawerControl.cs
Normal file
28
src/Ursa/Controls/Drawer/CustomDrawerControl.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Irihi.Avalonia.Shared.Contracts;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public class CustomDrawerControl: DrawerControlBase
|
||||
{
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
if (_closeButton is not null)
|
||||
{
|
||||
_closeButton.IsVisible = IsCloseButtonVisible;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
if (DataContext is IDialogContext context)
|
||||
{
|
||||
context.Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
OnElementClosing(this, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
139
src/Ursa/Controls/Drawer/DefaultDrawerControl.cs
Normal file
139
src/Ursa/Controls/Drawer/DefaultDrawerControl.cs
Normal file
@@ -0,0 +1,139 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Interactivity;
|
||||
using Irihi.Avalonia.Shared.Contracts;
|
||||
using Irihi.Avalonia.Shared.Helpers;
|
||||
using Ursa.Common;
|
||||
using Ursa.EventArgs;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
[TemplatePart(PART_YesButton, typeof(Button))]
|
||||
[TemplatePart(PART_NoButton, typeof(Button))]
|
||||
[TemplatePart(PART_OKButton, typeof(Button))]
|
||||
[TemplatePart(PART_CancelButton, typeof(Button))]
|
||||
public class DefaultDrawerControl: DrawerControlBase
|
||||
{
|
||||
public const string PART_YesButton = "PART_YesButton";
|
||||
public const string PART_NoButton = "PART_NoButton";
|
||||
public const string PART_OKButton = "PART_OKButton";
|
||||
public const string PART_CancelButton = "PART_CancelButton";
|
||||
|
||||
private Button? _yesButton;
|
||||
private Button? _noButton;
|
||||
private Button? _okButton;
|
||||
private Button? _cancelButton;
|
||||
|
||||
public static readonly StyledProperty<DialogButton> ButtonsProperty = AvaloniaProperty.Register<DefaultDrawerControl, DialogButton>(
|
||||
nameof(Buttons), DialogButton.OKCancel);
|
||||
|
||||
public DialogButton Buttons
|
||||
{
|
||||
get => GetValue(ButtonsProperty);
|
||||
set => SetValue(ButtonsProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<DialogMode> ModeProperty = AvaloniaProperty.Register<DefaultDrawerControl, DialogMode>(
|
||||
nameof(Mode), DialogMode.None);
|
||||
|
||||
public DialogMode Mode
|
||||
{
|
||||
get => GetValue(ModeProperty);
|
||||
set => SetValue(ModeProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<string?> TitleProperty = AvaloniaProperty.Register<DefaultDrawerControl, string?>(
|
||||
nameof(Title));
|
||||
|
||||
public string? Title
|
||||
{
|
||||
get => GetValue(TitleProperty);
|
||||
set => SetValue(TitleProperty, value);
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
Button.ClickEvent.RemoveHandler(OnDefaultButtonClick, _yesButton, _noButton, _okButton, _cancelButton);
|
||||
_yesButton = e.NameScope.Find<Button>(PART_YesButton);
|
||||
_noButton = e.NameScope.Find<Button>(PART_NoButton);
|
||||
_okButton = e.NameScope.Find<Button>(PART_OKButton);
|
||||
_cancelButton = e.NameScope.Find<Button>(PART_CancelButton);
|
||||
Button.ClickEvent.AddHandler(OnDefaultButtonClick, _yesButton, _noButton, _okButton, _cancelButton);
|
||||
SetButtonVisibility();
|
||||
}
|
||||
|
||||
private void SetButtonVisibility()
|
||||
{
|
||||
bool isCloseButtonVisible = DataContext is IDialogContext || Buttons != DialogButton.YesNo;
|
||||
Button.IsVisibleProperty.SetValue(isCloseButtonVisible, _closeButton);
|
||||
switch (Buttons)
|
||||
{
|
||||
case DialogButton.None:
|
||||
Button.IsVisibleProperty.SetValue(false, _okButton, _cancelButton, _yesButton, _noButton);
|
||||
break;
|
||||
case DialogButton.OK:
|
||||
Button.IsVisibleProperty.SetValue(true, _okButton);
|
||||
Button.IsVisibleProperty.SetValue(false, _cancelButton, _yesButton, _noButton);
|
||||
break;
|
||||
case DialogButton.OKCancel:
|
||||
Button.IsVisibleProperty.SetValue(true, _okButton, _cancelButton);
|
||||
Button.IsVisibleProperty.SetValue(false, _yesButton, _noButton);
|
||||
break;
|
||||
case DialogButton.YesNo:
|
||||
Button.IsVisibleProperty.SetValue(false, _okButton, _cancelButton);
|
||||
Button.IsVisibleProperty.SetValue(true, _yesButton, _noButton);
|
||||
break;
|
||||
case DialogButton.YesNoCancel:
|
||||
Button.IsVisibleProperty.SetValue(false, _okButton);
|
||||
Button.IsVisibleProperty.SetValue(true, _cancelButton, _yesButton, _noButton);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDefaultButtonClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button button)
|
||||
{
|
||||
if (button == _okButton)
|
||||
{
|
||||
OnElementClosing(this, DialogResult.OK);
|
||||
}
|
||||
else if (button == _cancelButton)
|
||||
{
|
||||
OnElementClosing(this, DialogResult.Cancel);
|
||||
}
|
||||
else if (button == _yesButton)
|
||||
{
|
||||
OnElementClosing(this, DialogResult.Yes);
|
||||
}
|
||||
else if (button == _noButton)
|
||||
{
|
||||
OnElementClosing(this, DialogResult.No);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
if (DataContext is IDialogContext context)
|
||||
{
|
||||
context.Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
DialogResult result = Buttons switch
|
||||
{
|
||||
DialogButton.None => DialogResult.None,
|
||||
DialogButton.OK => DialogResult.OK,
|
||||
DialogButton.OKCancel => DialogResult.Cancel,
|
||||
DialogButton.YesNo => DialogResult.No,
|
||||
DialogButton.YesNoCancel => DialogResult.Cancel,
|
||||
_ => DialogResult.None
|
||||
};
|
||||
RaiseEvent(new ResultEventArgs(ClosedEvent, result));
|
||||
}
|
||||
}
|
||||
}
|
||||
227
src/Ursa/Controls/Drawer/Drawer.cs
Normal file
227
src/Ursa/Controls/Drawer/Drawer.cs
Normal file
@@ -0,0 +1,227 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Ursa.Common;
|
||||
using Ursa.Controls.Options;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public static class Drawer
|
||||
{
|
||||
public static void Show<TView, TViewModel>(TViewModel vm, string? hostId = null, DrawerOptions? options = null)
|
||||
where TView: Control, new()
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return;
|
||||
var drawer = new DefaultDrawerControl()
|
||||
{
|
||||
Content = new TView(),
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureDefaultDrawer(drawer, options);
|
||||
host.AddDrawer(drawer);
|
||||
}
|
||||
|
||||
public static void Show(Control control, object? vm, string? hostId = null,
|
||||
DrawerOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return;
|
||||
var drawer = new DefaultDrawerControl()
|
||||
{
|
||||
Content = control,
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureDefaultDrawer(drawer, options);
|
||||
host.AddDrawer(drawer);
|
||||
}
|
||||
|
||||
public static void Show(object? vm, string? hostId = null, DrawerOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return;
|
||||
var view = host.GetDataTemplate(vm)?.Build(vm);
|
||||
if (view is null) view = new ContentControl() { Padding = new Thickness(24) };
|
||||
view.DataContext = vm;
|
||||
var drawer = new DefaultDrawerControl()
|
||||
{
|
||||
Content = view,
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureDefaultDrawer(drawer, options);
|
||||
host.AddDrawer(drawer);
|
||||
}
|
||||
|
||||
public static Task<DialogResult> ShowModal<TView, TViewModel>(TViewModel vm, string? hostId = null, DrawerOptions? options = null)
|
||||
where TView: Control, new()
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return Task.FromResult(DialogResult.None);
|
||||
var drawer = new DefaultDrawerControl()
|
||||
{
|
||||
Content = new TView(),
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureDefaultDrawer(drawer, options);
|
||||
host.AddModalDrawer(drawer);
|
||||
return drawer.ShowAsync<DialogResult>();
|
||||
}
|
||||
|
||||
public static Task<DialogResult> ShowModal(Control control, object? vm, string? hostId = null,
|
||||
DrawerOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return Task.FromResult(DialogResult.None);
|
||||
var drawer = new DefaultDrawerControl()
|
||||
{
|
||||
Content = control,
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureDefaultDrawer(drawer, options);
|
||||
host.AddModalDrawer(drawer);
|
||||
return drawer.ShowAsync<DialogResult>();
|
||||
}
|
||||
|
||||
public static Task<DialogResult> ShowModal(object? vm, string? hostId = null, DrawerOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return Task.FromResult(DialogResult.None);
|
||||
var view = host.GetDataTemplate(vm)?.Build(vm);
|
||||
if (view is null) view = new ContentControl() { Padding = new Thickness(24) };
|
||||
view.DataContext = vm;
|
||||
var drawer = new DefaultDrawerControl()
|
||||
{
|
||||
Content = view,
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureDefaultDrawer(drawer, options);
|
||||
host.AddModalDrawer(drawer);
|
||||
return drawer.ShowAsync<DialogResult>();
|
||||
}
|
||||
|
||||
public static void ShowCustom<TView, TViewModel>(TViewModel vm, string? hostId = null, DrawerOptions? options = null)
|
||||
where TView: Control, new()
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return;
|
||||
var dialog = new CustomDrawerControl()
|
||||
{
|
||||
Content = new TView(),
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureCustomDrawer(dialog, options);
|
||||
host.AddDrawer(dialog);
|
||||
}
|
||||
|
||||
public static void ShowCustom(Control control, object? vm, string? hostId = null, DrawerOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return;
|
||||
var dialog = new CustomDrawerControl()
|
||||
{
|
||||
Content = control,
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureCustomDrawer(dialog, options);
|
||||
host.AddDrawer(dialog);
|
||||
}
|
||||
|
||||
public static void ShowCustom(object? vm, string? hostId = null, DrawerOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return;
|
||||
var view = host.GetDataTemplate(vm)?.Build(vm);
|
||||
if (view is null) view = new ContentControl() { Padding = new Thickness(24) };
|
||||
view.DataContext = vm;
|
||||
var dialog = new CustomDrawerControl()
|
||||
{
|
||||
Content = view,
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureCustomDrawer(dialog, options);
|
||||
host.AddDrawer(dialog);
|
||||
}
|
||||
|
||||
public static Task<TResult?> ShowCustomModal<TView, TViewModel, TResult>(TViewModel vm, string? hostId = null, DrawerOptions? options = null)
|
||||
where TView: Control, new()
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return Task.FromResult<TResult?>(default);
|
||||
var dialog = new CustomDrawerControl()
|
||||
{
|
||||
Content = new TView(),
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureCustomDrawer(dialog, options);
|
||||
host.AddModalDrawer(dialog);
|
||||
return dialog.ShowAsync<TResult?>();
|
||||
}
|
||||
|
||||
public static Task<TResult?> ShowCustomModal<TResult>(Control control, object? vm, string? hostId = null, DrawerOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return Task.FromResult<TResult?>(default);
|
||||
var dialog = new CustomDrawerControl()
|
||||
{
|
||||
Content = control,
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureCustomDrawer(dialog, options);
|
||||
host.AddModalDrawer(dialog);
|
||||
return dialog.ShowAsync<TResult?>();
|
||||
}
|
||||
|
||||
public static Task<TResult?> ShowCustomModal<TResult>(object? vm, string? hostId = null, DrawerOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return Task.FromResult<TResult?>(default);
|
||||
var view = host.GetDataTemplate(vm)?.Build(vm);
|
||||
if (view is null) view = new ContentControl() { Padding = new Thickness(24) };
|
||||
view.DataContext = vm;
|
||||
var dialog = new CustomDrawerControl()
|
||||
{
|
||||
Content = view,
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureCustomDrawer(dialog, options);
|
||||
host.AddModalDrawer(dialog);
|
||||
return dialog.ShowAsync<TResult?>();
|
||||
}
|
||||
|
||||
private static void ConfigureCustomDrawer(CustomDrawerControl drawer, DrawerOptions? options)
|
||||
{
|
||||
options ??= DrawerOptions.Default;
|
||||
drawer.Position = options.Position;
|
||||
drawer.IsCloseButtonVisible = options.ShowCloseButton;
|
||||
drawer.CanLightDismiss = options.CanLightDismiss;
|
||||
if (options.Position == Position.Left || options.Position == Position.Right)
|
||||
{
|
||||
drawer.MinWidth = options.MinWidth ?? 0.0;
|
||||
drawer.MaxWidth = options.MaxWidth ?? double.PositiveInfinity;
|
||||
}
|
||||
if (options.Position is Position.Top or Position.Bottom)
|
||||
{
|
||||
drawer.MinHeight = options.MinHeight ?? 0.0;
|
||||
drawer.MaxHeight = options.MaxHeight ?? double.PositiveInfinity;
|
||||
}
|
||||
}
|
||||
|
||||
private static void ConfigureDefaultDrawer(DefaultDrawerControl drawer, DrawerOptions? options)
|
||||
{
|
||||
options ??= DrawerOptions.Default;
|
||||
drawer.Position = options.Position;
|
||||
drawer.IsCloseButtonVisible = options.IsCloseButtonVisible;
|
||||
drawer.CanLightDismiss = options.CanLightDismiss;
|
||||
drawer.Buttons = options.Buttons;
|
||||
drawer.Title = options.Title;
|
||||
if (options.Position == Position.Left || options.Position == Position.Right)
|
||||
{
|
||||
drawer.MinWidth = options.MinWidth ?? 0.0;
|
||||
drawer.MaxWidth = options.MaxWidth ?? double.PositiveInfinity;
|
||||
}
|
||||
if (options.Position is Position.Top or Position.Bottom)
|
||||
{
|
||||
drawer.MinHeight = options.MinHeight ?? 0.0;
|
||||
drawer.MaxHeight = options.MaxHeight ?? double.PositiveInfinity;
|
||||
}
|
||||
}
|
||||
}
|
||||
96
src/Ursa/Controls/Drawer/DrawerControlBase.cs
Normal file
96
src/Ursa/Controls/Drawer/DrawerControlBase.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Threading;
|
||||
using Irihi.Avalonia.Shared.Contracts;
|
||||
using Irihi.Avalonia.Shared.Helpers;
|
||||
using Ursa.Common;
|
||||
using Ursa.Controls.OverlayShared;
|
||||
using Ursa.EventArgs;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
[TemplatePart(PART_CloseButton, typeof(Button))]
|
||||
public abstract class DrawerControlBase: OverlayFeedbackElement
|
||||
{
|
||||
public const string PART_CloseButton = "PART_CloseButton";
|
||||
|
||||
protected internal Button? _closeButton;
|
||||
|
||||
public static readonly StyledProperty<Position> PositionProperty =
|
||||
AvaloniaProperty.Register<DrawerControlBase, Position>(
|
||||
nameof(Position), defaultValue: Position.Right);
|
||||
|
||||
public Position Position
|
||||
{
|
||||
get => GetValue(PositionProperty);
|
||||
set => SetValue(PositionProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<bool> IsOpenProperty = AvaloniaProperty.Register<DrawerControlBase, bool>(
|
||||
nameof(IsOpen));
|
||||
|
||||
public bool IsOpen
|
||||
{
|
||||
get => GetValue(IsOpenProperty);
|
||||
set => SetValue(IsOpenProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<bool> IsCloseButtonVisibleProperty =
|
||||
AvaloniaProperty.Register<DrawerControlBase, bool>(
|
||||
nameof(IsCloseButtonVisible), defaultValue: true);
|
||||
|
||||
public bool IsCloseButtonVisible
|
||||
{
|
||||
get => GetValue(IsCloseButtonVisibleProperty);
|
||||
set => SetValue(IsCloseButtonVisibleProperty, value);
|
||||
}
|
||||
|
||||
protected internal bool CanLightDismiss { get; set; }
|
||||
|
||||
static DrawerControlBase()
|
||||
{
|
||||
DataContextProperty.Changed.AddClassHandler<DrawerControlBase, object?>((o, e) => o.OnDataContextChange(e));
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
Button.ClickEvent.RemoveHandler(OnCloseButtonClick, _closeButton);
|
||||
_closeButton = e.NameScope.Find<Button>(PART_CloseButton);
|
||||
Button.ClickEvent.AddHandler(OnCloseButtonClick, _closeButton);
|
||||
}
|
||||
|
||||
private void OnDataContextChange(AvaloniaPropertyChangedEventArgs<object?> args)
|
||||
{
|
||||
if(args.OldValue.Value is IDialogContext oldContext)
|
||||
{
|
||||
oldContext.RequestClose -= OnContextRequestClose;
|
||||
}
|
||||
if(args.NewValue.Value is IDialogContext newContext)
|
||||
{
|
||||
newContext.RequestClose += OnContextRequestClose;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnContextRequestClose(object sender, object? e)
|
||||
{
|
||||
RaiseEvent(new ResultEventArgs(ClosedEvent, e));
|
||||
}
|
||||
|
||||
private void OnCloseButtonClick(object sender, RoutedEventArgs e) => Close();
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
if (DataContext is IDialogContext context)
|
||||
{
|
||||
context.Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
RaiseEvent(new ResultEventArgs(ClosedEvent, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
18
src/Ursa/Controls/Drawer/Options/DrawerOptions.cs
Normal file
18
src/Ursa/Controls/Drawer/Options/DrawerOptions.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using Ursa.Common;
|
||||
|
||||
namespace Ursa.Controls.Options;
|
||||
|
||||
public class DrawerOptions
|
||||
{
|
||||
internal static DrawerOptions Default => new ();
|
||||
public Position Position { get; set; } = Position.Right;
|
||||
public bool CanLightDismiss { get; set; } = true;
|
||||
public bool IsCloseButtonVisible { get; set; } = true;
|
||||
public double? MinWidth { get; set; } = null;
|
||||
public double? MinHeight { get; set; } = null;
|
||||
public double? MaxWidth { get; set; } = null;
|
||||
public double? MaxHeight { get; set; } = null;
|
||||
public DialogButton Buttons { get; set; } = DialogButton.OKCancel;
|
||||
public string? Title { get; set; }
|
||||
public bool ShowCloseButton { get; set; } = true;
|
||||
}
|
||||
158
src/Ursa/Controls/EnumSelector/EnumSelector.cs
Normal file
158
src/Ursa/Controls/EnumSelector/EnumSelector.cs
Normal file
@@ -0,0 +1,158 @@
|
||||
using System.ComponentModel;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Data;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public class EnumItemTuple
|
||||
{
|
||||
public string? DisplayName { get; set; }
|
||||
public object? Value { get; set; }
|
||||
}
|
||||
|
||||
public class EnumSelector: TemplatedControl
|
||||
{
|
||||
public static readonly StyledProperty<Type?> EnumTypeProperty = AvaloniaProperty.Register<EnumSelector, Type?>(
|
||||
nameof(EnumType), validate: OnTypeValidate);
|
||||
|
||||
public Type? EnumType
|
||||
{
|
||||
get => GetValue(EnumTypeProperty);
|
||||
set => SetValue(EnumTypeProperty, value);
|
||||
}
|
||||
|
||||
private static bool OnTypeValidate(Type? arg)
|
||||
{
|
||||
if (arg is null) return true;
|
||||
return arg.IsEnum;
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<object?> ValueProperty = AvaloniaProperty.Register<EnumSelector, object?>(
|
||||
nameof(Value), defaultBindingMode: BindingMode.TwoWay, coerce:OnValueCoerce);
|
||||
|
||||
private static object? OnValueCoerce(AvaloniaObject o, object? value)
|
||||
{
|
||||
if (o is not EnumSelector selector) return null;
|
||||
if (value is null) return null;
|
||||
if (value.GetType() != selector.EnumType) return null;
|
||||
var first = selector.Values?.FirstOrDefault(a => Equals(a.Value, value));
|
||||
if (first is null) return null;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
public object? Value
|
||||
{
|
||||
get => GetValue(ValueProperty);
|
||||
set => SetValue(ValueProperty, value);
|
||||
}
|
||||
|
||||
private EnumItemTuple? _selectedValue;
|
||||
|
||||
public static readonly DirectProperty<EnumSelector, EnumItemTuple?> SelectedValueProperty = AvaloniaProperty.RegisterDirect<EnumSelector, EnumItemTuple?>(
|
||||
nameof(SelectedValue), o => o.SelectedValue, (o, v) => o.SelectedValue = v);
|
||||
|
||||
public EnumItemTuple? SelectedValue
|
||||
{
|
||||
get => _selectedValue;
|
||||
private set => SetAndRaise(SelectedValueProperty, ref _selectedValue, value);
|
||||
}
|
||||
|
||||
public static readonly DirectProperty<EnumSelector, IList<EnumItemTuple>?> ValuesProperty = AvaloniaProperty.RegisterDirect<EnumSelector, IList<EnumItemTuple>?>(
|
||||
nameof(Values), o => o.Values);
|
||||
|
||||
private IList<EnumItemTuple>? _values;
|
||||
internal IList<EnumItemTuple>? Values
|
||||
{
|
||||
get => _values;
|
||||
private set => SetAndRaise(ValuesProperty, ref _values, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<bool> DisplayDescriptionProperty = AvaloniaProperty.Register<EnumSelector, bool>(
|
||||
nameof(DisplayDescription));
|
||||
|
||||
public bool DisplayDescription
|
||||
{
|
||||
get => GetValue(DisplayDescriptionProperty);
|
||||
set => SetValue(DisplayDescriptionProperty, value);
|
||||
}
|
||||
|
||||
static EnumSelector()
|
||||
{
|
||||
EnumTypeProperty.Changed.AddClassHandler<EnumSelector, Type?>((o, e) => o.OnTypeChanged(e));
|
||||
SelectedValueProperty.Changed.AddClassHandler<EnumSelector, EnumItemTuple?>((o, e) => o.OnSelectedValueChanged(e));
|
||||
ValueProperty.Changed.AddClassHandler<EnumSelector, object?>((o, e) => o.OnValueChanged(e));
|
||||
}
|
||||
|
||||
private void OnValueChanged(AvaloniaPropertyChangedEventArgs<object?> args)
|
||||
{
|
||||
if (_updateFromComboBox) return;
|
||||
var newValue = args.NewValue.Value;
|
||||
if (newValue is null)
|
||||
{
|
||||
SetCurrentValue(SelectedValueProperty, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (newValue.GetType() != EnumType)
|
||||
{
|
||||
SetCurrentValue(SelectedValueProperty, null);
|
||||
}
|
||||
var tuple = Values?.FirstOrDefault(x => Equals(x.Value, newValue));
|
||||
SetCurrentValue(SelectedValueProperty, tuple);
|
||||
}
|
||||
}
|
||||
|
||||
private bool _updateFromComboBox;
|
||||
|
||||
private void OnSelectedValueChanged(AvaloniaPropertyChangedEventArgs<EnumItemTuple?> args)
|
||||
{
|
||||
_updateFromComboBox = true;
|
||||
var newValue = args.NewValue.Value;
|
||||
SetCurrentValue(ValueProperty, newValue?.Value);
|
||||
_updateFromComboBox = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void OnTypeChanged(AvaloniaPropertyChangedEventArgs<Type?> args)
|
||||
{
|
||||
Values?.Clear();
|
||||
var newType = args.GetNewValue<Type?>();
|
||||
if (newType is null || !newType.IsEnum)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Values = GenerateItemTuple();
|
||||
}
|
||||
|
||||
private List<EnumItemTuple> GenerateItemTuple()
|
||||
{
|
||||
if (EnumType is null) return new List<EnumItemTuple>();
|
||||
var values = Enum.GetValues(EnumType);
|
||||
List<EnumItemTuple> list = new();
|
||||
var fields = EnumType.GetFields();
|
||||
foreach (var value in values)
|
||||
{
|
||||
if (value.GetType() == EnumType)
|
||||
{
|
||||
var displayName = value.ToString();
|
||||
var field = EnumType.GetField(displayName);
|
||||
var description = field?.GetCustomAttributes(typeof(DescriptionAttribute), false).FirstOrDefault();
|
||||
if (description is not null)
|
||||
{
|
||||
displayName = ((DescriptionAttribute) description).Description;
|
||||
}
|
||||
list.Add(new EnumItemTuple()
|
||||
{
|
||||
DisplayName = displayName,
|
||||
Value = value
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
76
src/Ursa/Controls/Form/Form.cs
Normal file
76
src/Ursa/Controls/Form/Form.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Layout;
|
||||
using Ursa.Common;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
[PseudoClasses(PC_FixedWidth)]
|
||||
public class Form: ItemsControl
|
||||
{
|
||||
public const string PC_FixedWidth = ":fixed-width";
|
||||
|
||||
public static readonly StyledProperty<GridLength> LabelWidthProperty = AvaloniaProperty.Register<Form, GridLength>(
|
||||
nameof(LabelWidth));
|
||||
|
||||
/// <summary>
|
||||
/// Behavior:
|
||||
/// <para>Fixed Width: all labels are with fixed length. </para>
|
||||
/// <para>Star: all labels are aligned by max length. </para>
|
||||
/// <para>Auto: labels are not aligned. </para>
|
||||
/// </summary>
|
||||
public GridLength LabelWidth
|
||||
{
|
||||
get => GetValue(LabelWidthProperty);
|
||||
set => SetValue(LabelWidthProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<Position> LabelPositionProperty = AvaloniaProperty.Register<Form, Position>(
|
||||
nameof(LabelPosition), defaultValue: Position.Top);
|
||||
|
||||
public Position LabelPosition
|
||||
{
|
||||
get => GetValue(LabelPositionProperty);
|
||||
set => SetValue(LabelPositionProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<HorizontalAlignment> LabelAlignmentProperty = AvaloniaProperty.Register<Form, HorizontalAlignment>(
|
||||
nameof(LabelAlignment), defaultValue: HorizontalAlignment.Left);
|
||||
|
||||
public HorizontalAlignment LabelAlignment
|
||||
{
|
||||
get => GetValue(LabelAlignmentProperty);
|
||||
set => SetValue(LabelAlignmentProperty, value);
|
||||
}
|
||||
|
||||
static Form()
|
||||
{
|
||||
LabelWidthProperty.Changed.AddClassHandler<Form, GridLength>((x, args) => x.LabelWidthChanged(args));
|
||||
}
|
||||
|
||||
private void LabelWidthChanged(AvaloniaPropertyChangedEventArgs<GridLength> args)
|
||||
{
|
||||
var newValue = args.NewValue.Value;
|
||||
bool isFixed = newValue.IsStar || newValue.IsAbsolute;
|
||||
PseudoClasses.Set(PC_FixedWidth, isFixed);
|
||||
}
|
||||
|
||||
protected override bool NeedsContainerOverride(object? item, int index, out object? recycleKey)
|
||||
{
|
||||
recycleKey = null;
|
||||
return item is not FormItem && item is not FormGroup;
|
||||
}
|
||||
|
||||
protected override Control CreateContainerForItemOverride(object? item, int index, object? recycleKey)
|
||||
{
|
||||
if (item is not Control control) return new FormItem();
|
||||
return new FormItem()
|
||||
{
|
||||
Content = control,
|
||||
[!FormItem.LabelProperty] = control[!FormItem.LabelProperty],
|
||||
[!FormItem.IsRequiredProperty] = control[!FormItem.IsRequiredProperty],
|
||||
[!FormItem.NoLabelProperty] = control[!FormItem.NoLabelProperty],
|
||||
};
|
||||
}
|
||||
}
|
||||
26
src/Ursa/Controls/Form/FormGroup.cs
Normal file
26
src/Ursa/Controls/Form/FormGroup.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public class FormGroup: HeaderedItemsControl
|
||||
{
|
||||
protected override bool NeedsContainerOverride(object? item, int index, out object? recycleKey)
|
||||
{
|
||||
recycleKey = null;
|
||||
return item is not FormItem;
|
||||
}
|
||||
|
||||
protected override Control CreateContainerForItemOverride(object? item, int index, object? recycleKey)
|
||||
{
|
||||
if (item is not Control control) return new FormItem();
|
||||
return new FormItem
|
||||
{
|
||||
Content = control,
|
||||
[!FormItem.LabelProperty] = control[!FormItem.LabelProperty],
|
||||
[!FormItem.IsRequiredProperty] = control[!FormItem.IsRequiredProperty],
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
93
src/Ursa/Controls/Form/FormItem.cs
Normal file
93
src/Ursa/Controls/Form/FormItem.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Reactive;
|
||||
using Avalonia.VisualTree;
|
||||
using Irihi.Avalonia.Shared.Helpers;
|
||||
using Ursa.Common;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
[PseudoClasses(PC_Horizontal, PC_NoLabel)]
|
||||
public class FormItem: ContentControl
|
||||
{
|
||||
public const string PC_Horizontal = ":horizontal";
|
||||
public const string PC_NoLabel = ":no-label";
|
||||
|
||||
#region Attached Properties
|
||||
public static readonly AttachedProperty<object?> LabelProperty =
|
||||
AvaloniaProperty.RegisterAttached<FormItem, Control, object?>("Label");
|
||||
public static void SetLabel(Control obj, object? value) => obj.SetValue(LabelProperty, value);
|
||||
public static object? GetLabel(Control obj) => obj.GetValue(LabelProperty);
|
||||
|
||||
|
||||
public static readonly AttachedProperty<bool> IsRequiredProperty =
|
||||
AvaloniaProperty.RegisterAttached<FormItem, Control, bool>("IsRequired");
|
||||
public static void SetIsRequired(Control obj, bool value) => obj.SetValue(IsRequiredProperty, value);
|
||||
public static bool GetIsRequired(Control obj) => obj.GetValue(IsRequiredProperty);
|
||||
|
||||
public static readonly AttachedProperty<bool> NoLabelProperty =
|
||||
AvaloniaProperty.RegisterAttached<FormItem, Control, bool>("NoLabel");
|
||||
|
||||
public static void SetNoLabel(Control obj, bool value) => obj.SetValue(NoLabelProperty, value);
|
||||
public static bool GetNoLabel(Control obj) => obj.GetValue(NoLabelProperty);
|
||||
#endregion
|
||||
|
||||
private List<IDisposable> _formSubscriptions = new List<IDisposable>();
|
||||
|
||||
public static readonly StyledProperty<double> LabelWidthProperty = AvaloniaProperty.Register<FormItem, double>(
|
||||
nameof(LabelWidth));
|
||||
|
||||
public double LabelWidth
|
||||
{
|
||||
get => GetValue(LabelWidthProperty);
|
||||
set => SetValue(LabelWidthProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<HorizontalAlignment> LabelAlignmentProperty = AvaloniaProperty.Register<FormItem, HorizontalAlignment>(
|
||||
nameof(LabelAlignment));
|
||||
|
||||
public HorizontalAlignment LabelAlignment
|
||||
{
|
||||
get => GetValue(LabelAlignmentProperty);
|
||||
set => SetValue(LabelAlignmentProperty, value);
|
||||
}
|
||||
|
||||
static FormItem()
|
||||
{
|
||||
NoLabelProperty.AffectsPseudoClass<FormItem>(PC_NoLabel);
|
||||
}
|
||||
|
||||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnAttachedToVisualTree(e);
|
||||
var form = this.GetVisualAncestors().OfType<Form>().FirstOrDefault();
|
||||
if (form is not null)
|
||||
{
|
||||
_formSubscriptions.Clear();
|
||||
var labelSubscription = form
|
||||
.GetObservable(Form.LabelWidthProperty)
|
||||
.Subscribe(new AnonymousObserver<GridLength>(length => { LabelWidth = length.IsAbsolute ? length.Value : double.NaN; }));
|
||||
var positionSubscription = form
|
||||
.GetObservable(Form.LabelPositionProperty)
|
||||
.Subscribe(new AnonymousObserver<Position>(position => { PseudoClasses.Set(PC_Horizontal, position == Position.Left);}));
|
||||
var alignmentSubscription = form
|
||||
.GetObservable(Form.LabelAlignmentProperty)
|
||||
.Subscribe(new AnonymousObserver<HorizontalAlignment>(alignment => { LabelAlignment = alignment; }));
|
||||
_formSubscriptions.Add(labelSubscription);
|
||||
_formSubscriptions.Add(positionSubscription);
|
||||
_formSubscriptions.Add(alignmentSubscription);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnDetachedFromVisualTree(e);
|
||||
foreach (var subscription in _formSubscriptions)
|
||||
{
|
||||
subscription.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
87
src/Ursa/Controls/Icons/TwoTonePathIcon.cs
Normal file
87
src/Ursa/Controls/Icons/TwoTonePathIcon.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
using System.ComponentModel;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Media;
|
||||
using Irihi.Avalonia.Shared.Helpers;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
[PseudoClasses(PC_Active)]
|
||||
public class TwoTonePathIcon: TemplatedControl
|
||||
{
|
||||
public const string PC_Active = ":active";
|
||||
|
||||
public static readonly StyledProperty<IBrush?> StrokeBrushProperty = AvaloniaProperty.Register<TwoTonePathIcon, IBrush?>(
|
||||
nameof(StrokeBrush));
|
||||
|
||||
public IBrush? StrokeBrush
|
||||
{
|
||||
get => GetValue(StrokeBrushProperty);
|
||||
set => SetValue(StrokeBrushProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<Geometry> DataProperty = AvaloniaProperty.Register<PathIcon, Geometry>(
|
||||
nameof(Data));
|
||||
|
||||
public Geometry Data
|
||||
{
|
||||
get => GetValue(DataProperty);
|
||||
set => SetValue(DataProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<bool> IsActiveProperty = AvaloniaProperty.Register<TwoTonePathIcon, bool>(
|
||||
nameof(IsActive), defaultBindingMode: BindingMode.TwoWay);
|
||||
|
||||
public bool IsActive
|
||||
{
|
||||
get => GetValue(IsActiveProperty);
|
||||
set => SetValue(IsActiveProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IBrush?> ActiveForegroundProperty = AvaloniaProperty.Register<TwoTonePathIcon, IBrush?>(
|
||||
nameof(ActiveForeground));
|
||||
|
||||
public IBrush? ActiveForeground
|
||||
{
|
||||
get => GetValue(ActiveForegroundProperty);
|
||||
set => SetValue(ActiveForegroundProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IBrush?> ActiveStrokeBrushProperty = AvaloniaProperty.Register<TwoTonePathIcon, IBrush?>(
|
||||
nameof(ActiveStrokeBrush));
|
||||
|
||||
public IBrush? ActiveStrokeBrush
|
||||
{
|
||||
get => GetValue(ActiveStrokeBrushProperty);
|
||||
set => SetValue(ActiveStrokeBrushProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<double> StrokeThicknessProperty =
|
||||
AvaloniaProperty.Register<TwoTonePathIcon, double>(
|
||||
nameof(StrokeThickness));
|
||||
public double StrokeThickness
|
||||
{
|
||||
get => GetValue(StrokeThicknessProperty);
|
||||
set => SetValue(StrokeThicknessProperty, value);
|
||||
}
|
||||
|
||||
static TwoTonePathIcon()
|
||||
{
|
||||
AffectsRender<TwoTonePathIcon>(
|
||||
DataProperty,
|
||||
StrokeBrushProperty,
|
||||
ForegroundProperty,
|
||||
ActiveForegroundProperty,
|
||||
ActiveStrokeBrushProperty);
|
||||
IsActiveProperty.AffectsPseudoClass<TwoTonePathIcon>(PC_Active);
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
PseudoClasses.Set(PC_Active, IsActive);
|
||||
}
|
||||
}
|
||||
271
src/Ursa/Controls/ImageViewer/ImageViewer.cs
Normal file
271
src/Ursa/Controls/ImageViewer/ImageViewer.cs
Normal file
@@ -0,0 +1,271 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Media.Imaging;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
[TemplatePart(PART_Image, typeof(Image))]
|
||||
[TemplatePart(PART_Layer, typeof(VisualLayerManager))]
|
||||
[PseudoClasses(PC_Moving)]
|
||||
public class ImageViewer: TemplatedControl
|
||||
{
|
||||
public const string PART_Image = "PART_Image";
|
||||
public const string PART_Layer = "PART_Layer";
|
||||
public const string PC_Moving = ":moving";
|
||||
|
||||
private Image? _image = null!;
|
||||
private VisualLayerManager? _layer;
|
||||
private Point? _lastClickPoint;
|
||||
private Point? _lastLocation;
|
||||
private bool _moving;
|
||||
|
||||
public static readonly StyledProperty<Control?> OverlayerProperty = AvaloniaProperty.Register<ImageViewer, Control?>(
|
||||
nameof(Overlayer));
|
||||
|
||||
public Control? Overlayer
|
||||
{
|
||||
get => GetValue(OverlayerProperty);
|
||||
set => SetValue(OverlayerProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IImage?> SourceProperty = Image.SourceProperty.AddOwner<ImageViewer>();
|
||||
public IImage? Source
|
||||
{
|
||||
get => GetValue(SourceProperty);
|
||||
set => SetValue(SourceProperty, value);
|
||||
}
|
||||
|
||||
private double _scale = 1;
|
||||
|
||||
public static readonly DirectProperty<ImageViewer, double> ScaleProperty = AvaloniaProperty.RegisterDirect<ImageViewer, double>(
|
||||
nameof(Scale), o => o.Scale, (o,v)=> o.Scale = v, unsetValue: 1);
|
||||
|
||||
public double Scale
|
||||
{
|
||||
get => _scale;
|
||||
set => SetAndRaise(ScaleProperty, ref _scale, value);
|
||||
}
|
||||
|
||||
private double _translateX;
|
||||
|
||||
public static readonly DirectProperty<ImageViewer, double> TranslateXProperty = AvaloniaProperty.RegisterDirect<ImageViewer, double>(
|
||||
nameof(TranslateX), o => o.TranslateX, (o,v)=>o.TranslateX = v, unsetValue: 0);
|
||||
|
||||
public double TranslateX
|
||||
{
|
||||
get => _translateX;
|
||||
set => SetAndRaise(TranslateXProperty, ref _translateX, value);
|
||||
}
|
||||
|
||||
private double _translateY;
|
||||
|
||||
public static readonly DirectProperty<ImageViewer, double> TranslateYProperty =
|
||||
AvaloniaProperty.RegisterDirect<ImageViewer, double>(
|
||||
nameof(TranslateY), o => o.TranslateY, (o, v) => o.TranslateY = v, unsetValue: 0);
|
||||
|
||||
public double TranslateY
|
||||
{
|
||||
get => _translateY;
|
||||
set => SetAndRaise(TranslateYProperty, ref _translateY, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<double> SmallChangeProperty = AvaloniaProperty.Register<ImageViewer, double>(
|
||||
nameof(SmallChange), defaultValue: 1);
|
||||
|
||||
public double SmallChange
|
||||
{
|
||||
get => GetValue(SmallChangeProperty);
|
||||
set => SetValue(SmallChangeProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<double> LargeChangeProperty = AvaloniaProperty.Register<ImageViewer, double>(
|
||||
nameof(LargeChange), defaultValue: 10);
|
||||
|
||||
public double LargeChange
|
||||
{
|
||||
get => GetValue(LargeChangeProperty);
|
||||
set => SetValue(LargeChangeProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<Stretch> StretchProperty =
|
||||
Image.StretchProperty.AddOwner<ImageViewer>(new StyledPropertyMetadata<Stretch>(Stretch.Uniform));
|
||||
|
||||
public Stretch Stretch
|
||||
{
|
||||
get => GetValue(StretchProperty);
|
||||
set => SetValue(StretchProperty, value);
|
||||
}
|
||||
|
||||
static ImageViewer()
|
||||
{
|
||||
FocusableProperty.OverrideDefaultValue<ImageViewer>(true);
|
||||
OverlayerProperty.Changed.AddClassHandler<ImageViewer>((o, e) => o.OnOverlayerChanged(e));
|
||||
SourceProperty.Changed.AddClassHandler<ImageViewer>((o, e) => o.OnSourceChanged(e));
|
||||
TranslateXProperty.Changed.AddClassHandler<ImageViewer>((o,e)=>o.OnTranslateXChanged(e));
|
||||
TranslateYProperty.Changed.AddClassHandler<ImageViewer>((o, e) => o.OnTranslateYChanged(e));
|
||||
StretchProperty.Changed.AddClassHandler<ImageViewer>((o, e) => o.OnStretchChanged(e));
|
||||
}
|
||||
|
||||
private void OnTranslateYChanged(AvaloniaPropertyChangedEventArgs args)
|
||||
{
|
||||
if (_moving) return;
|
||||
var newValue = args.GetNewValue<double>();
|
||||
if (_lastLocation is not null)
|
||||
{
|
||||
_lastLocation = _lastLocation.Value.WithY(newValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
_lastLocation = new Point(0, newValue);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTranslateXChanged(AvaloniaPropertyChangedEventArgs args)
|
||||
{
|
||||
if (_moving) return;
|
||||
var newValue = args.GetNewValue<double>();
|
||||
if (_lastLocation is not null)
|
||||
{
|
||||
_lastLocation = _lastLocation.Value.WithX(newValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
_lastLocation = new Point(newValue, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnOverlayerChanged(AvaloniaPropertyChangedEventArgs args)
|
||||
{
|
||||
var control = args.GetNewValue<Control?>();
|
||||
if (control is { } c)
|
||||
{
|
||||
AdornerLayer.SetAdorner(this, c);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSourceChanged(AvaloniaPropertyChangedEventArgs args)
|
||||
{
|
||||
IImage image = args.GetNewValue<IImage>();
|
||||
Size size = image.Size;
|
||||
double width = this.Bounds.Width;
|
||||
double height = this.Bounds.Height;
|
||||
if (_image is not null)
|
||||
{
|
||||
_image.Width = size.Width;
|
||||
_image.Height = size.Height;
|
||||
}
|
||||
Scale = GetScaleRatio(width/size.Width, height/size.Height, this.Stretch);
|
||||
}
|
||||
|
||||
private void OnStretchChanged(AvaloniaPropertyChangedEventArgs args)
|
||||
{
|
||||
var stretch = args.GetNewValue<Stretch>();
|
||||
Scale = GetScaleRatio(Width / _image!.Width, Height / _image!.Height, stretch);
|
||||
}
|
||||
|
||||
private double GetScaleRatio(double widthRatio, double heightRatio, Stretch stretch)
|
||||
{
|
||||
return stretch switch
|
||||
{
|
||||
Stretch.Fill => 1d,
|
||||
Stretch.None => 1d,
|
||||
Stretch.Uniform => Math.Min(widthRatio, heightRatio),
|
||||
Stretch.UniformToFill => Math.Max(widthRatio, heightRatio),
|
||||
_ => 1d,
|
||||
};
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
_image = e.NameScope.Get<Image>(PART_Image);
|
||||
_layer = e.NameScope.Get<VisualLayerManager>(PART_Layer);
|
||||
if (Source is { } i)
|
||||
{
|
||||
Size size = i.Size;
|
||||
double width = Bounds.Width;
|
||||
double height = Bounds.Height;
|
||||
_image.Width = size.Width;
|
||||
_image.Height = size.Height;
|
||||
Scale = GetScaleRatio(width/size.Width, height/size.Height, this.Stretch);
|
||||
}
|
||||
if (Overlayer is { } c)
|
||||
{
|
||||
AdornerLayer.SetAdorner(this, c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected override void OnPointerWheelChanged(PointerWheelEventArgs e)
|
||||
{
|
||||
base.OnPointerWheelChanged(e);
|
||||
if(e.Delta.Y > 0)
|
||||
{
|
||||
Scale *= 1.1;
|
||||
}
|
||||
else
|
||||
{
|
||||
var scale = Scale;
|
||||
scale /= 1.1;
|
||||
if (scale < 0.1) scale = 0.1;
|
||||
Scale = scale;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPointerMoved(PointerEventArgs e)
|
||||
{
|
||||
base.OnPointerMoved(e);
|
||||
if (e.Pointer.Captured == this && _lastClickPoint != null)
|
||||
{
|
||||
PseudoClasses.Set(PC_Moving, true);
|
||||
Point p = e.GetPosition(this);
|
||||
double deltaX = p.X - _lastClickPoint.Value.X;
|
||||
double deltaY = p.Y - _lastClickPoint.Value.Y;
|
||||
TranslateX = deltaX + (_lastLocation?.X ?? 0);
|
||||
TranslateY = deltaY + (_lastLocation?.Y ?? 0);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPointerPressed(PointerPressedEventArgs e)
|
||||
{
|
||||
base.OnPointerPressed(e);
|
||||
e.Pointer.Capture(this);
|
||||
_lastClickPoint = e.GetPosition(this);
|
||||
_moving = true;
|
||||
}
|
||||
|
||||
protected override void OnPointerReleased(PointerReleasedEventArgs e)
|
||||
{
|
||||
base.OnPointerReleased(e);
|
||||
e.Pointer.Capture(null);
|
||||
_lastLocation = new Point(TranslateX, TranslateY);
|
||||
PseudoClasses.Set(PC_Moving, false);
|
||||
_moving = false;
|
||||
}
|
||||
|
||||
protected override void OnKeyDown(KeyEventArgs e)
|
||||
{
|
||||
double step = e.KeyModifiers.HasFlag(KeyModifiers.Control) ? LargeChange : SmallChange;
|
||||
switch (e.Key)
|
||||
{
|
||||
case Key.Left:
|
||||
TranslateX -= step;
|
||||
break;
|
||||
case Key.Right:
|
||||
TranslateX += step;
|
||||
break;
|
||||
case Key.Up:
|
||||
TranslateY -= step;
|
||||
break;
|
||||
case Key.Down:
|
||||
TranslateY += step;
|
||||
break;
|
||||
}
|
||||
base.OnKeyDown(e);
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,29 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Converters;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Layout;
|
||||
using Irihi.Avalonia.Shared.Contracts;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public class KeyGestureInput: TemplatedControl
|
||||
[PseudoClasses(PC_Empty)]
|
||||
public class KeyGestureInput: TemplatedControl, IClearControl, IInnerContentControl
|
||||
{
|
||||
public const string PC_Empty = ":empty";
|
||||
static KeyGestureInput()
|
||||
{
|
||||
InputElement.FocusableProperty.OverrideDefaultValue<KeyGestureInput>(true);
|
||||
FocusableProperty.OverrideDefaultValue<KeyGestureInput>(true);
|
||||
GestureProperty.Changed.AddClassHandler<KeyGestureInput, KeyGesture?>((x, e) =>
|
||||
x.PseudoClasses.Set(PC_Empty, e.NewValue.Value is null));
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<KeyGesture> GestureProperty = AvaloniaProperty.Register<KeyGestureInput, KeyGesture>(
|
||||
public static readonly StyledProperty<KeyGesture?> GestureProperty = AvaloniaProperty.Register<KeyGestureInput, KeyGesture?>(
|
||||
nameof(Gesture));
|
||||
|
||||
public KeyGesture Gesture
|
||||
public KeyGesture? Gesture
|
||||
{
|
||||
get => GetValue(GestureProperty);
|
||||
set => SetValue(GestureProperty, value);
|
||||
@@ -60,7 +66,30 @@ public class KeyGestureInput: TemplatedControl
|
||||
get => GetValue(VerticalContentAlignmentProperty);
|
||||
set => SetValue(VerticalContentAlignmentProperty, value);
|
||||
}
|
||||
|
||||
|
||||
public static readonly StyledProperty<object?> InnerLeftContentProperty = AvaloniaProperty.Register<KeyGestureInput, object?>(
|
||||
nameof(InnerLeftContent));
|
||||
|
||||
public object? InnerLeftContent
|
||||
{
|
||||
get => GetValue(InnerLeftContentProperty);
|
||||
set => SetValue(InnerLeftContentProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<object?> InnerRightContentProperty = AvaloniaProperty.Register<KeyGestureInput, object?>(
|
||||
nameof(InnerRightContent));
|
||||
|
||||
public object? InnerRightContent
|
||||
{
|
||||
get => GetValue(InnerRightContentProperty);
|
||||
set => SetValue(InnerRightContentProperty, value);
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
PseudoClasses.Set(PC_Empty, Gesture is null);
|
||||
}
|
||||
|
||||
protected override void OnKeyDown(KeyEventArgs e)
|
||||
{
|
||||
@@ -94,4 +123,9 @@ public class KeyGestureInput: TemplatedControl
|
||||
Gesture = gesture;
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
SetCurrentValue(GestureProperty, null);
|
||||
}
|
||||
}
|
||||
8
src/Ursa/Controls/Layout/DefaultDialogLayout.cs
Normal file
8
src/Ursa/Controls/Layout/DefaultDialogLayout.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
using Avalonia.Controls.Primitives;
|
||||
|
||||
namespace Ursa.Controls.Layout;
|
||||
|
||||
public class DefaultDialogLayout: TemplatedControl
|
||||
{
|
||||
|
||||
}
|
||||
81
src/Ursa/Controls/MessageBox/MessageBox.cs
Normal file
81
src/Ursa/Controls/MessageBox/MessageBox.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Controls.Notifications;
|
||||
using Avalonia.Styling;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public static class MessageBox
|
||||
{
|
||||
public static async Task<MessageBoxResult> ShowAsync(
|
||||
string message,
|
||||
string? title = null,
|
||||
MessageBoxIcon icon = MessageBoxIcon.None,
|
||||
MessageBoxButton button = MessageBoxButton.OKCancel)
|
||||
{
|
||||
var messageWindow = new MessageBoxWindow(button)
|
||||
{
|
||||
Content = message,
|
||||
Title = title,
|
||||
MessageIcon = icon,
|
||||
};
|
||||
var lifetime = Application.Current?.ApplicationLifetime;
|
||||
if (lifetime is IClassicDesktopStyleApplicationLifetime classLifetime)
|
||||
{
|
||||
var main = classLifetime.MainWindow;
|
||||
if (main is null)
|
||||
{
|
||||
messageWindow.Show();
|
||||
return MessageBoxResult.None;
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await messageWindow.ShowDialog<MessageBoxResult>(main);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return MessageBoxResult.None;
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<MessageBoxResult> ShowAsync(
|
||||
Window owner,
|
||||
string message,
|
||||
string title,
|
||||
MessageBoxIcon icon = MessageBoxIcon.None,
|
||||
MessageBoxButton button = MessageBoxButton.OKCancel)
|
||||
{
|
||||
var messageWindow = new MessageBoxWindow(button)
|
||||
{
|
||||
Content = message,
|
||||
Title = title,
|
||||
MessageIcon = icon,
|
||||
};
|
||||
var result = await messageWindow.ShowDialog<MessageBoxResult>(owner);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async Task<MessageBoxResult> ShowOverlayAsync(
|
||||
string message,
|
||||
string? title = null,
|
||||
string? hostId = null,
|
||||
MessageBoxIcon icon = MessageBoxIcon.None,
|
||||
MessageBoxButton button = MessageBoxButton.OKCancel)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return MessageBoxResult.None;
|
||||
var messageControl = new MessageBoxControl()
|
||||
{
|
||||
Content = message,
|
||||
Title = title,
|
||||
Buttons = button,
|
||||
MessageIcon = icon,
|
||||
};
|
||||
host.AddModalDialog(messageControl);
|
||||
var result = await messageControl.ShowAsync<MessageBoxResult>();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
9
src/Ursa/Controls/MessageBox/MessageBoxButton.cs
Normal file
9
src/Ursa/Controls/MessageBox/MessageBoxButton.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public enum MessageBoxButton
|
||||
{
|
||||
OK,
|
||||
OKCancel,
|
||||
YesNo,
|
||||
YesNoCancel,
|
||||
}
|
||||
136
src/Ursa/Controls/MessageBox/MessageBoxControl.cs
Normal file
136
src/Ursa/Controls/MessageBox/MessageBoxControl.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Styling;
|
||||
using Irihi.Avalonia.Shared.Helpers;
|
||||
using Ursa.Common;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
/// <summary>
|
||||
/// The messageBox used to display in OverlayDialogHost.
|
||||
/// </summary>
|
||||
[TemplatePart(PART_NoButton, typeof(Button))]
|
||||
[TemplatePart(PART_OKButton, typeof(Button))]
|
||||
[TemplatePart(PART_CancelButton, typeof(Button))]
|
||||
[TemplatePart(PART_YesButton, typeof(Button))]
|
||||
public class MessageBoxControl: DialogControlBase
|
||||
{
|
||||
public const string PART_YesButton = "PART_YesButton";
|
||||
public const string PART_NoButton = "PART_NoButton";
|
||||
public const string PART_OKButton = "PART_OKButton";
|
||||
public const string PART_CancelButton = "PART_CancelButton";
|
||||
|
||||
private Button? _yesButton;
|
||||
private Button? _noButton;
|
||||
private Button? _okButton;
|
||||
private Button? _cancelButton;
|
||||
|
||||
public static readonly StyledProperty<MessageBoxIcon> MessageIconProperty =
|
||||
AvaloniaProperty.Register<MessageBoxWindow, MessageBoxIcon>(
|
||||
nameof(MessageIcon));
|
||||
|
||||
public MessageBoxIcon MessageIcon
|
||||
{
|
||||
get => GetValue(MessageIconProperty);
|
||||
set => SetValue(MessageIconProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<MessageBoxButton> ButtonsProperty = AvaloniaProperty.Register<MessageBoxControl, MessageBoxButton>(
|
||||
nameof(Buttons), MessageBoxButton.OK);
|
||||
|
||||
public MessageBoxButton Buttons
|
||||
{
|
||||
get => GetValue(ButtonsProperty);
|
||||
set => SetValue(ButtonsProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<string?> TitleProperty = AvaloniaProperty.Register<MessageBoxControl, string?>(
|
||||
nameof(Title));
|
||||
|
||||
public string? Title
|
||||
{
|
||||
get => GetValue(TitleProperty);
|
||||
set => SetValue(TitleProperty, value);
|
||||
}
|
||||
|
||||
static MessageBoxControl()
|
||||
{
|
||||
ButtonsProperty.Changed.AddClassHandler<MessageBoxControl>((o, e) => { o.SetButtonVisibility(); });
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
Button.ClickEvent.RemoveHandler(DefaultButtonsClose, _okButton, _cancelButton, _yesButton, _noButton);
|
||||
_okButton = e.NameScope.Find<Button>(PART_OKButton);
|
||||
_cancelButton = e.NameScope.Find<Button>(PART_CancelButton);
|
||||
_yesButton = e.NameScope.Find<Button>(PART_YesButton);
|
||||
_noButton = e.NameScope.Find<Button>(PART_NoButton);
|
||||
Button.ClickEvent.AddHandler(DefaultButtonsClose, _okButton, _cancelButton, _yesButton, _noButton);
|
||||
SetButtonVisibility();
|
||||
}
|
||||
|
||||
private void DefaultButtonsClose(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button button)
|
||||
{
|
||||
if (button == _okButton)
|
||||
{
|
||||
OnElementClosing(this, MessageBoxResult.OK);
|
||||
}
|
||||
else if (button == _cancelButton)
|
||||
{
|
||||
OnElementClosing(this, MessageBoxResult.Cancel);
|
||||
}
|
||||
else if (button == _yesButton)
|
||||
{
|
||||
OnElementClosing(this, MessageBoxResult.Yes);
|
||||
}
|
||||
else if (button == _noButton)
|
||||
{
|
||||
OnElementClosing(this, MessageBoxResult.No);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetButtonVisibility()
|
||||
{
|
||||
switch (Buttons)
|
||||
{
|
||||
case MessageBoxButton.OK:
|
||||
Button.IsVisibleProperty.SetValue(true, _okButton);
|
||||
Button.IsVisibleProperty.SetValue(false, _cancelButton, _yesButton, _noButton);
|
||||
break;
|
||||
case MessageBoxButton.OKCancel:
|
||||
Button.IsVisibleProperty.SetValue(true, _okButton, _cancelButton);
|
||||
Button.IsVisibleProperty.SetValue(false, _yesButton, _noButton);
|
||||
break;
|
||||
case MessageBoxButton.YesNo:
|
||||
Button.IsVisibleProperty.SetValue(false, _okButton, _cancelButton);
|
||||
Button.IsVisibleProperty.SetValue(true, _yesButton, _noButton);
|
||||
break;
|
||||
case MessageBoxButton.YesNoCancel:
|
||||
Button.IsVisibleProperty.SetValue(false, _okButton);
|
||||
Button.IsVisibleProperty.SetValue(true, _cancelButton, _yesButton, _noButton);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
MessageBoxResult result = Buttons switch
|
||||
{
|
||||
MessageBoxButton.OK => MessageBoxResult.OK,
|
||||
MessageBoxButton.OKCancel => MessageBoxResult.Cancel,
|
||||
MessageBoxButton.YesNo => MessageBoxResult.No,
|
||||
MessageBoxButton.YesNoCancel => MessageBoxResult.Cancel,
|
||||
_ => MessageBoxResult.None
|
||||
};
|
||||
OnElementClosing(this, result);
|
||||
}
|
||||
}
|
||||
15
src/Ursa/Controls/MessageBox/MessageBoxIcon.cs
Normal file
15
src/Ursa/Controls/MessageBox/MessageBoxIcon.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public enum MessageBoxIcon
|
||||
{
|
||||
Asterisk, // Same as Information
|
||||
Error,
|
||||
Exclamation, // Same as Warning
|
||||
Hand, // Same as Error
|
||||
Information,
|
||||
None,
|
||||
Question,
|
||||
Stop, // Same as Error
|
||||
Warning,
|
||||
Success,
|
||||
}
|
||||
10
src/Ursa/Controls/MessageBox/MessageBoxResult.cs
Normal file
10
src/Ursa/Controls/MessageBox/MessageBoxResult.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public enum MessageBoxResult
|
||||
{
|
||||
Cancel,
|
||||
No,
|
||||
None,
|
||||
OK,
|
||||
Yes,
|
||||
}
|
||||
137
src/Ursa/Controls/MessageBox/MessageBoxWindow.cs
Normal file
137
src/Ursa/Controls/MessageBox/MessageBoxWindow.cs
Normal file
@@ -0,0 +1,137 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Platform;
|
||||
using Irihi.Avalonia.Shared.Helpers;
|
||||
using Ursa.Common;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
[TemplatePart(PART_CloseButton, typeof(Button))]
|
||||
[TemplatePart(PART_NoButton, typeof(Button))]
|
||||
[TemplatePart(PART_OKButton, typeof(Button))]
|
||||
[TemplatePart(PART_CancelButton, typeof(Button))]
|
||||
[TemplatePart(PART_YesButton, typeof(Button))]
|
||||
public class MessageBoxWindow : Window
|
||||
{
|
||||
public const string PART_CloseButton = "PART_CloseButton";
|
||||
public const string PART_YesButton = "PART_YesButton";
|
||||
public const string PART_NoButton = "PART_NoButton";
|
||||
public const string PART_OKButton = "PART_OKButton";
|
||||
public const string PART_CancelButton = "PART_CancelButton";
|
||||
|
||||
private MessageBoxButton _buttonConfigs;
|
||||
|
||||
private Button? _closeButton;
|
||||
private Button? _yesButton;
|
||||
private Button? _noButton;
|
||||
private Button? _okButton;
|
||||
private Button? _cancelButton;
|
||||
|
||||
protected override Type StyleKeyOverride => typeof(MessageBoxWindow);
|
||||
|
||||
public static readonly StyledProperty<MessageBoxIcon> MessageIconProperty =
|
||||
AvaloniaProperty.Register<MessageBoxWindow, MessageBoxIcon>(
|
||||
nameof(MessageIcon));
|
||||
|
||||
public MessageBoxIcon MessageIcon
|
||||
{
|
||||
get => GetValue(MessageIconProperty);
|
||||
set => SetValue(MessageIconProperty, value);
|
||||
}
|
||||
|
||||
public MessageBoxWindow()
|
||||
{
|
||||
_buttonConfigs = MessageBoxButton.OK;
|
||||
}
|
||||
|
||||
public MessageBoxWindow(MessageBoxButton buttons)
|
||||
{
|
||||
_buttonConfigs = buttons;
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
Button.ClickEvent.RemoveHandler(OnDefaultButtonClick, _yesButton, _noButton, _okButton, _cancelButton);
|
||||
Button.ClickEvent.RemoveHandler(OnCloseButtonClick, _closeButton);
|
||||
_yesButton = e.NameScope.Find<Button>(PART_YesButton);
|
||||
_noButton = e.NameScope.Find<Button>(PART_NoButton);
|
||||
_okButton = e.NameScope.Find<Button>(PART_OKButton);
|
||||
_cancelButton = e.NameScope.Find<Button>(PART_CancelButton);
|
||||
_closeButton = e.NameScope.Find<Button>(PART_CloseButton);
|
||||
Button.ClickEvent.AddHandler(OnDefaultButtonClick, _yesButton, _noButton, _okButton, _cancelButton);
|
||||
Button.ClickEvent.AddHandler(OnCloseButtonClick, _closeButton);
|
||||
SetButtonVisibility();
|
||||
}
|
||||
|
||||
private void SetButtonVisibility()
|
||||
{
|
||||
switch (_buttonConfigs)
|
||||
{
|
||||
case MessageBoxButton.OK:
|
||||
Button.IsVisibleProperty.SetValue(true, _okButton);
|
||||
Button.IsVisibleProperty.SetValue(false, _cancelButton, _yesButton, _noButton);
|
||||
break;
|
||||
case MessageBoxButton.OKCancel:
|
||||
Button.IsVisibleProperty.SetValue(true, _okButton, _cancelButton);
|
||||
Button.IsVisibleProperty.SetValue(false, _yesButton, _noButton);
|
||||
break;
|
||||
case MessageBoxButton.YesNo:
|
||||
Button.IsVisibleProperty.SetValue(false, _okButton, _cancelButton);
|
||||
Button.IsVisibleProperty.SetValue(true, _yesButton, _noButton);
|
||||
break;
|
||||
case MessageBoxButton.YesNoCancel:
|
||||
Button.IsVisibleProperty.SetValue(false, _okButton);
|
||||
Button.IsVisibleProperty.SetValue(true, _cancelButton, _yesButton, _noButton);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCloseButtonClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_buttonConfigs == MessageBoxButton.OK)
|
||||
{
|
||||
Close(MessageBoxResult.OK);
|
||||
}
|
||||
|
||||
Close(MessageBoxResult.Cancel);
|
||||
}
|
||||
|
||||
private void OnDefaultButtonClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender == _okButton)
|
||||
{
|
||||
Close(MessageBoxResult.OK);
|
||||
}
|
||||
else if (sender == _cancelButton)
|
||||
{
|
||||
Close(MessageBoxResult.Cancel);
|
||||
}
|
||||
else if (sender == _yesButton)
|
||||
{
|
||||
Close(MessageBoxResult.Yes);
|
||||
}
|
||||
else if (sender == _noButton)
|
||||
{
|
||||
Close(MessageBoxResult.No);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnKeyUp(KeyEventArgs e)
|
||||
{
|
||||
base.OnKeyUp(e);
|
||||
if (e.Key == Key.Escape && _buttonConfigs == MessageBoxButton.OK)
|
||||
{
|
||||
Close(MessageBoxResult.OK);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPointerPressed(PointerPressedEventArgs e)
|
||||
{
|
||||
BeginMoveDrag(e);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user