Added PersonPicture
This commit is contained in:
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Toolkit.UI.Controls.Avalonia;
|
||||||
|
|
||||||
|
public class BitmapIcon : FluentAvalonia.UI.Controls.BitmapIcon
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Toolkit.UI.Controls.Avalonia;
|
||||||
|
|
||||||
|
public class BitmapIconSource : FluentAvalonia.UI.Controls.BitmapIconSource
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Controls.Templates;
|
||||||
|
using Avalonia.LogicalTree;
|
||||||
|
using Avalonia.Metadata;
|
||||||
|
|
||||||
|
namespace Toolkit.UI.Controls.Avalonia;
|
||||||
|
|
||||||
|
public class ContentIcon : FluentAvalonia.UI.Controls.FAIconElement
|
||||||
|
{
|
||||||
|
public static readonly StyledProperty<object?> ContentProperty =
|
||||||
|
AvaloniaProperty.Register<ContentIcon, object?>("Content");
|
||||||
|
|
||||||
|
public static readonly StyledProperty<IDataTemplate?> ContentTemplateProperty =
|
||||||
|
AvaloniaProperty.Register<ContentIcon, IDataTemplate?>("ContentTemplate");
|
||||||
|
|
||||||
|
private ContentControl? content;
|
||||||
|
|
||||||
|
[Content]
|
||||||
|
public object? Content
|
||||||
|
{
|
||||||
|
get => GetValue(ContentProperty);
|
||||||
|
set => SetValue(ContentProperty, value);
|
||||||
|
}
|
||||||
|
public IDataTemplate? IconTemplate
|
||||||
|
{
|
||||||
|
get => GetValue(ContentTemplateProperty);
|
||||||
|
set => SetValue(ContentTemplateProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Size MeasureOverride(Size availableSize)
|
||||||
|
{
|
||||||
|
if (content == null)
|
||||||
|
{
|
||||||
|
CreateContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.MeasureOverride(availableSize);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs args)
|
||||||
|
{
|
||||||
|
if (VisualChildren.Count > 0)
|
||||||
|
{
|
||||||
|
((ILogical)VisualChildren[0]).NotifyAttachedToLogicalTree(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
base.OnAttachedToLogicalTree(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs args)
|
||||||
|
{
|
||||||
|
if (VisualChildren.Count > 0)
|
||||||
|
{
|
||||||
|
((ILogical)VisualChildren[0]).NotifyDetachedFromLogicalTree(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
base.OnDetachedFromLogicalTree(args);
|
||||||
|
}
|
||||||
|
private void CreateContent()
|
||||||
|
{
|
||||||
|
content = new ContentControl();
|
||||||
|
|
||||||
|
content.Bind(ContentControl.ContentProperty, this.GetBindingObservable(ContentProperty));
|
||||||
|
content.Bind(ContentControl.ContentTemplateProperty, this.GetBindingObservable(ContentTemplateProperty));
|
||||||
|
|
||||||
|
LogicalChildren.Add(content);
|
||||||
|
VisualChildren.Add(content);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Controls.Templates;
|
||||||
|
using Avalonia.Metadata;
|
||||||
|
|
||||||
|
namespace Toolkit.UI.Controls.Avalonia;
|
||||||
|
|
||||||
|
public class ContentIconSource : FluentAvalonia.UI.Controls.IconSource
|
||||||
|
{
|
||||||
|
public static readonly StyledProperty<object?> ContentProperty =
|
||||||
|
AvaloniaProperty.Register<ContentIconSource, object?>("Content");
|
||||||
|
|
||||||
|
public static readonly StyledProperty<IDataTemplate?> ContentTemplateProperty =
|
||||||
|
AvaloniaProperty.Register<ContentIconSource, IDataTemplate?>("ContentTemplate");
|
||||||
|
|
||||||
|
[Content]
|
||||||
|
public object? Content
|
||||||
|
{
|
||||||
|
get => GetValue(ContentProperty);
|
||||||
|
set => SetValue(ContentProperty, value);
|
||||||
|
}
|
||||||
|
public IDataTemplate? IconTemplate
|
||||||
|
{
|
||||||
|
get => GetValue(ContentTemplateProperty);
|
||||||
|
set => SetValue(ContentTemplateProperty, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Toolkit.UI.Controls.Avalonia;
|
||||||
|
|
||||||
|
public class FAIconElement : FluentAvalonia.UI.Controls.FAIconElement
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Toolkit.UI.Controls.Avalonia;
|
||||||
|
|
||||||
|
public class FAPathIcon : FluentAvalonia.UI.Controls.FAPathIcon
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Toolkit.UI.Controls.Avalonia;
|
||||||
|
|
||||||
|
public class FontIcon : FluentAvalonia.UI.Controls.FontIcon
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Kromek.UI.Avalonia.Controls
|
||||||
|
{
|
||||||
|
|
||||||
|
public class FontIconSource : FluentAvalonia.UI.Controls.FontIconSource
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace Toolkit.UI.Controls.Avalonia;
|
||||||
|
|
||||||
|
public class IconHelper
|
||||||
|
{
|
||||||
|
private static MethodInfo? invoker;
|
||||||
|
|
||||||
|
public static FluentAvalonia.UI.Controls.FAIconElement? CreateIconElement(FluentAvalonia.UI.Controls.IconSource source)
|
||||||
|
{
|
||||||
|
if (source is ContentIconSource contentIconSource)
|
||||||
|
{
|
||||||
|
ContentIcon contentIcon = new()
|
||||||
|
{
|
||||||
|
[!ContentIcon.ContentProperty] = contentIconSource[!ContentIconSource.ContentProperty],
|
||||||
|
[!ContentIcon.ContentTemplateProperty] = contentIconSource[!ContentIconSource.ContentTemplateProperty],
|
||||||
|
};
|
||||||
|
|
||||||
|
return contentIcon;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (invoker == null)
|
||||||
|
{
|
||||||
|
Type? iconHelpersType = Type.GetType("FluentAvalonia.UI.Controls.IconHelpers,FluentAvalonia");
|
||||||
|
if (iconHelpersType?.GetMethod("CreateFromUnknown", BindingFlags.Public | BindingFlags.Static) is MethodInfo createFromUnknown)
|
||||||
|
{
|
||||||
|
invoker = createFromUnknown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (FluentAvalonia.UI.Controls.FAIconElement?)invoker?.Invoke(null, new object[] { source });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Toolkit.UI.Controls.Avalonia;
|
||||||
|
|
||||||
|
public class ImageIcon : FluentAvalonia.UI.Controls.ImageIcon
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Toolkit.UI.Controls.Avalonia;
|
||||||
|
|
||||||
|
public class ImageIconSource : FluentAvalonia.UI.Controls.ImageIconSource
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using Avalonia.Controls.Templates;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.LogicalTree;
|
||||||
|
using Avalonia.Metadata;
|
||||||
|
using Avalonia;
|
||||||
|
|
||||||
|
namespace Toolkit.UI.Controls.Avalonia;
|
||||||
|
|
||||||
|
public class PathIconSource : FluentAvalonia.UI.Controls.PathIconSource
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Toolkit.UI.Controls.Avalonia;
|
||||||
|
|
||||||
|
public class SymbolIcon : FluentAvalonia.UI.Controls.SymbolIcon
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Toolkit.UI.Controls.Avalonia;
|
||||||
|
|
||||||
|
public class SymbolIconSource : FluentAvalonia.UI.Controls.SymbolIconSource
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
<ResourceDictionary
|
||||||
|
xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:controls="using:Toolkit.UI.Controls.Avalonia">
|
||||||
|
<x:Double x:Key="PersonPictureEllipseBadgeStrokeOpacity">1</x:Double>
|
||||||
|
<x:Double x:Key="PersonPictureEllipseBadgeImageSourceStrokeOpacity">1</x:Double>
|
||||||
|
<x:Double x:Key="PersonPictureEllipseStrokeThickness">1</x:Double>
|
||||||
|
<x:Double x:Key="PersonPictureEllipseBadgeStrokeThickness">2</x:Double>
|
||||||
|
<Thickness x:Key="PersonPictureBadgeGridMargin">0,-4,-4,0</Thickness>
|
||||||
|
<ControlTheme x:Key="{x:Type controls:PersonPicture}" TargetType="controls:PersonPicture">
|
||||||
|
<Setter Property="Foreground" Value="{DynamicResource PersonPictureForegroundThemeBrush}" />
|
||||||
|
<Setter Property="Width" Value="100" />
|
||||||
|
<Setter Property="Height" Value="100" />
|
||||||
|
<Setter Property="FontFamily" Value="{DynamicResource ContentControlThemeFontFamily}" />
|
||||||
|
<Setter Property="FontWeight" Value="350" />
|
||||||
|
<Setter Property="IsTabStop" Value="False" />
|
||||||
|
<Setter Property="Template">
|
||||||
|
<ControlTemplate>
|
||||||
|
<Grid x:Name="RootGrid">
|
||||||
|
<Ellipse
|
||||||
|
Width="{TemplateBinding Width}"
|
||||||
|
Height="{TemplateBinding Height}"
|
||||||
|
Fill="{DynamicResource PersonPictureEllipseFillThemeBrush}"
|
||||||
|
Stroke="{DynamicResource PersonPictureEllipseFillStrokeBrush}"
|
||||||
|
StrokeThickness="{DynamicResource PersonPictureEllipseStrokeThickness}" />
|
||||||
|
<TextBlock
|
||||||
|
x:Name="InitialsTextBlock"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
FontFamily="{TemplateBinding FontFamily}"
|
||||||
|
FontSize="40"
|
||||||
|
FontWeight="{TemplateBinding FontWeight}"
|
||||||
|
Foreground="{TemplateBinding Foreground}"
|
||||||
|
Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.ActualInitials}" />
|
||||||
|
<Ellipse
|
||||||
|
x:Name="PersonPictureEllipse"
|
||||||
|
Width="{TemplateBinding Width}"
|
||||||
|
Height="{TemplateBinding Height}"
|
||||||
|
FlowDirection="LeftToRight" />
|
||||||
|
<Grid
|
||||||
|
x:Name="BadgeGrid"
|
||||||
|
Margin="{DynamicResource PersonPictureBadgeGridMargin}"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
VerticalAlignment="Top"
|
||||||
|
IsVisible="False">
|
||||||
|
<Ellipse
|
||||||
|
x:Name="BadgingBackgroundEllipse"
|
||||||
|
Fill="{DynamicResource PersonPictureEllipseBadgeFillThemeBrush}"
|
||||||
|
Opacity="{DynamicResource PersonPictureEllipseBadgeStrokeOpacity}"
|
||||||
|
Stroke="{DynamicResource PersonPictureEllipseBadgeStrokeThemeBrush}"
|
||||||
|
StrokeThickness="{DynamicResource PersonPictureEllipseBadgeStrokeThickness}" />
|
||||||
|
<Ellipse
|
||||||
|
x:Name="BadgingEllipse"
|
||||||
|
FlowDirection="LeftToRight"
|
||||||
|
Opacity="0" />
|
||||||
|
<TextBlock
|
||||||
|
x:Name="BadgeNumberTextBlock"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
FontFamily="{TemplateBinding FontFamily}"
|
||||||
|
FontWeight="{TemplateBinding FontWeight}"
|
||||||
|
Foreground="{DynamicResource PersonPictureEllipseBadgeForegroundThemeBrush}" />
|
||||||
|
<controls:FontIcon
|
||||||
|
x:Name="BadgeGlyphIcon"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
FontFamily="{DynamicResource SymbolThemeFontFamily}"
|
||||||
|
FontWeight="{TemplateBinding FontWeight}"
|
||||||
|
Foreground="{DynamicResource PersonPictureEllipseBadgeForegroundThemeBrush}" />
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter>
|
||||||
|
</ControlTheme>
|
||||||
|
</ResourceDictionary>
|
||||||
@@ -0,0 +1,379 @@
|
|||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Controls.Primitives;
|
||||||
|
using Avalonia.Controls.Shapes;
|
||||||
|
using Avalonia.Media;
|
||||||
|
using Avalonia.Media.Imaging;
|
||||||
|
using Kromek.UI.Avalonia.Controls;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Toolkit.UI.Controls.Avalonia;
|
||||||
|
|
||||||
|
public class PersonPicture : TemplatedControl
|
||||||
|
{
|
||||||
|
public static readonly StyledProperty<string> BadgeGlyphProperty =
|
||||||
|
AvaloniaProperty.Register<PersonPicture, string>(nameof(BadgeGlyph));
|
||||||
|
|
||||||
|
public static readonly StyledProperty<IImage> BadgeImageSourceProperty =
|
||||||
|
AvaloniaProperty.Register<PersonPicture, IImage>(nameof(BadgeImageSource));
|
||||||
|
|
||||||
|
public static readonly StyledProperty<int> BadgeNumberProperty =
|
||||||
|
AvaloniaProperty.Register<PersonPicture, int>(nameof(BadgeNumber));
|
||||||
|
|
||||||
|
public static readonly StyledProperty<string> BadgeTextProperty =
|
||||||
|
AvaloniaProperty.Register<PersonPicture, string>(nameof(BadgeText));
|
||||||
|
|
||||||
|
public static readonly StyledProperty<string> DisplayNameProperty =
|
||||||
|
AvaloniaProperty.Register<PersonPicture, string>(nameof(DisplayName));
|
||||||
|
|
||||||
|
public static readonly StyledProperty<string> InitialsProperty =
|
||||||
|
AvaloniaProperty.Register<PersonPicture, string>(nameof(Initials));
|
||||||
|
|
||||||
|
public static readonly StyledProperty<bool> IsGroupProperty =
|
||||||
|
AvaloniaProperty.Register<PersonPicture, bool>(nameof(IsGroup));
|
||||||
|
|
||||||
|
public static readonly StyledProperty<IImage> ProfilePictureProperty =
|
||||||
|
AvaloniaProperty.Register<PersonPicture, IImage>(nameof(ProfilePicture));
|
||||||
|
|
||||||
|
private static readonly StyledProperty<PersonPictureTemplateSettings> TemplateSettingsProperty =
|
||||||
|
AvaloniaProperty.Register<PersonPicture, PersonPictureTemplateSettings>(nameof(TemplateSettings));
|
||||||
|
|
||||||
|
private FontIcon badgeGlyphIcon;
|
||||||
|
private ImageBrush badgeImageBrush;
|
||||||
|
private TextBlock badgeNumberTextBlock;
|
||||||
|
private Ellipse badgingBackgroundEllipse;
|
||||||
|
private Ellipse badgingEllipse;
|
||||||
|
private string displayNameInitials;
|
||||||
|
private TextBlock initialsTextBlock;
|
||||||
|
|
||||||
|
public PersonPicture()
|
||||||
|
{
|
||||||
|
SetValue(TemplateSettingsProperty, new PersonPictureTemplateSettings());
|
||||||
|
SizeChanged += OnSizeChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string BadgeGlyph
|
||||||
|
{
|
||||||
|
get => GetValue(BadgeGlyphProperty);
|
||||||
|
set => SetValue(BadgeGlyphProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IImage BadgeImageSource
|
||||||
|
{
|
||||||
|
get => GetValue(BadgeImageSourceProperty);
|
||||||
|
set => SetValue(BadgeImageSourceProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int BadgeNumber
|
||||||
|
{
|
||||||
|
get => GetValue(BadgeNumberProperty);
|
||||||
|
set => SetValue(BadgeNumberProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string BadgeText
|
||||||
|
{
|
||||||
|
get => GetValue(BadgeTextProperty);
|
||||||
|
set => SetValue(BadgeTextProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string DisplayName
|
||||||
|
{
|
||||||
|
get => GetValue(DisplayNameProperty);
|
||||||
|
set => SetValue(DisplayNameProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Initials
|
||||||
|
{
|
||||||
|
get => GetValue(InitialsProperty);
|
||||||
|
set => SetValue(InitialsProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsGroup
|
||||||
|
{
|
||||||
|
get => GetValue(IsGroupProperty);
|
||||||
|
set => SetValue(IsGroupProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IImage ProfilePicture
|
||||||
|
{
|
||||||
|
get => GetValue(ProfilePictureProperty);
|
||||||
|
set => SetValue(ProfilePictureProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersonPictureTemplateSettings TemplateSettings
|
||||||
|
{
|
||||||
|
get => GetValue(TemplateSettingsProperty);
|
||||||
|
set => SetValue(TemplateSettingsProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnApplyTemplate(TemplateAppliedEventArgs args)
|
||||||
|
{
|
||||||
|
base.OnApplyTemplate(args);
|
||||||
|
|
||||||
|
initialsTextBlock = args.NameScope.Get<TextBlock>("InitialsTextBlock");
|
||||||
|
|
||||||
|
badgeNumberTextBlock = args.NameScope.Get<TextBlock>("BadgeNumberTextBlock");
|
||||||
|
badgeGlyphIcon = args.NameScope.Get<FontIcon>("BadgeGlyphIcon");
|
||||||
|
badgingEllipse = args.NameScope.Get<Ellipse>("BadgingEllipse");
|
||||||
|
badgingBackgroundEllipse = args.NameScope.Get<Ellipse>("BadgingBackgroundEllipse");
|
||||||
|
|
||||||
|
UpdateBadge();
|
||||||
|
UpdateIfReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||||
|
{
|
||||||
|
base.OnPropertyChanged(change);
|
||||||
|
|
||||||
|
if (change.Property == BadgeGlyphProperty)
|
||||||
|
{
|
||||||
|
UpdateBadge();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (change.Property == BadgeImageSourceProperty)
|
||||||
|
{
|
||||||
|
UpdateBadge();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (change.Property == BadgeNumberProperty)
|
||||||
|
{
|
||||||
|
UpdateBadge();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (change.Property == DisplayNameProperty)
|
||||||
|
{
|
||||||
|
UpdateDisplayName();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (change.Property == InitialsProperty)
|
||||||
|
{
|
||||||
|
UpdateIfReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (change.Property == IsGroupProperty)
|
||||||
|
{
|
||||||
|
UpdateIfReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (change.Property == ProfilePictureProperty)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IImage? GetImageSource()
|
||||||
|
{
|
||||||
|
if (ProfilePicture != null)
|
||||||
|
{
|
||||||
|
return ProfilePicture;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetInitials()
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(Initials))
|
||||||
|
{
|
||||||
|
return Initials;
|
||||||
|
}
|
||||||
|
else if (!string.IsNullOrEmpty(displayNameInitials))
|
||||||
|
{
|
||||||
|
return displayNameInitials;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSizeChanged(object? sender, SizeChangedEventArgs args)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
bool widthChanged = args.NewSize.Width != args.PreviousSize.Width;
|
||||||
|
bool heightChanged = args.NewSize.Height != args.PreviousSize.Height;
|
||||||
|
double newSize;
|
||||||
|
|
||||||
|
if (widthChanged && heightChanged)
|
||||||
|
{
|
||||||
|
newSize = args.NewSize.Width < args.NewSize.Height ? args.NewSize.Width : args.NewSize.Height;
|
||||||
|
}
|
||||||
|
else if (widthChanged)
|
||||||
|
{
|
||||||
|
newSize = args.NewSize.Width;
|
||||||
|
}
|
||||||
|
else if (heightChanged)
|
||||||
|
{
|
||||||
|
newSize = args.NewSize.Height;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Height = newSize;
|
||||||
|
Width = newSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
double fontSize = Math.Max(1.0, Width * .42);
|
||||||
|
|
||||||
|
if (initialsTextBlock is not null)
|
||||||
|
{
|
||||||
|
initialsTextBlock.FontSize = fontSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (badgingEllipse is not null && badgingBackgroundEllipse is not null && badgeNumberTextBlock is not null && badgeGlyphIcon is not null)
|
||||||
|
{
|
||||||
|
double newSize = args.NewSize.Width < args.NewSize.Height ? args.NewSize.Width : args.NewSize.Height;
|
||||||
|
badgingEllipse.Height = newSize * 0.5;
|
||||||
|
badgingEllipse.Width = newSize * 0.5;
|
||||||
|
badgingBackgroundEllipse.Height = newSize * 0.5;
|
||||||
|
badgingBackgroundEllipse.Width = newSize * 0.5;
|
||||||
|
badgeNumberTextBlock.FontSize = Math.Max(1.0, badgingEllipse.Height * 0.6);
|
||||||
|
badgeGlyphIcon.FontSize = Math.Max(1.0, badgingEllipse.Height * 0.6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateBadge()
|
||||||
|
{
|
||||||
|
if (BadgeImageSource != null)
|
||||||
|
{
|
||||||
|
UpdateBadgeImageSource();
|
||||||
|
}
|
||||||
|
else if (BadgeNumber != 0)
|
||||||
|
{
|
||||||
|
UpdateBadgeNumber();
|
||||||
|
}
|
||||||
|
else if (!string.IsNullOrEmpty(BadgeGlyph))
|
||||||
|
{
|
||||||
|
UpdateBadgeGlyph();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PseudoClasses.Set(":NoBadge", true);
|
||||||
|
if (badgeNumberTextBlock != null)
|
||||||
|
{
|
||||||
|
badgeNumberTextBlock.Text = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (badgeGlyphIcon != null)
|
||||||
|
{
|
||||||
|
badgeGlyphIcon.Glyph = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateBadgeGlyph()
|
||||||
|
{
|
||||||
|
if (badgingEllipse == null || badgeGlyphIcon == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(BadgeGlyph))
|
||||||
|
{
|
||||||
|
PseudoClasses.Set(":NoBadge", true);
|
||||||
|
badgeGlyphIcon.Glyph = "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PseudoClasses.Set(":BadgeWithoutImageSource", true);
|
||||||
|
badgeGlyphIcon.Glyph = BadgeGlyph;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateBadgeImageSource()
|
||||||
|
{
|
||||||
|
if (badgingEllipse == null || badgeImageBrush == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
badgeImageBrush.Source = (Bitmap?)BadgeImageSource;
|
||||||
|
|
||||||
|
if (BadgeImageSource != null)
|
||||||
|
{
|
||||||
|
PseudoClasses.Set(":BadgeWithImageSource", true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PseudoClasses.Set(":NoBadge", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void UpdateBadgeNumber()
|
||||||
|
{
|
||||||
|
if (badgingEllipse == null || badgeNumberTextBlock == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BadgeNumber <= 0)
|
||||||
|
{
|
||||||
|
PseudoClasses.Set(":NoBadge", true);
|
||||||
|
badgeNumberTextBlock.Text = "";
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PseudoClasses.Set(":BadgeWithoutImageSource", true);
|
||||||
|
if (BadgeNumber <= 99)
|
||||||
|
{
|
||||||
|
badgeNumberTextBlock.Text = BadgeNumber.ToString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
badgeNumberTextBlock.Text = "99+";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void UpdateDisplayName()
|
||||||
|
{
|
||||||
|
displayNameInitials = PersonPictureInitialsGenerator.InitialsFromDisplayName(DisplayName);
|
||||||
|
UpdateIfReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateIfReady()
|
||||||
|
{
|
||||||
|
string initials = GetInitials();
|
||||||
|
IImage? imageSource = GetImageSource();
|
||||||
|
|
||||||
|
PersonPictureTemplateSettings templateSettings = TemplateSettings;
|
||||||
|
templateSettings.ActualInitials = initials;
|
||||||
|
|
||||||
|
if (imageSource is not null)
|
||||||
|
{
|
||||||
|
ImageBrush? imageBrush = templateSettings.ActualImageBrush;
|
||||||
|
if (imageBrush == null)
|
||||||
|
{
|
||||||
|
imageBrush = new ImageBrush
|
||||||
|
{
|
||||||
|
Stretch = Stretch.UniformToFill
|
||||||
|
};
|
||||||
|
|
||||||
|
templateSettings.ActualImageBrush = imageBrush;
|
||||||
|
}
|
||||||
|
|
||||||
|
imageBrush.Source = (Bitmap?)imageSource;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
templateSettings.ActualImageBrush = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsGroup)
|
||||||
|
{
|
||||||
|
PseudoClasses.Set(":Group", true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (imageSource != null)
|
||||||
|
{
|
||||||
|
PseudoClasses.Set(":Photo", true);
|
||||||
|
}
|
||||||
|
else if (!string.IsNullOrEmpty(initials))
|
||||||
|
{
|
||||||
|
PseudoClasses.Set(":Initials", true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PseudoClasses.Set(":NoPhotoOrInitials", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace Toolkit.UI.Controls.Avalonia;
|
||||||
|
|
||||||
|
internal enum PersonPictureCharacterType
|
||||||
|
{
|
||||||
|
Other = 0,
|
||||||
|
Standard = 1,
|
||||||
|
Symbolic = 2,
|
||||||
|
Glyph = 3
|
||||||
|
}
|
||||||
@@ -0,0 +1,413 @@
|
|||||||
|
namespace Toolkit.UI.Controls.Avalonia;
|
||||||
|
|
||||||
|
internal class PersonPictureInitialsGenerator
|
||||||
|
{
|
||||||
|
public static PersonPictureCharacterType GetCharacterType(string str)
|
||||||
|
{
|
||||||
|
|
||||||
|
PersonPictureCharacterType result = PersonPictureCharacterType.Other;
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
if ((i >= str.Length) || (str[i] == '\0') || (str[i] == 0xFEFF))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
char character = str[i];
|
||||||
|
PersonPictureCharacterType evaluationResult = GetCharacterType(character);
|
||||||
|
|
||||||
|
switch (evaluationResult)
|
||||||
|
{
|
||||||
|
case PersonPictureCharacterType.Glyph:
|
||||||
|
result = PersonPictureCharacterType.Glyph;
|
||||||
|
break;
|
||||||
|
case PersonPictureCharacterType.Symbolic:
|
||||||
|
if (result != PersonPictureCharacterType.Glyph)
|
||||||
|
{
|
||||||
|
result = PersonPictureCharacterType.Symbolic;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PersonPictureCharacterType.Standard:
|
||||||
|
if ((result != PersonPictureCharacterType.Glyph) && (result != PersonPictureCharacterType.Symbolic))
|
||||||
|
{
|
||||||
|
result = PersonPictureCharacterType.Standard;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PersonPictureCharacterType GetCharacterType(char character)
|
||||||
|
{
|
||||||
|
|
||||||
|
// IPA Extensions
|
||||||
|
if ((character >= 0x0250) && (character <= 0x02AF))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Glyph;
|
||||||
|
}
|
||||||
|
// Arabic
|
||||||
|
if ((character >= 0x0600) && (character <= 0x06FF))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Glyph;
|
||||||
|
}
|
||||||
|
// Arabic Supplement
|
||||||
|
if ((character >= 0x0750) && (character <= 0x077F))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Glyph;
|
||||||
|
}
|
||||||
|
// Arabic Extended-A
|
||||||
|
if ((character >= 0x08A0) && (character <= 0x08FF))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Glyph;
|
||||||
|
}
|
||||||
|
// Arabic Presentation Forms-A
|
||||||
|
if ((character >= 0xFB50) && (character <= 0xFDFF))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Glyph;
|
||||||
|
}
|
||||||
|
// Arabic Presentation Forms-B
|
||||||
|
if ((character >= 0xFE70) && (character <= 0xFEFF))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Glyph;
|
||||||
|
}
|
||||||
|
// Devanagari
|
||||||
|
if ((character >= 0x0900) && (character <= 0x097F))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Glyph;
|
||||||
|
}
|
||||||
|
// Devanagari Extended
|
||||||
|
if ((character >= 0xA8E0) && (character <= 0xA8FF))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Glyph;
|
||||||
|
}
|
||||||
|
// Bengali
|
||||||
|
if ((character >= 0x0980) && (character <= 0x09FF))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Glyph;
|
||||||
|
}
|
||||||
|
// Gurmukhi
|
||||||
|
if ((character >= 0x0A00) && (character <= 0x0A7F))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Glyph;
|
||||||
|
}
|
||||||
|
// Gujarati
|
||||||
|
if ((character >= 0x0A80) && (character <= 0x0AFF))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Glyph;
|
||||||
|
}
|
||||||
|
// Oriya
|
||||||
|
if ((character >= 0x0B00) && (character <= 0x0B7F))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Glyph;
|
||||||
|
}
|
||||||
|
// Tamil
|
||||||
|
if ((character >= 0x0B80) && (character <= 0x0BFF))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Glyph;
|
||||||
|
}
|
||||||
|
// Telugu
|
||||||
|
if ((character >= 0x0C00) && (character <= 0x0C7F))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Glyph;
|
||||||
|
}
|
||||||
|
// Kannada
|
||||||
|
if ((character >= 0x0C80) && (character <= 0x0CFF))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Glyph;
|
||||||
|
}
|
||||||
|
// Malayalam
|
||||||
|
if ((character >= 0x0D00) && (character <= 0x0D7F))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Glyph;
|
||||||
|
}
|
||||||
|
// Sinhala
|
||||||
|
if ((character >= 0x0D80) && (character <= 0x0DFF))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Glyph;
|
||||||
|
}
|
||||||
|
// Thai
|
||||||
|
if ((character >= 0x0E00) && (character <= 0x0E7F))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Glyph;
|
||||||
|
}
|
||||||
|
// Lao
|
||||||
|
if ((character >= 0x0E80) && (character <= 0x0EFF))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Glyph;
|
||||||
|
}
|
||||||
|
// SYMBOLIC
|
||||||
|
//
|
||||||
|
// CJK Unified Ideographs
|
||||||
|
if ((character >= 0x4E00) && (character <= 0x9FFF))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Symbolic;
|
||||||
|
}
|
||||||
|
// CJK Unified Ideographs Extension
|
||||||
|
if ((character >= 0x3400) && (character <= 0x4DBF))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Symbolic;
|
||||||
|
}
|
||||||
|
// CJK Unified Ideographs Extension B
|
||||||
|
if ((character >= 0x20000) && (character <= 0x2A6DF))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Symbolic;
|
||||||
|
}
|
||||||
|
// CJK Unified Ideographs Extension C
|
||||||
|
if ((character >= 0x2A700) && (character <= 0x2B73F))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Symbolic;
|
||||||
|
}
|
||||||
|
// CJK Unified Ideographs Extension D
|
||||||
|
if ((character >= 0x2B740) && (character <= 0x2B81F))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Symbolic;
|
||||||
|
}
|
||||||
|
// CJK Radicals Supplement
|
||||||
|
if ((character >= 0x2E80) && (character <= 0x2EFF))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Symbolic;
|
||||||
|
}
|
||||||
|
// CJK Symbols and Punctuation
|
||||||
|
if ((character >= 0x3000) && (character <= 0x303F))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Symbolic;
|
||||||
|
}
|
||||||
|
// CJK Strokes
|
||||||
|
if ((character >= 0x31C0) && (character <= 0x31EF))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Symbolic;
|
||||||
|
}
|
||||||
|
// Enclosed CJK Letters and Months
|
||||||
|
if ((character >= 0x3200) && (character <= 0x32FF))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Symbolic;
|
||||||
|
}
|
||||||
|
// CJK Compatibility
|
||||||
|
if ((character >= 0x3300) && (character <= 0x33FF))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Symbolic;
|
||||||
|
}
|
||||||
|
// CJK Compatibility Ideographs
|
||||||
|
if ((character >= 0xF900) && (character <= 0xFAFF))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Symbolic;
|
||||||
|
}
|
||||||
|
// CJK Compatibility Forms
|
||||||
|
if ((character >= 0xFE30) && (character <= 0xFE4F))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Symbolic;
|
||||||
|
}
|
||||||
|
// CJK Compatibility Ideographs Supplement
|
||||||
|
if ((character >= 0x2F800) && (character <= 0x2FA1F))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Symbolic;
|
||||||
|
}
|
||||||
|
// Greek and Coptic
|
||||||
|
if ((character >= 0x0370) && (character <= 0x03FF))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Symbolic;
|
||||||
|
}
|
||||||
|
// Hebrew
|
||||||
|
if ((character >= 0x0590) && (character <= 0x05FF))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Symbolic;
|
||||||
|
}
|
||||||
|
// Armenian
|
||||||
|
if ((character >= 0x0530) && (character <= 0x058F))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Symbolic;
|
||||||
|
}
|
||||||
|
// LATIN
|
||||||
|
//
|
||||||
|
// Basic Latin
|
||||||
|
if ((character > 0x0000) && (character <= 0x007F))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Standard;
|
||||||
|
}
|
||||||
|
// Latin-1 Supplement
|
||||||
|
if ((character >= 0x0080) && (character <= 0x00FF))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Standard;
|
||||||
|
}
|
||||||
|
// Latin Extended-A
|
||||||
|
if ((character >= 0x0100) && (character <= 0x017F))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Standard;
|
||||||
|
}
|
||||||
|
// Latin Extended-B
|
||||||
|
if ((character >= 0x0180) && (character <= 0x024F))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Standard;
|
||||||
|
}
|
||||||
|
// Latin Extended-C
|
||||||
|
if ((character >= 0x2C60) && (character <= 0x2C7F))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Standard;
|
||||||
|
}
|
||||||
|
// Latin Extended-D
|
||||||
|
if ((character >= 0xA720) && (character <= 0xA7FF))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Standard;
|
||||||
|
}
|
||||||
|
// Latin Extended-E
|
||||||
|
if ((character >= 0xAB30) && (character <= 0xAB6F))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Standard;
|
||||||
|
}
|
||||||
|
// Latin Extended Additional
|
||||||
|
if ((character >= 0x1E00) && (character <= 0x1EFF))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Standard;
|
||||||
|
}
|
||||||
|
// Cyrillic
|
||||||
|
if ((character >= 0x0400) && (character <= 0x04FF))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Standard;
|
||||||
|
}
|
||||||
|
// Cyrillic Supplement
|
||||||
|
if ((character >= 0x0500) && (character <= 0x052F))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Standard;
|
||||||
|
}
|
||||||
|
// Combining Diacritical Marks
|
||||||
|
if ((character >= 0x0300) && (character <= 0x036F))
|
||||||
|
{
|
||||||
|
return PersonPictureCharacterType.Standard;
|
||||||
|
}
|
||||||
|
return PersonPictureCharacterType.Other;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string InitialsFromDisplayName(string contactDisplayName)
|
||||||
|
{
|
||||||
|
PersonPictureCharacterType type = GetCharacterType(contactDisplayName);
|
||||||
|
if (type == PersonPictureCharacterType.Standard)
|
||||||
|
{
|
||||||
|
string displayName = contactDisplayName;
|
||||||
|
StripTrailingBrackets(ref displayName);
|
||||||
|
string[] words = Split(displayName, ' ');
|
||||||
|
|
||||||
|
if (words.Length == 1)
|
||||||
|
{
|
||||||
|
string firstWord = words.First();
|
||||||
|
string result = GetFirstFullCharacter(firstWord);
|
||||||
|
|
||||||
|
return result.ToUpper();
|
||||||
|
}
|
||||||
|
else if (words.Length > 1)
|
||||||
|
{
|
||||||
|
string firstWord = words.First();
|
||||||
|
string lastWord = words.Last();
|
||||||
|
string result = GetFirstFullCharacter(firstWord);
|
||||||
|
result += GetFirstFullCharacter(lastWord);
|
||||||
|
|
||||||
|
return result.ToUpper();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static string GetFirstFullCharacter(string str)
|
||||||
|
{
|
||||||
|
int start = 0;
|
||||||
|
while (start < str.Length)
|
||||||
|
{
|
||||||
|
char character = str[start];
|
||||||
|
// Omit ! " # $ % & ' ( ) * + , - . /
|
||||||
|
if ((character >= 0x0021) && (character <= 0x002F))
|
||||||
|
{
|
||||||
|
start++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Omit : ; < = > ? @
|
||||||
|
if ((character >= 0x003A) && (character <= 0x0040))
|
||||||
|
{
|
||||||
|
start++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Omit { | } ~
|
||||||
|
if ((character >= 0x007B) && (character <= 0x007E))
|
||||||
|
{
|
||||||
|
start++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start >= str.Length)
|
||||||
|
{
|
||||||
|
start = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = start + 1;
|
||||||
|
while (index < str.Length)
|
||||||
|
{
|
||||||
|
char character = str[index];
|
||||||
|
|
||||||
|
if ((character < 0x0300) || (character > 0x036F))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int strLength = index - start;
|
||||||
|
return SafeSubstring(str, start, strLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string SafeSubstring(string value, int startIndex, int length)
|
||||||
|
{
|
||||||
|
if (value is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startIndex > value.Length)
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length > value.Length - startIndex)
|
||||||
|
{
|
||||||
|
length = value.Length - startIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value.Substring(startIndex, length);
|
||||||
|
}
|
||||||
|
private static string[] Split(string source, char delim, int maxIterations = 25)
|
||||||
|
{
|
||||||
|
return source.Split(new[] { delim }, maxIterations);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void StripTrailingBrackets(ref string source)
|
||||||
|
{
|
||||||
|
string[] delimiters = { "{}", "()", "[]" };
|
||||||
|
if (source.Length == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
foreach (var delimiter in delimiters)
|
||||||
|
{
|
||||||
|
if (source[source.Length - 1] != delimiter[1])
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var start = source.LastIndexOf(delimiter[0]);
|
||||||
|
if (start == -1)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
source = source.Remove(start);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Media;
|
||||||
|
|
||||||
|
namespace Toolkit.UI.Controls.Avalonia;
|
||||||
|
|
||||||
|
public class PersonPictureTemplateSettings : AvaloniaObject
|
||||||
|
{
|
||||||
|
private static readonly StyledProperty<ImageBrush?> ActualImageBrushProperty =
|
||||||
|
AvaloniaProperty.Register<PersonPictureTemplateSettings, ImageBrush?>(nameof(ActualImageBrush));
|
||||||
|
|
||||||
|
|
||||||
|
private static readonly StyledProperty<string> ActualInitialsProperty =
|
||||||
|
AvaloniaProperty.Register<PersonPictureTemplateSettings, string>(nameof(ActualInitials));
|
||||||
|
|
||||||
|
public ImageBrush? ActualImageBrush
|
||||||
|
{
|
||||||
|
get => GetValue(ActualImageBrushProperty);
|
||||||
|
set => SetValue(ActualImageBrushProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ActualInitials
|
||||||
|
{
|
||||||
|
get => GetValue(ActualInitialsProperty);
|
||||||
|
set => SetValue(ActualInitialsProperty, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user