Fix a bunch of templating issues
This commit is contained in:
@@ -8,106 +8,138 @@ namespace Toolkit.UI.Controls.Avalonia;
|
||||
public class ContentBadge :
|
||||
ContentControl
|
||||
{
|
||||
public static readonly StyledProperty<string?> BadgePathProperty =
|
||||
AvaloniaProperty.Register<ContentBadge, string?>(nameof(BadgePath));
|
||||
|
||||
public static readonly StyledProperty<double> BadgeSizeProperty =
|
||||
AvaloniaProperty.Register<ContentBadge, double>(nameof(BadgeSize), 14);
|
||||
public static readonly StyledProperty<string> BadgePathProperty =
|
||||
AvaloniaProperty.Register<ContentBadge, string>(nameof(BadgePath));
|
||||
|
||||
public static readonly StyledProperty<ContentBadgePlacement> BadgePlacementProperty =
|
||||
AvaloniaProperty.Register<ContentBadge, ContentBadgePlacement>(nameof(BadgePlacement), ContentBadgePlacement.BottomRight);
|
||||
|
||||
public static readonly StyledProperty<double> BadgeSizeProperty =
|
||||
AvaloniaProperty.Register<ContentBadge, double>(nameof(BadgeSize), 14);
|
||||
|
||||
public static readonly StyledProperty<bool> IsBadgeVisibleProperty =
|
||||
AvaloniaProperty.Register<ContentBadge, bool>(nameof(IsBadgeVisible), true);
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
|
||||
if (change.Property == BadgePathProperty ||
|
||||
change.Property == BadgeSizeProperty ||
|
||||
change.Property == IsBadgeVisibleProperty)
|
||||
{
|
||||
UpdateBadge();
|
||||
}
|
||||
}
|
||||
|
||||
private ContentControl? badgeContent;
|
||||
|
||||
public string BadgePath
|
||||
{
|
||||
get => GetValue(BadgePathProperty);
|
||||
set => SetValue(BadgePathProperty, value);
|
||||
}
|
||||
|
||||
public ContentBadgePlacement BadgePlacement
|
||||
{
|
||||
get => GetValue(BadgePlacementProperty);
|
||||
set => SetValue(BadgePlacementProperty, value);
|
||||
}
|
||||
|
||||
public string? BadgePath
|
||||
{
|
||||
get => GetValue(BadgePathProperty);
|
||||
set => SetValue(BadgePathProperty, value);
|
||||
}
|
||||
|
||||
public double BadgeSize
|
||||
{
|
||||
get => GetValue(BadgeSizeProperty);
|
||||
set => SetValue(BadgeSizeProperty, value);
|
||||
}
|
||||
|
||||
public void UpdateClip()
|
||||
public bool IsBadgeVisible
|
||||
{
|
||||
if (Content is Control content &&
|
||||
badgeContent is not null &&
|
||||
BadgePath is { Length: > 0 } &&
|
||||
Geometry.Parse(BadgePath) is Geometry geometry)
|
||||
get => GetValue(IsBadgeVisibleProperty);
|
||||
set => SetValue(IsBadgeVisibleProperty, value);
|
||||
}
|
||||
|
||||
public void UpdateBadge()
|
||||
{
|
||||
if (Content is Control content && badgeContent is not null)
|
||||
{
|
||||
double backgroundWidth = DesiredSize.Width;
|
||||
double backgroundHeight = DesiredSize.Height;
|
||||
|
||||
double scaleX = BadgeSize / geometry.Bounds.Width;
|
||||
double scaleY = BadgeSize / geometry.Bounds.Height;
|
||||
|
||||
double adjustedStrokeWidth = Math.Min(scaleX, scaleY) * 8;
|
||||
|
||||
Geometry knockoutGeometry = geometry.GetWidenedGeometry(new Pen(new SolidColorBrush(Colors.Transparent), adjustedStrokeWidth));
|
||||
|
||||
TransformGroup transformGroup = new();
|
||||
transformGroup.Children.Add(new ScaleTransform(scaleX, scaleY));
|
||||
|
||||
double scaledWidth = knockoutGeometry.Bounds.Width * scaleX;
|
||||
double scaledHeight = knockoutGeometry.Bounds.Height * scaleY;
|
||||
|
||||
double offsetX = 0;
|
||||
double offsetY = 0;
|
||||
|
||||
switch (BadgePlacement)
|
||||
if (IsBadgeVisible &&
|
||||
BadgePath is { Length: > 0 } &&
|
||||
Geometry.Parse(BadgePath) is Geometry geometry)
|
||||
{
|
||||
case ContentBadgePlacement.TopLeft:
|
||||
offsetX = 0;
|
||||
offsetY = 0;
|
||||
break;
|
||||
case ContentBadgePlacement.TopRight:
|
||||
offsetX = backgroundWidth - scaledWidth;
|
||||
offsetY = 0;
|
||||
break;
|
||||
case ContentBadgePlacement.BottomLeft:
|
||||
offsetX = 0;
|
||||
offsetY = backgroundHeight - scaledHeight;
|
||||
break;
|
||||
case ContentBadgePlacement.BottomRight:
|
||||
offsetX = backgroundWidth - scaledWidth;
|
||||
offsetY = backgroundHeight - scaledHeight;
|
||||
break;
|
||||
double backgroundWidth = DesiredSize.Width;
|
||||
double backgroundHeight = DesiredSize.Height;
|
||||
|
||||
double badgeWidth = geometry.Bounds.Width;
|
||||
double badgeHeight = geometry.Bounds.Height;
|
||||
double scale = BadgeSize / Math.Max(badgeWidth, badgeHeight);
|
||||
|
||||
double scaleX = scale;
|
||||
double scaleY = scale;
|
||||
|
||||
double adjustedStrokeWidth = Math.Min(scaleX, scaleY) * 8;
|
||||
|
||||
Geometry knockoutGeometry = geometry.GetWidenedGeometry(new Pen(new SolidColorBrush(Colors.Transparent), adjustedStrokeWidth));
|
||||
|
||||
TransformGroup transformGroup = new();
|
||||
transformGroup.Children.Add(new ScaleTransform(scaleX, scaleY));
|
||||
|
||||
double scaledWidth = knockoutGeometry.Bounds.Width * scaleX;
|
||||
double scaledHeight = knockoutGeometry.Bounds.Height * scaleY;
|
||||
|
||||
double offsetX = 0;
|
||||
double offsetY = 0;
|
||||
|
||||
switch (BadgePlacement)
|
||||
{
|
||||
case ContentBadgePlacement.TopLeft:
|
||||
offsetX = 0;
|
||||
offsetY = 0;
|
||||
break;
|
||||
case ContentBadgePlacement.TopRight:
|
||||
offsetX = backgroundWidth - scaledWidth;
|
||||
offsetY = 0;
|
||||
break;
|
||||
case ContentBadgePlacement.BottomLeft:
|
||||
offsetX = 0;
|
||||
offsetY = backgroundHeight - scaledHeight;
|
||||
break;
|
||||
case ContentBadgePlacement.BottomRight:
|
||||
offsetX = backgroundWidth - scaledWidth;
|
||||
offsetY = backgroundHeight - scaledHeight;
|
||||
break;
|
||||
}
|
||||
|
||||
transformGroup.Children.Add(new TranslateTransform(offsetX, offsetY));
|
||||
knockoutGeometry.Transform = transformGroup;
|
||||
|
||||
CombinedGeometry combinedGeometry = new()
|
||||
{
|
||||
GeometryCombineMode = GeometryCombineMode.Exclude,
|
||||
Geometry1 = new RectangleGeometry { Rect = new Rect(0, 0, backgroundWidth, backgroundHeight) },
|
||||
Geometry2 = knockoutGeometry
|
||||
};
|
||||
|
||||
content.Clip = combinedGeometry;
|
||||
|
||||
Geometry overlayGeometry = geometry.Clone();
|
||||
|
||||
TransformGroup overlayTransformGroup = new();
|
||||
overlayTransformGroup.Children.Add(new ScaleTransform(scaleX, scaleY));
|
||||
|
||||
overlayTransformGroup.Children.Add(new TranslateTransform(offsetX, offsetY));
|
||||
overlayGeometry.Transform = overlayTransformGroup;
|
||||
|
||||
badgeContent.Content = new Path
|
||||
{
|
||||
Data = overlayGeometry,
|
||||
Fill = Foreground
|
||||
};
|
||||
}
|
||||
|
||||
transformGroup.Children.Add(new TranslateTransform(offsetX, offsetY));
|
||||
knockoutGeometry.Transform = transformGroup;
|
||||
|
||||
CombinedGeometry combinedGeometry = new()
|
||||
else
|
||||
{
|
||||
GeometryCombineMode = GeometryCombineMode.Exclude,
|
||||
Geometry1 = new RectangleGeometry { Rect = new Rect(0, 0, backgroundWidth, backgroundHeight) },
|
||||
Geometry2 = knockoutGeometry
|
||||
};
|
||||
|
||||
content.Clip = combinedGeometry;
|
||||
|
||||
Geometry overlayGeometry = geometry.Clone();
|
||||
|
||||
TransformGroup overlayTransformGroup = new();
|
||||
overlayTransformGroup.Children.Add(new ScaleTransform(scaleX, scaleY));
|
||||
|
||||
overlayTransformGroup.Children.Add(new TranslateTransform(offsetX, offsetY));
|
||||
overlayGeometry.Transform = overlayTransformGroup;
|
||||
|
||||
badgeContent.Content = new Path
|
||||
{
|
||||
Data = overlayGeometry,
|
||||
Fill = Foreground
|
||||
};
|
||||
badgeContent.Content = null;
|
||||
content.Clip = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +152,7 @@ public class ContentBadge :
|
||||
protected override void OnSizeChanged(SizeChangedEventArgs args)
|
||||
{
|
||||
base.OnSizeChanged(args);
|
||||
UpdateClip();
|
||||
UpdateBadge();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user