diff --git a/AntdWpf/AntdWpf.csproj b/AntdWpf/AntdWpf.csproj
index 0777f59..77fe687 100644
--- a/AntdWpf/AntdWpf.csproj
+++ b/AntdWpf/AntdWpf.csproj
@@ -3,6 +3,7 @@
net462
Library
true
+
13.0
true
False
diff --git a/AntdWpf/Controls/Alert.cs b/AntdWpf/Controls/Alert.cs
index d8de09d..ac514d1 100644
--- a/AntdWpf/Controls/Alert.cs
+++ b/AntdWpf/Controls/Alert.cs
@@ -1,17 +1,16 @@
-namespace AntdWpf.Controls
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+using System.Windows.Markup;
+using System.Windows.Media;
+namespace AntdWpf.Controls
{
- using System.Windows;
- using System.Windows.Controls.Primitives;
- using System.Windows.Markup;
- using System.Windows.Media;
- using ControlBase = System.Windows.Controls.Control;
-
///
/// Alert component for feedback.
///
[ContentProperty("Message")]
[TemplatePart(Name = PART_Close, Type = typeof(ButtonBase))]
- public class Alert : ControlBase
+ public class Alert : Control
{
#region Fields
diff --git a/AntdWpf/Controls/AntButton.cs b/AntdWpf/Controls/AntButton.cs
new file mode 100644
index 0000000..c8635cd
--- /dev/null
+++ b/AntdWpf/Controls/AntButton.cs
@@ -0,0 +1,339 @@
+using System;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+using System.Windows.Shapes;
+
+namespace AntdWpf.Controls;
+
+///
+/// To trigger an operation.
+///
+[TemplatePart(Name = PART_Border, Type = typeof(FrameworkElement))]
+[TemplateVisualState(Name = "Loaded", GroupName = "LoadStates")]
+[TemplateVisualState(Name = "Unloaded", GroupName = "LoadStates")]
+public class AntButton : Button
+{
+ #region Fields
+
+ private const string PART_Border = "PART_Border";
+
+ private FrameworkElement border;
+
+ private VisualState mouseOverState;
+
+ private VisualState pressedState;
+
+ private VisualState focusedState;
+
+ #endregion
+
+ #region Properties
+
+ public static readonly DependencyProperty GhostProperty =
+ DependencyProperty.Register("Ghost", typeof(bool), typeof(AntButton), new PropertyMetadata(false, OnEffectBrushChanged));
+
+ ///
+ /// Gets/sets whether to make the background transparent and invert text and border colors.
+ ///
+ public bool Ghost
+ {
+ get { return (bool)GetValue(GhostProperty); }
+ set { SetValue(GhostProperty, value); }
+ }
+
+ public static readonly DependencyProperty IconProperty =
+ DependencyProperty.Register("Icon", typeof(string), typeof(AntButton), new PropertyMetadata(null));
+
+ ///
+ /// Gets/sets the icon type of the button.
+ ///
+ public string Icon
+ {
+ get { return (string)GetValue(IconProperty); }
+ set { SetValue(IconProperty, value); }
+ }
+
+ public static readonly DependencyProperty LoadingProperty =
+ DependencyProperty.Register("Loading", typeof(bool), typeof(AntButton), new PropertyMetadata(false, OnLoadingChanged));
+
+ ///
+ /// Gets/sets the loading state of the button.
+ ///
+ public bool Loading
+ {
+ get { return (bool)GetValue(LoadingProperty); }
+ set { SetValue(LoadingProperty, value); }
+ }
+
+ private static void OnLoadingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ (d as AntButton).SetLoadVisualState();
+ }
+
+ private void SetLoadVisualState()
+ {
+ VisualStateManager.GoToState(this, (Loading ? "Loaded" : "Unloaded"), true);
+ }
+
+
+ public static readonly DependencyProperty ShapeProperty =
+ DependencyProperty.Register("Shape", typeof(Shapes), typeof(AntButton), new PropertyMetadata(Shapes.Square));
+
+ ///
+ /// Gets/sets the shape of button.
+ ///
+ public Shapes Shape
+ {
+ get { return (Shapes)GetValue(ShapeProperty); }
+ set { SetValue(ShapeProperty, value); }
+ }
+
+ public static readonly DependencyProperty SizeProperty =
+ DependencyProperty.Register("Size", typeof(Sizes?), typeof(AntButton), new PropertyMetadata(null));
+
+ ///
+ /// Gets/sets the size of the button.
+ ///
+ public Sizes? Size
+ {
+ get { return (Sizes?)GetValue(SizeProperty); }
+ set { SetValue(SizeProperty, value); }
+ }
+
+ public static readonly DependencyProperty TypeProperty =
+ DependencyProperty.Register("Type", typeof(ButtonType?), typeof(AntButton), new PropertyMetadata(null));
+
+ ///
+ /// Gets/sets the type of the button.
+ ///
+ public ButtonType? Type
+ {
+ get { return (ButtonType?)GetValue(TypeProperty); }
+ set { SetValue(TypeProperty, value); }
+ }
+
+ public static readonly DependencyProperty EffectBrushProperty = DependencyProperty.Register(
+ "EffectBrush",
+ typeof(Brush),
+ typeof(AntButton),
+ new FrameworkPropertyMetadata(
+ Brushes.Transparent,
+ FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.Inherits,
+ OnEffectBrushChanged));
+
+ ///
+ /// Gets/sets the border effect brush of the button.
+ ///
+ public Brush EffectBrush
+ {
+ get { return (Brush)GetValue(EffectBrushProperty); }
+ set { SetValue(EffectBrushProperty, value); }
+ }
+
+ private static void OnEffectBrushChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ (d as AntButton).SetVisualStateAnimation();
+ }
+
+ ///
+ /// Force background transparent in Ghost state.
+ ///
+ private static object OnBackgroundCoerceValue(DependencyObject d, object baseValue)
+ {
+ var button = d as AntButton;
+
+ if (button.Ghost)
+ {
+ return Brushes.Transparent;
+ }
+
+ return baseValue;
+ }
+
+ #endregion
+
+ #region Constructors
+
+ static AntButton()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(AntButton), new FrameworkPropertyMetadata(typeof(AntButton)));
+ BackgroundProperty.OverrideMetadata(typeof(AntButton), new FrameworkPropertyMetadata { CoerceValueCallback = OnBackgroundCoerceValue });
+ }
+
+ #endregion
+
+ #region Overrides
+
+ public override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ border = GetTemplateChild(PART_Border) as FrameworkElement;
+ mouseOverState = GetTemplateChild("MouseOver") as VisualState;
+
+ focusedState = GetTemplateChild("Focused") as VisualState;
+ pressedState = GetTemplateChild("Pressed") as VisualState;
+
+ SetVisualStateAnimation();
+ SetLoadVisualState();
+ }
+
+ #endregion
+
+ #region Private Methods
+
+ private void SetVisualStateAnimation()
+ {
+ // No initialization or no need for me to handle.
+ if (border == null || mouseOverState == null && focusedState == null && pressedState == null) return;
+
+ // Unable to extract color.
+ if (EffectBrush is SolidColorBrush brush)
+ {
+ var isShape = border is Shape;
+ Func func;
+
+ if (!Type.HasValue || Type.Value == ButtonType.Dashed)
+ {
+ func = CreateDefaultStoryboard;
+ }
+ else if (Type.Value == ButtonType.Primary)
+ {
+ func = CreatePrimaryStoryboard;
+ }
+ else
+ {
+ // Danger
+ func = CreateDangerStoryboard;
+ }
+
+ if (mouseOverState != null)
+ {
+ mouseOverState.Storyboard = func(this, brush.Color, 5, isShape, false, null);
+ }
+
+ if (focusedState != null)
+ {
+ focusedState.Storyboard = func(this, brush.Color, 5, isShape, true, null);
+ }
+
+ if (pressedState != null)
+ {
+ pressedState.Storyboard = func(this, brush.Color, 7, isShape, false, TimeSpan.FromSeconds(0));
+ }
+ }
+ }
+
+ private static Storyboard CreateDefaultStoryboard(AntButton button, Color color, int index, bool IsShape, bool focused, Duration? duration = null)
+ {
+ var storyboard = new Storyboard();
+ var children = storyboard.Children;
+
+ color = ColorPalette.Toning(color, index);
+ children.Add(CreateForegroundAnimation(button, color, duration));
+ children.Add(CreateBorderAnimation(PART_Border, color, IsShape, duration));
+
+ return storyboard;
+ }
+
+ private static Storyboard CreatePrimaryStoryboard(AntButton button, Color color, int index, bool IsShape, bool focused, Duration? duration = null)
+ {
+ var storyboard = new Storyboard();
+ var children = storyboard.Children;
+
+ color = ColorPalette.Toning(color, index);
+
+ if (button.Ghost)
+ {
+ children.Add(CreateForegroundAnimation(button, color, duration));
+ } else
+ {
+ children.Add(CreateBackgroundAnimation(PART_Border, color, IsShape, duration));
+ }
+
+ children.Add(CreateBorderAnimation(PART_Border, color, IsShape, duration));
+
+ return storyboard;
+ }
+
+ private static Storyboard CreateDangerStoryboard(AntButton button, Color color, int index, bool IsShape, bool focused, Duration? duration = null)
+ {
+ var storyboard = new Storyboard();
+ var children = storyboard.Children;
+
+ Color foreground;
+ color = ColorPalette.Toning(color, index);
+
+ if (button.Ghost)
+ {
+ foreground = color;
+ } else
+ {
+ Color background;
+
+ if (focused)
+ {
+ foreground = color;
+ background = Colors.White;
+ }
+ else
+ {
+ foreground = Colors.White;
+ background = color;
+ }
+
+ children.Add(CreateBackgroundAnimation(PART_Border, background, IsShape, duration));
+ }
+
+ children.Add(CreateForegroundAnimation(button, foreground, duration));
+ children.Add(CreateBorderAnimation(PART_Border, color, IsShape, duration));
+
+ return storyboard;
+ }
+
+ private static Timeline CreateForegroundAnimation(DependencyObject target, Color color, Duration? duration = null)
+ {
+ return CreateColorAnimation(target, "(Control.Foreground).(SolidColorBrush.Color)", color, duration);
+ }
+
+ private static Timeline CreateBackgroundAnimation(string target, Color color, bool IsShape, Duration? duration = null)
+ {
+ return CreateColorAnimation(target, (IsShape ? "Fill" : "Background") + ".Color", color, duration);
+ }
+
+ private static Timeline CreateBorderAnimation(string target, Color color, bool IsShape, Duration? duration = null)
+ {
+ return CreateColorAnimation(target, (IsShape ? "Stroke" : "BorderBrush") + ".Color", color, duration);
+ }
+
+ private static Timeline CreateColorAnimation(object target, string path, Color color, Duration? duration)
+ {
+ var animation = new ColorAnimation() { To = color };
+
+ if (duration.HasValue)
+ {
+ animation.Duration = duration.Value;
+ }
+
+ if (target is DependencyObject)
+ {
+ Storyboard.SetTarget(animation, (DependencyObject)target);
+ } else
+ {
+ Storyboard.SetTargetName(animation, (string)target);
+ }
+
+ Storyboard.SetTargetProperty(animation, new PropertyPath(path));
+
+ return animation;
+ }
+
+ #endregion
+}
+
+public enum ButtonType : byte
+{
+ Primary, Dashed, Danger
+}
diff --git a/AntdWpf/Controls/AntIcon.cs b/AntdWpf/Controls/AntIcon.cs
index 5045076..f7380ea 100644
--- a/AntdWpf/Controls/AntIcon.cs
+++ b/AntdWpf/Controls/AntIcon.cs
@@ -7,6 +7,9 @@ using System.Windows.Media;
namespace AntdWpf.Controls
{
+ ///
+ /// 图标控件
+ ///
public class AntIcon : System.Windows.Controls.Control
{
private static readonly Lazy> _dataList
diff --git a/AntdWpf/Controls/AntdBorder.cs b/AntdWpf/Controls/AntdBorder.cs
new file mode 100644
index 0000000..a6f33e7
--- /dev/null
+++ b/AntdWpf/Controls/AntdBorder.cs
@@ -0,0 +1,749 @@
+using System;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+
+using AntdWpf.Utils;
+
+namespace AntdWpf.Controls;
+
+///
+/// Draws a border, background, or both around another element.
+///
+public class AntdBorder : Decorator
+{
+ #region Fields
+
+ private StreamGeometry backgroundGeometryCache;
+
+ private StreamGeometry upperLeftCache;
+
+ private StreamGeometry upperRightCache;
+
+ private StreamGeometry lowerRightCache;
+
+ private StreamGeometry lowerLeftCache;
+
+ private bool useComplexRender;
+
+ private Pen leftPenCache;
+
+ private Pen topPenCache;
+
+ private Pen rightPenCache;
+
+ private Pen bottomPenCache;
+
+ #endregion
+
+ #region Properties
+
+ public static readonly DependencyProperty BackgroundProperty = DependencyProperty.Register(
+ "Background",
+ typeof(Brush),
+ typeof(AntdBorder),
+ new FrameworkPropertyMetadata(
+ null,
+ FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.SubPropertiesDoNotAffectRender
+ ));
+
+ ///
+ /// Gets or sets the brush that fills the area between the bounds of a Border.
+ ///
+ public Brush Background
+ {
+ get { return (Brush)GetValue(BackgroundProperty); }
+ set { SetValue(BackgroundProperty, value); }
+ }
+
+ public static readonly DependencyProperty BorderBrushProperty = DependencyProperty.Register(
+ "BorderBrush",
+ typeof(Brush),
+ typeof(AntdBorder),
+ new FrameworkPropertyMetadata(
+ null,
+ FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.SubPropertiesDoNotAffectRender,
+ OnClearPenCache
+ ));
+
+ ///
+ /// Gets or sets the brush that draws the outer border color.
+ ///
+ public Brush BorderBrush
+ {
+ get { return (Brush)GetValue(BorderBrushProperty); }
+ set { SetValue(BorderBrushProperty, value); }
+ }
+
+ public static readonly DependencyProperty BorderThicknessProperty = DependencyProperty.Register(
+ "BorderThickness",
+ typeof(Thickness),
+ typeof(AntdBorder),
+ new FrameworkPropertyMetadata(
+ new Thickness(),
+ FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender,
+ OnClearPenCache
+ ),
+ IsThicknessValid);
+
+ ///
+ /// Gets or sets the relative thickness of a border.
+ ///
+ public Thickness BorderThickness
+ {
+ get { return (Thickness)GetValue(BorderThicknessProperty); }
+ set { SetValue(BorderThicknessProperty, value); }
+ }
+
+ private static void OnClearPenCache(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var border = (AntdBorder)d;
+ border.leftPenCache = border.topPenCache = border.rightPenCache = border.bottomPenCache = null;
+ }
+
+ private static bool IsThicknessValid(object value)
+ {
+ return ThicknessUtil.IsValid((Thickness)value, false, false, false, false);
+ }
+
+ public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.Register(
+ "CornerRadius",
+ typeof(CornerRadius),
+ typeof(AntdBorder),
+ new FrameworkPropertyMetadata(
+ new CornerRadius(),
+ FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender
+ ),
+ IsCornerRadiusValid);
+
+ ///
+ /// Gets or sets a value that represents the degree to which the corners of a Border are rounded.
+ ///
+ public CornerRadius CornerRadius
+ {
+ get { return (CornerRadius)GetValue(CornerRadiusProperty); }
+ set { SetValue(CornerRadiusProperty, value); }
+ }
+
+ private static bool IsCornerRadiusValid(object value)
+ {
+ return CornerRadiusUtil.IsValid((CornerRadius)value, false, false, false, false);
+ }
+
+ public static readonly DependencyProperty PaddingProperty = DependencyProperty.Register(
+ "Padding",
+ typeof(Thickness),
+ typeof(AntdBorder),
+ new FrameworkPropertyMetadata(
+ new Thickness(),
+ FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender
+ ),
+ IsThicknessValid);
+
+ ///
+ /// Gets or sets a thickness value that describes the amount of space between a border and its child element.
+ ///
+ public Thickness Padding
+ {
+ get { return (Thickness)GetValue(PaddingProperty); }
+ set { SetValue(PaddingProperty, value); }
+ }
+
+ public static readonly DependencyProperty BorderStyleProperty = DependencyProperty.Register(
+ "BorderStyle",
+ typeof(BorderStyle),
+ typeof(AntdBorder),
+ new FrameworkPropertyMetadata(
+ BorderStyle.Solid,
+ FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.SubPropertiesDoNotAffectRender,
+ OnClearPenCache
+ ));
+
+ ///
+ /// Gets or sets the border style.
+ ///
+ public BorderStyle BorderStyle
+ {
+ get { return (BorderStyle)GetValue(BorderStyleProperty); }
+ set { SetValue(BorderStyleProperty, value); }
+ }
+
+ #endregion
+
+ #region Overrides
+
+ ///
+ /// Updates DesiredSize of the Border. Called by parent UIElement. This is the first pass of layout.
+ ///
+ ///
+ /// Border determines its desired size it needs from the specified border the child: its sizing
+ /// properties, margin, and requested size.
+ ///
+ /// Constraint size is an "upper limit" that the return value should not exceed.
+ /// The Decorator's desired size.
+ protected override Size MeasureOverride(Size constraint)
+ {
+ var child = Child;
+ var desiredSize = new Size();
+ var borders = BorderThickness;
+
+ if (UseLayoutRounding)
+ {
+ var dpi = DpiUtil.GetDpi(this);
+ borders = new Thickness(UIElementUtil.RoundLayoutValue(borders.Left, dpi.DpiScaleX), UIElementUtil.RoundLayoutValue(borders.Top, dpi.DpiScaleY),
+ UIElementUtil.RoundLayoutValue(borders.Right, dpi.DpiScaleX), UIElementUtil.RoundLayoutValue(borders.Bottom, dpi.DpiScaleY));
+ }
+
+ // Compute the total size required
+ var borderSize = ThicknessUtil.CollapseThickness(borders);
+ var paddingSize = ThicknessUtil.CollapseThickness(Padding);
+
+ // If we have a child
+ if (child != null)
+ {
+ // Combine into total decorating size
+ var combined = new Size(borderSize.Width + paddingSize.Width, borderSize.Height + paddingSize.Height);
+
+ // Remove size of border only from child's reference size.
+ var childConstraint = new Size(Math.Max(0.0, constraint.Width - combined.Width),
+ Math.Max(0.0, constraint.Height - combined.Height));
+
+
+ child.Measure(childConstraint);
+ var childSize = child.DesiredSize;
+
+ // Now use the returned size to drive our size, by adding back the margins, etc.
+ desiredSize.Width = childSize.Width + combined.Width;
+ desiredSize.Height = childSize.Height + combined.Height;
+ }
+ else
+ {
+ // Combine into total decorating size
+ desiredSize = new Size(borderSize.Width + paddingSize.Width, borderSize.Height + paddingSize.Height);
+ }
+
+ return desiredSize;
+ }
+
+ ///
+ /// Border computes the position of its single child and applies its child's alignments to the child.
+ ///
+ /// The size reserved for this element by the parent
+ /// The actual ink area of the element, typically the same as finalSize
+ protected override Size ArrangeOverride(Size finalSize)
+ {
+ var borders = BorderThickness;
+
+ if (UseLayoutRounding)
+ {
+ var dpi = DpiUtil.GetDpi(this);
+ borders = new Thickness(UIElementUtil.RoundLayoutValue(borders.Left, dpi.DpiScaleX), UIElementUtil.RoundLayoutValue(borders.Top, dpi.DpiScaleY),
+ UIElementUtil.RoundLayoutValue(borders.Right, dpi.DpiScaleX), UIElementUtil.RoundLayoutValue(borders.Bottom, dpi.DpiScaleY));
+ }
+
+ var boundRect = new Rect(finalSize);
+ var innerRect = RectUtil.Deflate(boundRect, borders);
+
+ // arrange child
+ var child = Child;
+ if (child != null)
+ {
+ Rect childRect = RectUtil.Deflate(innerRect, Padding);
+ child.Arrange(childRect);
+ }
+
+ var radius = CornerRadius;
+
+ useComplexRender = !CornerRadiusUtil.IsUniform(radius) || !ThicknessUtil.IsUniform(borders);
+ backgroundGeometryCache = upperLeftCache = upperRightCache = lowerRightCache = lowerLeftCache = null;
+
+ if (useComplexRender)
+ {
+ // calculate border / background rendering geometry
+ if (!DoubleUtil.IsZero(boundRect.Width) && !DoubleUtil.IsZero(boundRect.Height))
+ {
+ var outerRadii = new Radii(boundRect, radius, borders, true);
+
+ // Upper-right corner
+ var radiusX = boundRect.TopRight.X - outerRadii.TopRight.X;
+ var radiusY = outerRadii.RightTop.Y - boundRect.TopRight.Y;
+ if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY))
+ {
+ upperRightCache = GenerateRoundedGeometry(outerRadii.TopRight, outerRadii.RightTop, new Size(radiusX, radiusY));
+ }
+
+ // Lower-right corner
+ radiusX = boundRect.BottomRight.X - outerRadii.BottomRight.X;
+ radiusY = boundRect.BottomRight.Y - outerRadii.RightBottom.Y;
+ if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY))
+ {
+ lowerRightCache = GenerateRoundedGeometry(outerRadii.RightBottom, outerRadii.BottomRight, new Size(radiusX, radiusY));
+ }
+
+ // Lower-left corner
+ radiusX = outerRadii.BottomLeft.X - boundRect.BottomLeft.X;
+ radiusY = boundRect.BottomLeft.Y - outerRadii.LeftBottom.Y;
+ if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY))
+ {
+ lowerLeftCache = GenerateRoundedGeometry(outerRadii.BottomLeft, outerRadii.LeftBottom, new Size(radiusX, radiusY));
+ }
+
+ // Upper-left corner
+ radiusX = outerRadii.TopLeft.X - boundRect.TopLeft.X;
+ radiusY = outerRadii.LeftTop.Y - boundRect.TopLeft.Y;
+ if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY))
+ {
+ upperLeftCache = GenerateRoundedGeometry(outerRadii.LeftTop, outerRadii.TopLeft, new Size(radiusX, radiusY));
+ }
+ }
+
+ if (!DoubleUtil.IsZero(innerRect.Width) && !DoubleUtil.IsZero(innerRect.Height))
+ {
+ var innerRadii = new Radii(innerRect, radius, borders, false);
+ var backgroundGeometry = new StreamGeometry();
+
+ using (StreamGeometryContext sc = backgroundGeometry.Open())
+ {
+ // create the border geometry
+ sc.BeginFigure(innerRadii.TopLeft, true /* is filled */, true /* is closed */);
+
+ // Top line
+ sc.LineTo(innerRadii.TopRight, true /* is stroked */, false /* is smooth join */);
+
+ // Upper-right corners
+ var radiusX = innerRect.TopRight.X - innerRadii.TopRight.X;
+ var radiusY = innerRadii.RightTop.Y - innerRect.TopRight.Y;
+ if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY))
+ {
+ sc.ArcTo(innerRadii.RightTop, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise, true, false);
+ }
+
+ // Right line
+ sc.LineTo(innerRadii.RightBottom, true /* is stroked */, false /* is smooth join */);
+
+ // Lower-right corners
+ radiusX = innerRect.BottomRight.X - innerRadii.BottomRight.X;
+ radiusY = innerRect.BottomRight.Y - innerRadii.RightBottom.Y;
+ if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY))
+ {
+ sc.ArcTo(innerRadii.BottomRight, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise, true, false);
+ }
+
+ // Bottom line
+ sc.LineTo(innerRadii.BottomLeft, true /* is stroked */, false /* is smooth join */);
+
+ // Lower-left corners
+ radiusX = innerRadii.BottomLeft.X - innerRect.BottomLeft.X;
+ radiusY = innerRect.BottomLeft.Y - innerRadii.LeftBottom.Y;
+ if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY))
+ {
+ sc.ArcTo(innerRadii.LeftBottom, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise, true, false);
+ }
+
+ // Left line
+ sc.LineTo(innerRadii.LeftTop, true /* is stroked */, false /* is smooth join */);
+
+ // Upper-left corners
+ radiusX = innerRadii.TopLeft.X - innerRect.TopLeft.X;
+ radiusY = innerRadii.LeftTop.Y - innerRect.TopLeft.Y;
+ if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY))
+ {
+ sc.ArcTo(innerRadii.TopLeft, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise, true, false);
+ }
+ }
+
+ backgroundGeometry.Freeze();
+ backgroundGeometryCache = backgroundGeometry;
+ }
+ }
+
+ return finalSize;
+ }
+
+ protected override void OnRender(DrawingContext dc)
+ {
+ if (useComplexRender)
+ {
+ ComplexRender(dc);
+ } else
+ {
+ SimpleRender(dc);
+ }
+ }
+
+ #endregion
+
+ #region Private Methods
+
+ private void SimpleRender(DrawingContext dc)
+ {
+ var useLayoutRounding = UseLayoutRounding;
+ var dpi = DpiUtil.GetDpi(this);
+
+ Brush brush;
+ var borderStyle = BorderStyle;
+
+ var borders = BorderThickness;
+ var cornerRadius = CornerRadius;
+
+ var outerCornerRadius = cornerRadius.TopLeft; // Already validated that all corners have the same radius
+ var roundedCorners = !DoubleUtil.IsZero(outerCornerRadius);
+
+ var width = RenderSize.Width;
+ var height = RenderSize.Height;
+
+ // Draw border
+ if (!ThicknessUtil.IsZero(borders) && (brush = BorderBrush) != null)
+ {
+ var pen = GetPen(brush, borderStyle, borders.Left, dpi.DpiScaleX, useLayoutRounding);
+ var penThickness = pen.Thickness;
+
+ double x = penThickness * 0.5;
+ var rect = new Rect(x, x, width - penThickness, height - penThickness);
+
+ if (roundedCorners)
+ {
+ dc.DrawRoundedRectangle(null, pen, rect, outerCornerRadius, outerCornerRadius);
+ }
+ else
+ {
+ dc.DrawRectangle(null, pen, rect);
+ }
+ }
+
+ // Draw background in rectangle inside border.
+ if ((brush = Background) != null)
+ {
+ // Intialize background
+ Point ptTL, ptBR;
+
+ if (useLayoutRounding)
+ {
+ ptTL = new Point(UIElementUtil.RoundLayoutValue(borders.Left, dpi.DpiScaleX),
+ UIElementUtil.RoundLayoutValue(borders.Top, dpi.DpiScaleY));
+ ptBR = new Point(width - UIElementUtil.RoundLayoutValue(borders.Right, dpi.DpiScaleX),
+ height - UIElementUtil.RoundLayoutValue(borders.Bottom, dpi.DpiScaleY));
+ }
+ else
+ {
+ ptTL = new Point(borders.Left, borders.Top);
+ ptBR = new Point(width - borders.Right, height - borders.Bottom);
+ }
+
+ // Do not draw background if the borders are so large that they overlap.
+ if (ptBR.X > ptTL.X && ptBR.Y > ptTL.Y)
+ {
+ if (roundedCorners)
+ {
+ // Determine the inner edge radius
+ var innerCornerRadius = Math.Max(0.0, outerCornerRadius - borders.Top * 0.5);
+ dc.DrawRoundedRectangle(brush, null, new Rect(ptTL, ptBR), innerCornerRadius, innerCornerRadius);
+ }
+ else
+ {
+ dc.DrawRectangle(brush, null, new Rect(ptTL, ptBR));
+ }
+ }
+ }
+ }
+
+ private void ComplexRender(DrawingContext dc)
+ {
+ Brush brush;
+ var width = RenderSize.Width;
+ var height = RenderSize.Height;
+
+ //Draw border
+ if (!DoubleUtil.IsZero(width) && !DoubleUtil.IsZero(height) && (brush = BorderBrush) != null)
+ {
+ var useLayoutRounding = UseLayoutRounding;
+ var dpi = DpiUtil.GetDpi(this);
+
+ var borders = BorderThickness;
+ var borderStyle = BorderStyle;
+ var radius = CornerRadius;
+ double x, y;
+
+ // Left Line
+ if (!DoubleUtil.IsZero(borders.Left))
+ {
+ if (leftPenCache == null)
+ {
+ leftPenCache = GetPen(brush, borderStyle, borders.Left, dpi.DpiScaleX, useLayoutRounding);
+ }
+
+ x = leftPenCache.Thickness * 0.5;
+ dc.DrawLine(leftPenCache, new Point(x, radius.TopLeft), new Point(x, height - radius.BottomLeft));
+ }
+
+ // Top Line
+ if (!DoubleUtil.IsZero(borders.Top))
+ {
+ if (topPenCache == null)
+ {
+ topPenCache = GetPen(brush, borderStyle, borders.Top, dpi.DpiScaleY, useLayoutRounding);
+ }
+
+ y = topPenCache.Thickness * 0.5;
+ dc.DrawLine(topPenCache, new Point(radius.TopLeft, y), new Point(width - radius.TopRight, y));
+ }
+
+ // Right Line
+ if (!DoubleUtil.IsZero(borders.Right))
+ {
+ if (rightPenCache == null)
+ {
+ rightPenCache = GetPen(brush, borderStyle, borders.Right, dpi.DpiScaleX, useLayoutRounding);
+ }
+
+ x = width - rightPenCache.Thickness * 0.5;
+ dc.DrawLine(rightPenCache, new Point(x, radius.TopRight), new Point(x, height - radius.BottomRight));
+ }
+
+ // Bottom Line
+ if (!DoubleUtil.IsZero(borders.Bottom))
+ {
+ if (bottomPenCache == null)
+ {
+ bottomPenCache = GetPen(brush, borderStyle, borders.Bottom, dpi.DpiScaleY, useLayoutRounding);
+ }
+
+ y = height - bottomPenCache.Thickness * 0.5;
+ dc.DrawLine(bottomPenCache, new Point(radius.BottomLeft, y), new Point(width - radius.BottomRight, y));
+ }
+
+ // Draw Rounded
+ Pen pen;
+
+ if (upperLeftCache != null && (pen = GetMaxPen(leftPenCache, topPenCache)) != null)
+ {
+ dc.DrawGeometry(null, pen, upperLeftCache);
+ }
+
+ if (upperRightCache != null && (pen = GetMaxPen(topPenCache, rightPenCache)) != null)
+ {
+ dc.DrawGeometry(null, pen, upperRightCache);
+ }
+
+ if (lowerRightCache != null && (pen = GetMaxPen(rightPenCache, bottomPenCache)) != null)
+ {
+ dc.DrawGeometry(null, pen, lowerRightCache);
+ }
+
+ if (lowerLeftCache != null && (pen = GetMaxPen(bottomPenCache, leftPenCache)) != null)
+ {
+ dc.DrawGeometry(null, pen, lowerLeftCache);
+ }
+ }
+
+ // Draw background in rectangle inside border.
+ if (backgroundGeometryCache != null && (brush = Background) != null)
+ {
+ dc.DrawGeometry(brush, null, backgroundGeometryCache);
+ }
+ }
+
+ private Pen GetMaxPen(Pen pen1, Pen pen2)
+ {
+ if (pen2 == null || (pen1 != null && pen2.Thickness < pen1.Thickness))
+ {
+ return pen1;
+ }
+
+ return pen2;
+ }
+
+ private static StreamGeometry GenerateRoundedGeometry(Point startPoint, Point endPoint, Size size)
+ {
+ var streamGeometry = new StreamGeometry();
+
+ using (StreamGeometryContext sc = streamGeometry.Open())
+ {
+ sc.BeginFigure(startPoint, true, false);
+ sc.ArcTo(endPoint, size, 0, false, SweepDirection.Clockwise, true, false);
+ }
+
+ streamGeometry.Freeze();
+ return streamGeometry;
+ }
+
+ private static Pen GetPen(Brush brush, BorderStyle borderStyle, double thickness, double dpi, bool useLayoutRounding)
+ {
+ var pen = new Pen
+ {
+ Brush = brush,
+ DashCap = PenLineCap.Flat,
+ Thickness = useLayoutRounding ? UIElementUtil.RoundLayoutValue(thickness, dpi) : thickness,
+ };
+
+ switch (borderStyle)
+ {
+ case BorderStyle.Dotted:
+ pen.DashStyle = new DashStyle(new double[] { 1 }, 0d);
+ break;
+ case BorderStyle.Dashed:
+ pen.DashStyle = new DashStyle(new double[] { 4, 2 }, 0d);
+ break;
+ default:
+ break;
+ }
+
+ if (brush.IsFrozen)
+ {
+ pen.Freeze();
+ }
+
+ return pen;
+ }
+
+ #endregion
+
+ #region Private Structures Classes
+
+ private struct Radii
+ {
+ #region Fields
+
+ internal readonly Point LeftTop;
+
+ internal readonly Point LeftBottom;
+
+ internal readonly Point TopLeft;
+
+ internal readonly Point TopRight;
+
+ internal readonly Point RightTop;
+
+ internal readonly Point RightBottom;
+
+ internal readonly Point BottomRight;
+
+ internal readonly Point BottomLeft;
+
+ #endregion
+
+ internal Radii(Rect rect, CornerRadius radius, Thickness borders, bool outer)
+ {
+ var left = borders.Left * 0.5;
+ var top = borders.Top * 0.5;
+ var right = borders.Right * 0.5;
+ var bottom = borders.Bottom * 0.5;
+
+ LeftTop = new Point(0d, 0d);
+ LeftBottom = new Point(0d, rect.Height);
+
+ TopLeft = new Point(0d, 0d);
+ TopRight = new Point(rect.Width, 0d);
+
+ RightTop = new Point(rect.Width, 0d);
+ RightBottom = new Point(rect.Width, rect.Height);
+
+ BottomRight = new Point(rect.Width, rect.Height);
+ BottomLeft = new Point(0d, rect.Height);
+
+ if (outer)
+ {
+ LeftTop.X = left;
+ LeftBottom.X = left;
+
+ TopLeft.Y = top;
+ TopRight.Y = top;
+
+ RightTop.X -= right;
+ RightBottom.X -= right;
+
+ BottomLeft.Y -= bottom;
+ BottomRight.Y -= bottom;
+
+ if (!DoubleUtil.IsZero(radius.TopLeft))
+ {
+ TopLeft.X = radius.TopLeft; // + left;
+ LeftTop.Y = radius.TopLeft;// + top;
+ }
+
+ if (!DoubleUtil.IsZero(radius.TopRight))
+ {
+ RightTop.Y = radius.TopRight;// + top;
+ TopRight.X -= radius.TopRight;// + right;
+ }
+
+ if (!DoubleUtil.IsZero(radius.BottomRight))
+ {
+ BottomRight.X -= radius.BottomRight;// + right;
+ RightBottom.Y -= radius.BottomRight;// + bottom; ;
+ }
+
+ if (!DoubleUtil.IsZero(radius.BottomLeft))
+ {
+ LeftBottom.Y -= radius.BottomLeft; // + bottom;
+ BottomLeft.X = radius.BottomLeft;// + left;
+ }
+ } else
+ {
+ TopLeft.X = Math.Max(0.0, radius.TopLeft - left);
+ LeftTop.Y = Math.Max(0.0, radius.TopLeft - top);
+
+ RightTop.Y = Math.Max(0.0, radius.TopRight - top);
+ TopRight.X -= Math.Max(0.0, radius.TopRight - right);
+
+ BottomRight.X -= Math.Max(0.0, radius.BottomRight - right);
+ RightBottom.Y -= Math.Max(0.0, radius.BottomRight - bottom);
+
+ LeftBottom.Y -= Math.Max(0.0, radius.BottomLeft - bottom);
+ BottomLeft.X = Math.Max(0.0, radius.BottomLeft - left);
+ }
+
+ // check keypoints for overlap and resolve by partitioning corners according to
+ // the percentage of each one.
+
+ // top edge
+ if (TopLeft.X > TopRight.X)
+ {
+ var v = TopLeft.X / (TopLeft.X + rect.Width - TopRight.X) * rect.Width;
+ TopLeft.X = v;
+ TopRight.X = v;
+ }
+
+ // right edge
+ if (RightTop.Y > RightBottom.Y)
+ {
+ var v = RightTop.Y / (RightTop.Y + rect.Height - RightBottom.Y) * rect.Height;
+ RightTop.Y = v;
+ RightBottom.Y = v;
+ }
+
+ // bottom edge
+ if (BottomRight.X < BottomLeft.X)
+ {
+ var v = BottomLeft.X / (BottomLeft.X + rect.Width - BottomRight.X) * rect.Width;
+ BottomRight.X = v;
+ BottomLeft.X = v;
+ }
+
+ // left edge
+ if (LeftBottom.Y < LeftTop.Y)
+ {
+ var v = LeftTop.Y / (LeftTop.Y + rect.Height - LeftBottom.Y) * rect.Height;
+ LeftBottom.Y = v;
+ LeftTop.Y = v;
+ }
+
+ // Apply offset
+ var offset = new Vector(rect.TopLeft.X, rect.TopLeft.Y);
+
+ LeftTop += offset;
+ LeftBottom += offset;
+
+ TopRight += offset;
+ TopLeft += offset;
+
+ RightTop += offset;
+ RightBottom += offset;
+
+ BottomRight += offset;
+ BottomLeft += offset;
+ }
+ }
+
+ #endregion Private Structures Classes
+}
diff --git a/AntdWpf/Controls/ContentControl.cs b/AntdWpf/Controls/AntdContentControl.cs
similarity index 76%
rename from AntdWpf/Controls/ContentControl.cs
rename to AntdWpf/Controls/AntdContentControl.cs
index d6ad90c..01b4b94 100644
--- a/AntdWpf/Controls/ContentControl.cs
+++ b/AntdWpf/Controls/AntdContentControl.cs
@@ -2,12 +2,11 @@
{
using System.Windows;
using System.Windows.Controls;
- using ContentControlBase = System.Windows.Controls.ContentControl;
- public class ContentControl : ContentControlBase
+ public class AntdContentControl : ContentControl
{
public static readonly DependencyProperty ContentCharacterCasingProperty =
- DependencyProperty.Register("ContentCharacterCasing", typeof(CharacterCasing), typeof(ContentControl),
+ DependencyProperty.Register("ContentCharacterCasing", typeof(CharacterCasing), typeof(AntdContentControl),
new FrameworkPropertyMetadata(CharacterCasing.Normal, FrameworkPropertyMetadataOptions.Inherits | FrameworkPropertyMetadataOptions.AffectsMeasure),
value => CharacterCasing.Normal <= (CharacterCasing)value && (CharacterCasing)value <= CharacterCasing.Upper);
@@ -21,7 +20,7 @@
}
public static readonly DependencyProperty RecognizesAccessKeyProperty =
- DependencyProperty.Register("RecognizesAccessKey", typeof(bool), typeof(ContentControl), new FrameworkPropertyMetadata(false));
+ DependencyProperty.Register("RecognizesAccessKey", typeof(bool), typeof(AntdContentControl), new FrameworkPropertyMetadata(false));
///
/// Determine if the inner ContentPresenter should use AccessText in its style
@@ -32,9 +31,9 @@
set { SetValue(RecognizesAccessKeyProperty, value); }
}
- static ContentControl()
+ static AntdContentControl()
{
- DefaultStyleKeyProperty.OverrideMetadata(typeof(ContentControl), new FrameworkPropertyMetadata(typeof(ContentControl)));
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(AntdContentControl), new FrameworkPropertyMetadata(typeof(AntdContentControl)));
}
}
}
diff --git a/AntdWpf/Controls/Window.cs b/AntdWpf/Controls/AntdWindow.cs
similarity index 89%
rename from AntdWpf/Controls/Window.cs
rename to AntdWpf/Controls/AntdWindow.cs
index 086ed4b..e55428b 100644
--- a/AntdWpf/Controls/Window.cs
+++ b/AntdWpf/Controls/AntdWindow.cs
@@ -1,9 +1,6 @@
-using AntdWpf.Controls;
-
-using AntdWpf.Contracts;
+using AntdWpf.Contracts;
using AntdWpf.Microsoft.Windows.Shell;
using AntdWpf.Win32;
-using Microsoft.Windows.Shell;
using System;
using System.Collections;
using System.Reflection;
@@ -14,22 +11,19 @@ using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using Standard;
-using SystemCommands = AntdWpf.Microsoft.Windows.Shell.SystemCommands;
-using ThumbBase = System.Windows.Controls.Primitives.Thumb;
-using WindowBase = System.Windows.Window;
namespace AntdWpf.Controls
{
- [TemplatePart(Name = PART_TitleBarThumb, Type = typeof(ThumbBase))]
+ [TemplatePart(Name = PART_TitleBarThumb, Type = typeof(Thumb))]
[TemplatePart(Name = PART_TitleBar, Type = typeof(UIElement))]
[TemplatePart(Name = PART_Icon, Type = typeof(FrameworkElement))]
[TemplatePart(Name = PART_LeftWindowCommands, Type = typeof(WindowCommands))]
[TemplatePart(Name = PART_Title, Type = typeof(UIElement))]
[TemplatePart(Name = PART_RightWindowCommands, Type = typeof(WindowCommands))]
[TemplatePart(Name = PART_WindowButtons, Type = typeof(WindowButtons))]
- public class Window : WindowBase
+ public class AntdWindow : Window
{
#region Fields
@@ -47,7 +41,7 @@ namespace AntdWpf.Controls
private const string PART_WindowButtons = "PART_WindowButtons";
- private ThumbBase titleBarThumb;
+ private Thumb titleBarThumb;
private UIElement titleBar;
@@ -66,7 +60,7 @@ namespace AntdWpf.Controls
#region Properties
public static readonly DependencyProperty IgnoreTaskbarProperty =
- DependencyProperty.Register("IgnoreTaskbar", typeof(bool), typeof(Window), new PropertyMetadata(false));
+ DependencyProperty.Register("IgnoreTaskbar", typeof(bool), typeof(AntdWindow), new PropertyMetadata(false));
///
/// Gets/sets whether the window will ignore (and overlap) the taskbar when maximized.
@@ -78,7 +72,7 @@ namespace AntdWpf.Controls
}
public static readonly DependencyProperty ShowSystemMenuProperty =
- DependencyProperty.Register("ShowSystemMenu", typeof(bool), typeof(Window), new PropertyMetadata(false));
+ DependencyProperty.Register("ShowSystemMenu", typeof(bool), typeof(AntdWindow), new PropertyMetadata(false));
///
/// Gets/sets if the the system menu should popup on right click.
@@ -90,7 +84,7 @@ namespace AntdWpf.Controls
}
public static readonly DependencyProperty IsDraggableProperty =
- DependencyProperty.Register("IsDraggable", typeof(bool), typeof(Window), new PropertyMetadata(true));
+ DependencyProperty.Register("IsDraggable", typeof(bool), typeof(AntdWindow), new PropertyMetadata(true));
///
/// Gets/sets if the the allow drag window
@@ -102,7 +96,7 @@ namespace AntdWpf.Controls
}
public static readonly DependencyProperty UseNoneWindowStyleProperty =
- DependencyProperty.Register("UseNoneWindowStyle", typeof(bool), typeof(Window), new PropertyMetadata(false, OnUseNoneWindowStyleChanged));
+ DependencyProperty.Register("UseNoneWindowStyle", typeof(bool), typeof(AntdWindow), new PropertyMetadata(false, OnUseNoneWindowStyleChanged));
///
/// Gets/sets whether the WindowStyle is None or not.
@@ -117,7 +111,7 @@ namespace AntdWpf.Controls
{
if (e.NewValue != e.OldValue)
{
- (d as Window).ToggleNoneWindowStyle((bool)e.NewValue);
+ (d as AntdWindow).ToggleNoneWindowStyle((bool)e.NewValue);
}
}
@@ -130,13 +124,13 @@ namespace AntdWpf.Controls
{
get
{
- var value = typeof(WindowBase).GetProperty("CriticalHandle", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(this, new object[0]);
+ var value = typeof(Window).GetProperty("CriticalHandle", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(this, new object[0]);
return (IntPtr)value;
}
}
public static readonly DependencyProperty TitleBarHeightProperty =
- DependencyProperty.Register("TitleBarHeight", typeof(double), typeof(Window), new PropertyMetadata(30d, OnTitleBarHeightChanged));
+ DependencyProperty.Register("TitleBarHeight", typeof(double), typeof(AntdWindow), new PropertyMetadata(30d, OnTitleBarHeightChanged));
///
/// Gets/sets the TitleBar height.
@@ -149,7 +143,7 @@ namespace AntdWpf.Controls
private static void OnTitleBarHeightChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
- var window = (Window)dependencyObject;
+ var window = (AntdWindow)dependencyObject;
if (e.NewValue != e.OldValue)
{
window.SetVisibiltyForTitleBarElements((int)e.NewValue > 0);
@@ -157,7 +151,7 @@ namespace AntdWpf.Controls
}
public static readonly DependencyProperty TitleBarForegroundProperty =
- DependencyProperty.Register("TitleBarForeground", typeof(Brush), typeof(Window));
+ DependencyProperty.Register("TitleBarForeground", typeof(Brush), typeof(AntdWindow));
///
/// Gets/sets the foreground brush of the title bar.
@@ -169,7 +163,7 @@ namespace AntdWpf.Controls
}
public static readonly DependencyProperty TitleBarBackgroundProperty =
- DependencyProperty.Register("TitleBarBackground", typeof(Brush), typeof(Window), new PropertyMetadata(Brushes.Transparent));
+ DependencyProperty.Register("TitleBarBackground", typeof(Brush), typeof(AntdWindow), new PropertyMetadata(Brushes.Transparent));
///
/// Gets/sets the background brush of the title bar.
@@ -181,7 +175,7 @@ namespace AntdWpf.Controls
}
public static readonly DependencyProperty ShowIconProperty =
- DependencyProperty.Register("ShowIcon", typeof(bool), typeof(Window), new PropertyMetadata(true, OnShowIconChanged));
+ DependencyProperty.Register("ShowIcon", typeof(bool), typeof(AntdWindow), new PropertyMetadata(true, OnShowIconChanged));
///
/// Gets/sets whether the titlebar icon is visible or not.
@@ -196,12 +190,12 @@ namespace AntdWpf.Controls
{
if (e.NewValue != e.OldValue)
{
- (d as Window).SetVisibiltyForIcon();
+ (d as AntdWindow).SetVisibiltyForIcon();
}
}
public static readonly DependencyProperty IconTemplateProperty =
- DependencyProperty.Register("IconTemplate", typeof(DataTemplate), typeof(Window), new PropertyMetadata(null));
+ DependencyProperty.Register("IconTemplate", typeof(DataTemplate), typeof(AntdWindow), new PropertyMetadata(null));
///
/// Gets/sets the icon content template to show a custom icon.
@@ -213,7 +207,7 @@ namespace AntdWpf.Controls
}
public static readonly DependencyProperty TitleCharacterCasingProperty =
- DependencyProperty.Register("TitleCharacterCasing", typeof(CharacterCasing), typeof(Window),
+ DependencyProperty.Register("TitleCharacterCasing", typeof(CharacterCasing), typeof(AntdWindow),
new FrameworkPropertyMetadata(CharacterCasing.Normal, FrameworkPropertyMetadataOptions.Inherits | FrameworkPropertyMetadataOptions.AffectsMeasure),
value => CharacterCasing.Normal <= (CharacterCasing)value && (CharacterCasing)value <= CharacterCasing.Upper);
@@ -227,7 +221,7 @@ namespace AntdWpf.Controls
}
public static readonly DependencyProperty TitleAlignmentProperty =
- DependencyProperty.Register("TitleAlignment", typeof(HorizontalAlignment), typeof(Window), new PropertyMetadata(HorizontalAlignment.Stretch, OnTitleAlignmentChanged));
+ DependencyProperty.Register("TitleAlignment", typeof(HorizontalAlignment), typeof(AntdWindow), new PropertyMetadata(HorizontalAlignment.Stretch, OnTitleAlignmentChanged));
public HorizontalAlignment TitleAlignment
{
@@ -237,7 +231,7 @@ namespace AntdWpf.Controls
private static void OnTitleAlignmentChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
- if (dependencyObject is Window window)
+ if (dependencyObject is AntdWindow window)
{
window.SizeChanged -= window.OnSizeChanged;
@@ -249,7 +243,7 @@ namespace AntdWpf.Controls
}
public static readonly DependencyProperty TitleTemplateProperty =
- DependencyProperty.Register("TitleTemplate", typeof(DataTemplate), typeof(Window), new PropertyMetadata(null));
+ DependencyProperty.Register("TitleTemplate", typeof(DataTemplate), typeof(AntdWindow), new PropertyMetadata(null));
///
/// Gets/sets the title content template to show a custom title.
@@ -261,7 +255,7 @@ namespace AntdWpf.Controls
}
public static readonly DependencyProperty LeftWindowCommandsProperty =
- DependencyProperty.Register("LeftWindowCommands", typeof(WindowCommands), typeof(Window), new PropertyMetadata(null, UpdateLogicalChilds));
+ DependencyProperty.Register("LeftWindowCommands", typeof(WindowCommands), typeof(AntdWindow), new PropertyMetadata(null, UpdateLogicalChilds));
///
/// Gets/sets the left window commands that hosts the user commands.
@@ -273,7 +267,7 @@ namespace AntdWpf.Controls
}
public static readonly DependencyProperty RightWindowCommandsProperty =
- DependencyProperty.Register("RightWindowCommands", typeof(WindowCommands), typeof(Window), new PropertyMetadata(null, UpdateLogicalChilds));
+ DependencyProperty.Register("RightWindowCommands", typeof(WindowCommands), typeof(AntdWindow), new PropertyMetadata(null, UpdateLogicalChilds));
///
/// Gets/sets the right window commands that hosts the user commands.
@@ -285,7 +279,7 @@ namespace AntdWpf.Controls
}
public static readonly DependencyProperty WindowButtonsProperty =
- DependencyProperty.Register("WindowButtons", typeof(WindowButtons), typeof(Window), new PropertyMetadata(null, UpdateLogicalChilds));
+ DependencyProperty.Register("WindowButtons", typeof(WindowButtons), typeof(AntdWindow), new PropertyMetadata(null, UpdateLogicalChilds));
///
/// Gets/sets the window button commands that hosts the min/max/close commands.
@@ -298,7 +292,7 @@ namespace AntdWpf.Controls
private static void UpdateLogicalChilds(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
- if (!(dependencyObject is Window window))
+ if (!(dependencyObject is AntdWindow window))
{
return;
}
@@ -332,14 +326,14 @@ namespace AntdWpf.Controls
#region Constructors
- static Window()
+ static AntdWindow()
{
- DefaultStyleKeyProperty.OverrideMetadata(typeof(Window), new FrameworkPropertyMetadata(typeof(Window)));
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(AntdWindow), new FrameworkPropertyMetadata(typeof(AntdWindow)));
}
- public Window()
+ public AntdWindow()
{
- SetResourceReference(StyleProperty, typeof(Window));
+ //SetResourceReference(StyleProperty, typeof(AntdWindow));
DataContextChanged += OnDataContextChanged;
}
@@ -381,7 +375,7 @@ namespace AntdWpf.Controls
{
base.OnApplyTemplate();
- titleBarThumb = GetTemplateChild(PART_TitleBarThumb) as ThumbBase;
+ titleBarThumb = GetTemplateChild(PART_TitleBarThumb) as Thumb;
titleBar = GetTemplateChild(PART_TitleBar) as UIElement;
icon = GetTemplateChild(PART_Icon) as FrameworkElement;
title = GetTemplateChild(PART_Title) as UIElement;
@@ -557,9 +551,7 @@ namespace AntdWpf.Controls
Close();
} else
{
-#pragma warning disable 618
- SystemCommands.ShowSystemMenu(this, PointToScreen(new Point(0, TitleBarHeight)));
-#pragma warning restore 618
+ System.Windows.SystemCommands.ShowSystemMenu(this, PointToScreen(new Point(0, TitleBarHeight)));
}
}
@@ -583,7 +575,7 @@ namespace AntdWpf.Controls
DoThumbMouseRightButtonUp(this, e);
}
- internal static void DoThumbPreviewMouseLeftButtonUp(Window window, MouseButtonEventArgs e)
+ internal static void DoThumbPreviewMouseLeftButtonUp(AntdWindow window, MouseButtonEventArgs e)
{
if (e.Source == e.OriginalSource)
{
@@ -591,7 +583,7 @@ namespace AntdWpf.Controls
}
}
- internal static void DoThumbDragDelta(IThumb thumb, Window window, DragDeltaEventArgs e)
+ internal static void DoThumbDragDelta(IThumb thumb, AntdWindow window, DragDeltaEventArgs e)
{
if (thumb == null)
{
@@ -660,7 +652,7 @@ namespace AntdWpf.Controls
///
///
///
- internal static void DoThumbMouseDoubleClick(Window window, MouseButtonEventArgs e)
+ internal static void DoThumbMouseDoubleClick(AntdWindow window, MouseButtonEventArgs e)
{
// restore/maximize only with left button
if (e.ChangedButton == MouseButton.Left)
@@ -671,16 +663,14 @@ namespace AntdWpf.Controls
var isMouseOnTitlebar = mousePos.Y <= window.TitleBarHeight && window.TitleBarHeight > 0;
if (canResize && isMouseOnTitlebar)
{
-#pragma warning disable 618
if (window.WindowState == WindowState.Normal)
{
- SystemCommands.MaximizeWindow(window);
+ System.Windows.SystemCommands.MaximizeWindow(window);
}
else
{
- SystemCommands.RestoreWindow(window);
+ System.Windows.SystemCommands.RestoreWindow(window);
}
-#pragma warning restore 618
e.Handled = true;
}
}
@@ -691,7 +681,7 @@ namespace AntdWpf.Controls
///
///
///
- internal static void DoThumbMouseRightButtonUp(Window window, MouseButtonEventArgs e)
+ internal static void DoThumbMouseRightButtonUp(AntdWindow window, MouseButtonEventArgs e)
{
if (window.ShowSystemMenu)
{
@@ -699,9 +689,7 @@ namespace AntdWpf.Controls
var mousePos = e.GetPosition(window);
if ((mousePos.Y <= window.TitleBarHeight && window.TitleBarHeight > 0) || (window.UseNoneWindowStyle && window.TitleBarHeight <= 0))
{
-#pragma warning disable 618
- SystemCommands.ShowSystemMenu(window, window.PointToScreen(mousePos));
-#pragma warning restore 618
+ System.Windows.SystemCommands.ShowSystemMenu(window, window.PointToScreen(mousePos));
}
}
}
diff --git a/AntdWpf/Controls/Avatar.cs b/AntdWpf/Controls/Avatar.cs
index ebc774c..e21be2e 100644
--- a/AntdWpf/Controls/Avatar.cs
+++ b/AntdWpf/Controls/Avatar.cs
@@ -1,258 +1,256 @@
-namespace AntdWpf.Controls
+namespace AntdWpf.Controls;
+
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Markup;
+using System.Windows.Media;
+
+///
+/// Avatars can be used to represent people or objects. It supports images, Icons, or letters.
+///
+[ContentProperty("Text")]
+[TemplatePart(Name = "PART_Content", Type = typeof(ContentPresenter))]
+public class Avatar : Control
{
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Markup;
- using System.Windows.Media;
- using ControlBase = System.Windows.Controls.Control;
+ #region Fields
+
+ private const string PART_Content = "PART_Content";
+
+ private ContentPresenter contentPresenter;
+
+ #endregion
+
+ #region Properties
+
+ public static readonly DependencyProperty IconProperty =
+ DependencyProperty.Register("Icon", typeof(string), typeof(Avatar), new PropertyMetadata(null, OnContentChanged));
///
- /// Avatars can be used to represent people or objects. It supports images, Icons, or letters.
+ /// Gets/sets the icon type for an icon avatar.
///
- [ContentProperty("Text")]
- [TemplatePart(Name = "PART_Content", Type = typeof(ContentPresenter))]
- public class Avatar : ControlBase
+ public string Icon
{
- #region Fields
-
- private const string PART_Content = "PART_Content";
-
- private ContentPresenter contentPresenter;
-
- #endregion
-
- #region Properties
-
- public static readonly DependencyProperty IconProperty =
- DependencyProperty.Register("Icon", typeof(string), typeof(Avatar), new PropertyMetadata(null, OnContentChanged));
-
- ///
- /// Gets/sets the icon type for an icon avatar.
- ///
- public string Icon
- {
- get { return (string)GetValue(IconProperty); }
- set { SetValue(IconProperty, value); }
- }
-
- private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- (d as Avatar).SetContent(true);
- }
-
- public static readonly DependencyProperty ShapeProperty =
- DependencyProperty.Register("Shape", typeof(Shapes), typeof(Avatar), new PropertyMetadata(Shapes.Circle));
-
- ///
- /// Gets/sets the shape of avatar.
- ///
- public Shapes Shape
- {
- get { return (Shapes)GetValue(ShapeProperty); }
- set { SetValue(ShapeProperty, value); }
- }
-
- public static readonly DependencyProperty SizeProperty =
- DependencyProperty.Register("Size", typeof(Sizes?), typeof(Avatar), new PropertyMetadata(null, OnSizeChanged));
-
- ///
- /// Gets/sets the size of the avatar.
- ///
- public Sizes? Size
- {
- get { return (Sizes?)GetValue(SizeProperty); }
- set { SetValue(SizeProperty, value); }
- }
-
- private static void OnSizeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- var avatar = d as Avatar;
- var newValue = (Sizes?)e.NewValue;
- var oldValue = (Sizes?)e.OldValue;
-
- if (newValue.HasValue && newValue.Value >= 0)
- {
- var size = (double)newValue.Value;
- avatar.SetValue(WidthProperty, size);
- avatar.SetValue(HeightProperty, size);
- avatar.SetValue(FontSizeProperty, size / 2);
- }
- else if (oldValue.HasValue && oldValue.Value >= 0)
- {
- avatar.ClearValue(WidthProperty);
- avatar.ClearValue(HeightProperty);
- avatar.ClearValue(FontSizeProperty);
- }
- }
-
- public static readonly DependencyProperty SourceProperty =
- DependencyProperty.Register("Source", typeof(ImageSource), typeof(Avatar), new PropertyMetadata(null, OnContentChanged));
-
- ///
- /// Gets/sets the ImageSource for an image avatar.
- ///
- public ImageSource Source
- {
- get { return (ImageSource)GetValue(SourceProperty); }
- set { SetValue(SourceProperty, value); }
- }
-
- public static readonly DependencyProperty TextProperty =
- DependencyProperty.Register("Text", typeof(string), typeof(Avatar), new PropertyMetadata(string.Empty, OnContentChanged));
-
- ///
- /// Gets/sets the text for an text avatar.
- ///
- public string Text
- {
- get { return (string)GetValue(TextProperty); }
- set { SetValue(TextProperty, value); }
- }
-
- public static readonly DependencyProperty AlternativeProperty =
- DependencyProperty.Register("Alternative", typeof(string), typeof(Avatar), new PropertyMetadata(string.Empty));
-
- ///
- /// Gets/sets the alternative text describing the image.
- ///
- public string Alternative
- {
- get { return (string)GetValue(AlternativeProperty); }
- set { SetValue(AlternativeProperty, value); }
- }
-
- public static readonly DependencyProperty IsImageProperty =
- DependencyProperty.Register("IsImage", typeof(bool), typeof(Avatar), new PropertyMetadata(false));
-
- ///
- /// Gets the current avatar type as an image.
- ///
- public bool IsImage
- {
- get { return (bool)GetValue(IsImageProperty); }
- private set { SetValue(IsImageProperty, value); }
- }
-
- #endregion
-
- #region Constructors
-
- static Avatar()
- {
- DefaultStyleKeyProperty.OverrideMetadata(typeof(Avatar), new FrameworkPropertyMetadata(typeof(Avatar)));
- }
-
- #endregion
-
- #region Overrides
-
- public override void OnApplyTemplate()
- {
- base.OnApplyTemplate();
-
- contentPresenter = GetTemplateChild(PART_Content) as ContentPresenter;
- SetContent(true);
- }
-
- #endregion
-
- #region Private Methods
-
- private void SetContent(bool imageExist)
- {
- if (contentPresenter == null) return;
-
- var content = contentPresenter.Content;
-
- // Clear Event
- if (content is Image)
- {
- ClearValue(IsImageProperty);
- ((Image)content).ImageFailed -= OnImageFailed;
- }
- else if (content is TextBlock)
- {
- SizeChanged -= OnTextSizeChanged;
- ((TextBlock)content).SizeChanged -= OnTextSizeChanged;
- }
-
- if (Source != null && imageExist)
- {
- if (!(content is Image))
- {
- content = new Image();
- }
-
- SetCurrentValue(IsImageProperty, true);
-
- var image = (Image)content;
- image.Source = Source;
-
- image.ImageFailed += OnImageFailed;
- RenderOptions.SetBitmapScalingMode(image, BitmapScalingMode.HighQuality);
-
- }
- else if (Icon != null)
- {
- if (!(content is Icon))
- {
- content = new Icon();
- }
-
- ((Icon)content).Type = Icon;
- }
- else
- {
- var text = string.IsNullOrEmpty(Text) ? (imageExist ? string.Empty : Alternative) : Text;
-
- if (!(content is TextBlock))
- {
- content = new TextBlock();
- }
-
- var textblock = (TextBlock)content;
-
- SizeChanged += OnTextSizeChanged;
- textblock.SizeChanged += OnTextSizeChanged;
-
- textblock.Text = text;
- textblock.RenderTransformOrigin = new Point(0.5, 0.5);
- }
-
- // 引用传递对 Null 无效
- contentPresenter.Content = content;
- }
-
- private void OnImageFailed(object sender, ExceptionRoutedEventArgs e)
- {
- SetContent(false);
- }
-
- ///
- /// Autoset Font Size
- ///
- ///
- ///
- private void OnTextSizeChanged(object sender, SizeChangedEventArgs e)
- {
- if (contentPresenter != null && contentPresenter.Content is TextBlock textBlock)
- {
- var childrenWidth = textBlock.ActualWidth;
- var width = ActualWidth - 8;
- var scale = 1d;
- var left = 0d;
-
- if (width < childrenWidth)
- {
- scale = width / childrenWidth;
- left = ActualWidth / 2 - childrenWidth / 2;
- }
-
- textBlock.Margin = new Thickness(left, 0d, left, 0d);
- textBlock.RenderTransform = new ScaleTransform(scale, scale);
- }
- }
-
- #endregion
+ get { return (string)GetValue(IconProperty); }
+ set { SetValue(IconProperty, value); }
}
+
+ private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ (d as Avatar).SetContent(true);
+ }
+
+ public static readonly DependencyProperty ShapeProperty =
+ DependencyProperty.Register("Shape", typeof(Shapes), typeof(Avatar), new PropertyMetadata(Shapes.Circle));
+
+ ///
+ /// Gets/sets the shape of avatar.
+ ///
+ public Shapes Shape
+ {
+ get { return (Shapes)GetValue(ShapeProperty); }
+ set { SetValue(ShapeProperty, value); }
+ }
+
+ public static readonly DependencyProperty SizeProperty =
+ DependencyProperty.Register("Size", typeof(Sizes?), typeof(Avatar), new PropertyMetadata(null, OnSizeChanged));
+
+ ///
+ /// Gets/sets the size of the avatar.
+ ///
+ public Sizes? Size
+ {
+ get { return (Sizes?)GetValue(SizeProperty); }
+ set { SetValue(SizeProperty, value); }
+ }
+
+ private static void OnSizeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var avatar = d as Avatar;
+ var newValue = (Sizes?)e.NewValue;
+ var oldValue = (Sizes?)e.OldValue;
+
+ if (newValue.HasValue && newValue.Value >= 0)
+ {
+ var size = (double)newValue.Value;
+ avatar.SetValue(WidthProperty, size);
+ avatar.SetValue(HeightProperty, size);
+ avatar.SetValue(FontSizeProperty, size / 2);
+ }
+ else if (oldValue.HasValue && oldValue.Value >= 0)
+ {
+ avatar.ClearValue(WidthProperty);
+ avatar.ClearValue(HeightProperty);
+ avatar.ClearValue(FontSizeProperty);
+ }
+ }
+
+ public static readonly DependencyProperty SourceProperty =
+ DependencyProperty.Register("Source", typeof(ImageSource), typeof(Avatar), new PropertyMetadata(null, OnContentChanged));
+
+ ///
+ /// Gets/sets the ImageSource for an image avatar.
+ ///
+ public ImageSource Source
+ {
+ get { return (ImageSource)GetValue(SourceProperty); }
+ set { SetValue(SourceProperty, value); }
+ }
+
+ public static readonly DependencyProperty TextProperty =
+ DependencyProperty.Register("Text", typeof(string), typeof(Avatar), new PropertyMetadata(string.Empty, OnContentChanged));
+
+ ///
+ /// Gets/sets the text for an text avatar.
+ ///
+ public string Text
+ {
+ get { return (string)GetValue(TextProperty); }
+ set { SetValue(TextProperty, value); }
+ }
+
+ public static readonly DependencyProperty AlternativeProperty =
+ DependencyProperty.Register("Alternative", typeof(string), typeof(Avatar), new PropertyMetadata(string.Empty));
+
+ ///
+ /// Gets/sets the alternative text describing the image.
+ ///
+ public string Alternative
+ {
+ get { return (string)GetValue(AlternativeProperty); }
+ set { SetValue(AlternativeProperty, value); }
+ }
+
+ public static readonly DependencyProperty IsImageProperty =
+ DependencyProperty.Register("IsImage", typeof(bool), typeof(Avatar), new PropertyMetadata(false));
+
+ ///
+ /// Gets the current avatar type as an image.
+ ///
+ public bool IsImage
+ {
+ get { return (bool)GetValue(IsImageProperty); }
+ private set { SetValue(IsImageProperty, value); }
+ }
+
+ #endregion
+
+ #region Constructors
+
+ static Avatar()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(Avatar), new FrameworkPropertyMetadata(typeof(Avatar)));
+ }
+
+ #endregion
+
+ #region Overrides
+
+ public override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ contentPresenter = GetTemplateChild(PART_Content) as ContentPresenter;
+ SetContent(true);
+ }
+
+ #endregion
+
+ #region Private Methods
+
+ private void SetContent(bool imageExist)
+ {
+ if (contentPresenter == null) return;
+
+ var content = contentPresenter.Content;
+
+ // Clear Event
+ if (content is Image img)
+ {
+ ClearValue(IsImageProperty);
+ img.ImageFailed -= OnImageFailed;
+ }
+ else if (content is TextBlock block)
+ {
+ SizeChanged -= OnTextSizeChanged;
+ block.SizeChanged -= OnTextSizeChanged;
+ }
+
+ if (Source != null && imageExist)
+ {
+ if (content is not Image)
+ {
+ content = new Image();
+ }
+
+ SetCurrentValue(IsImageProperty, true);
+
+ var image = (Image)content;
+ image.Source = Source;
+
+ image.ImageFailed += OnImageFailed;
+ RenderOptions.SetBitmapScalingMode(image, BitmapScalingMode.HighQuality);
+
+ }
+ else if (Icon != null)
+ {
+ if (content is not Controls.Icon icon)
+ {
+ content = new Icon();
+ }
+
+ ((Icon)content).Type = Icon;
+ }
+ else
+ {
+ var text = string.IsNullOrEmpty(Text) ? (imageExist ? string.Empty : Alternative) : Text;
+
+ if (content is not TextBlock)
+ {
+ content = new TextBlock();
+ }
+
+ var textblock = (TextBlock)content;
+
+ SizeChanged += OnTextSizeChanged;
+ textblock.SizeChanged += OnTextSizeChanged;
+
+ textblock.Text = text;
+ textblock.RenderTransformOrigin = new Point(0.5, 0.5);
+ }
+
+ // 引用传递对 Null 无效
+ contentPresenter.Content = content;
+ }
+
+ private void OnImageFailed(object sender, ExceptionRoutedEventArgs e)
+ {
+ SetContent(false);
+ }
+
+ ///
+ /// Autoset Font Size
+ ///
+ ///
+ ///
+ private void OnTextSizeChanged(object sender, SizeChangedEventArgs e)
+ {
+ if (contentPresenter != null && contentPresenter.Content is TextBlock textBlock)
+ {
+ var childrenWidth = textBlock.ActualWidth;
+ var width = ActualWidth - 8;
+ var scale = 1d;
+ var left = 0d;
+
+ if (width < childrenWidth)
+ {
+ scale = width / childrenWidth;
+ left = ActualWidth / 2 - childrenWidth / 2;
+ }
+
+ textBlock.Margin = new Thickness(left, 0d, left, 0d);
+ textBlock.RenderTransform = new ScaleTransform(scale, scale);
+ }
+ }
+
+ #endregion
}
diff --git a/AntdWpf/Controls/Badge.cs b/AntdWpf/Controls/Badge.cs
index 05a6b5a..54d989e 100644
--- a/AntdWpf/Controls/Badge.cs
+++ b/AntdWpf/Controls/Badge.cs
@@ -1,224 +1,223 @@
-namespace AntdWpf.Controls
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+using WindowSize = System.Windows.Size;
+using ContentControlBase = System.Windows.Controls.ContentControl;
+
+namespace AntdWpf.Controls;
+
+[TemplatePart(Name = PART_BadgeContainer, Type = typeof(FrameworkElement))]
+[TemplatePart(Name = PART_Count, Type = typeof(ContentPresenter))]
+public class Badge : ContentControlBase
{
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Media;
- using WindowSize = System.Windows.Size;
- using ContentControlBase = System.Windows.Controls.ContentControl;
+ #region Fields
- [TemplatePart(Name = PART_BadgeContainer, Type = typeof(FrameworkElement))]
- [TemplatePart(Name = PART_Count, Type = typeof(ContentPresenter))]
- public class Badge : ContentControlBase
+ private const string PART_BadgeContainer = "PART_BadgeContainer";
+
+ private const string PART_Count = "PART_Count";
+
+ private FrameworkElement badgeContainer;
+
+ private ContentPresenter count;
+
+ #endregion
+
+ #region Properties
+
+ public static readonly DependencyProperty CountProperty =
+ DependencyProperty.Register("Count", typeof(object), typeof(Badge), new PropertyMetadata(null, OnCountChanged));
+
+ ///
+ /// Gets/sets number to show in badge
+ ///
+ public object Count
{
- #region Fields
+ get { return (object)GetValue(CountProperty); }
+ set { SetValue(CountProperty, value); }
+ }
- private const string PART_BadgeContainer = "PART_BadgeContainer";
+ private static void OnCountChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ (d as Badge).ApplyCount();
+ }
- private const string PART_Count = "PART_Count";
+ private void ApplyCount()
+ {
+ if (count == null) return;
- private FrameworkElement badgeContainer;
+ var content = Count;
- private ContentPresenter count;
-
- #endregion
-
- #region Properties
-
- public static readonly DependencyProperty CountProperty =
- DependencyProperty.Register("Count", typeof(object), typeof(Badge), new PropertyMetadata(null, OnCountChanged));
-
- ///
- /// Gets/sets number to show in badge
- ///
- public object Count
+ if (Count is string)
{
- get { return (object)GetValue(CountProperty); }
- set { SetValue(CountProperty, value); }
- }
-
- private static void OnCountChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- (d as Badge).ApplyCount();
- }
-
- private void ApplyCount()
- {
- if (count == null) return;
-
- var content = Count;
-
- if (Count is string)
+ try
{
- try
+ var d = int.Parse(Count as string);
+
+ if (d > OverflowCount)
{
- var d = int.Parse(Count as string);
-
- if (d > OverflowCount)
- {
- content = OverflowCount + "+";
- }
+ content = OverflowCount + "+";
}
- catch { } // Swallow the error, it may be normal
}
-
- count.Content = content;
+ catch { } // Swallow the error, it may be normal
}
- public static readonly DependencyProperty DotProperty =
- DependencyProperty.Register("Dot", typeof(bool), typeof(Badge), new PropertyMetadata(false));
-
- ///
- /// Gets/sets whether to display a red dot instead of count
- ///
- public bool Dot
- {
- get { return (bool)GetValue(DotProperty); }
- set { SetValue(DotProperty, value); }
- }
-
- public static readonly DependencyProperty OffsetProperty =
- DependencyProperty.Register("Offset", typeof(Point?), typeof(Badge), new PropertyMetadata(null));
-
- public Point? Offset
- {
- get { return (Point?)GetValue(OffsetProperty); }
- set { SetValue(OffsetProperty, value); }
- }
-
- public static readonly DependencyProperty OverflowCountProperty =
- DependencyProperty.Register("OverflowCount", typeof(int), typeof(Badge), new PropertyMetadata(99, OnCountChanged));
-
- ///
- /// Gets/sets max count to show
- ///
- public int OverflowCount
- {
- get { return (int)GetValue(OverflowCountProperty); }
- set { SetValue(OverflowCountProperty, value); }
- }
-
- public static readonly DependencyProperty ShowZeroProperty =
- DependencyProperty.Register("ShowZero", typeof(bool), typeof(Badge), new PropertyMetadata(false));
-
- ///
- /// Gets/sets whether to show badge when count is zero
- ///
- public bool ShowZero
- {
- get { return (bool)GetValue(ShowZeroProperty); }
- set { SetValue(ShowZeroProperty, value); }
- }
-
- public static readonly DependencyProperty StatusProperty =
- DependencyProperty.Register("Status", typeof(BadgeStatus?), typeof(Badge), new PropertyMetadata(null));
-
- ///
- /// Gets/sets badge as a status dot
- ///
- public BadgeStatus? Status
- {
- get { return (BadgeStatus?)GetValue(StatusProperty); }
- set { SetValue(StatusProperty, value); }
- }
-
- public static readonly DependencyProperty TextProperty =
- DependencyProperty.Register("Text", typeof(string), typeof(Badge), new PropertyMetadata(string.Empty));
-
- ///
- /// Gets/sets the text of the status dot. valid with StatusProperty set
- ///
- public string Text
- {
- get { return (string)GetValue(TextProperty); }
- set { SetValue(TextProperty, value); }
- }
-
- public static readonly DependencyProperty BadgeHeightProperty =
- DependencyProperty.Register("BadgeHeight", typeof(double), typeof(Badge), new PropertyMetadata(default(double)));
-
- public double BadgeHeight
- {
- get { return (double)GetValue(BadgeHeightProperty); }
- set { SetValue(BadgeHeightProperty, value); }
- }
-
- public static readonly DependencyProperty BadgeForegroundProperty =
- DependencyProperty.Register("BadgeForeground", typeof(Brush), typeof(Badge), new PropertyMetadata(default(Brush)));
-
- public Brush BadgeForeground
- {
- get { return (Brush)GetValue(BadgeForegroundProperty); }
- set { SetValue(BadgeForegroundProperty, value); }
- }
-
-
- public static readonly DependencyProperty BadgeBackgroundProperty =
- DependencyProperty.Register("BadgeBackground", typeof(Brush), typeof(Badge), new PropertyMetadata(default(Brush)));
-
- public Brush BadgeBackground
- {
- get { return (Brush)GetValue(BadgeBackgroundProperty); }
- set { SetValue(BadgeBackgroundProperty, value); }
- }
-
-
- #endregion
-
- #region Constructors
-
- static Badge()
- {
- DefaultStyleKeyProperty.OverrideMetadata(typeof(Badge), new FrameworkPropertyMetadata(typeof(Badge)));
- }
-
- #endregion
-
- #region Overrides
-
- public override void OnApplyTemplate()
- {
- base.OnApplyTemplate();
-
- badgeContainer = GetTemplateChild(PART_BadgeContainer) as FrameworkElement;
- count = GetTemplateChild(PART_Count) as ContentPresenter;
-
- ApplyCount();
- }
-
- protected override WindowSize ArrangeOverride(WindowSize arrangeBounds)
- {
- var result = base.ArrangeOverride(arrangeBounds);
-
- if (badgeContainer == null) return result;
-
- var desiredSize = badgeContainer.DesiredSize;
-
- // System.Console.WriteLine(desiredSize);
- // if ((desiredSize.Width <= 0.0 || desiredSize.Height <= 0.0))
-
-
- //var containerDesiredSize = _badgeContainer.DesiredSize;
- //if ((containerDesiredSize.Width <= 0.0 || containerDesiredSize.Height <= 0.0)
- // && !double.IsNaN(_badgeContainer.ActualWidth) && !double.IsInfinity(_badgeContainer.ActualWidth)
- // && !double.IsNaN(_badgeContainer.ActualHeight) && !double.IsInfinity(_badgeContainer.ActualHeight))
- //{
- // containerDesiredSize = new Size(_badgeContainer.ActualWidth, _badgeContainer.ActualHeight);
- //}
-
- var h = 0 - desiredSize.Width / 2;
- var v = 0 - desiredSize.Height / 2;
-
- // badgeContainer.Margin = new Thickness(0);
- // badgeContainer.Margin = new Thickness(h, v, h, v);
-
- return result;
- }
-
- #endregion
+ count.Content = content;
}
- public enum BadgeStatus : byte
+ public static readonly DependencyProperty DotProperty =
+ DependencyProperty.Register("Dot", typeof(bool), typeof(Badge), new PropertyMetadata(false));
+
+ ///
+ /// Gets/sets whether to display a red dot instead of count
+ ///
+ public bool Dot
{
- Success, Processing, Default, Error, Warning
+ get { return (bool)GetValue(DotProperty); }
+ set { SetValue(DotProperty, value); }
}
+
+ public static readonly DependencyProperty OffsetProperty =
+ DependencyProperty.Register("Offset", typeof(Point?), typeof(Badge), new PropertyMetadata(null));
+
+ public Point? Offset
+ {
+ get { return (Point?)GetValue(OffsetProperty); }
+ set { SetValue(OffsetProperty, value); }
+ }
+
+ public static readonly DependencyProperty OverflowCountProperty =
+ DependencyProperty.Register("OverflowCount", typeof(int), typeof(Badge), new PropertyMetadata(99, OnCountChanged));
+
+ ///
+ /// Gets/sets max count to show
+ ///
+ public int OverflowCount
+ {
+ get { return (int)GetValue(OverflowCountProperty); }
+ set { SetValue(OverflowCountProperty, value); }
+ }
+
+ public static readonly DependencyProperty ShowZeroProperty =
+ DependencyProperty.Register("ShowZero", typeof(bool), typeof(Badge), new PropertyMetadata(false));
+
+ ///
+ /// Gets/sets whether to show badge when count is zero
+ ///
+ public bool ShowZero
+ {
+ get { return (bool)GetValue(ShowZeroProperty); }
+ set { SetValue(ShowZeroProperty, value); }
+ }
+
+ public static readonly DependencyProperty StatusProperty =
+ DependencyProperty.Register("Status", typeof(BadgeStatus?), typeof(Badge), new PropertyMetadata(null));
+
+ ///
+ /// Gets/sets badge as a status dot
+ ///
+ public BadgeStatus? Status
+ {
+ get { return (BadgeStatus?)GetValue(StatusProperty); }
+ set { SetValue(StatusProperty, value); }
+ }
+
+ public static readonly DependencyProperty TextProperty =
+ DependencyProperty.Register("Text", typeof(string), typeof(Badge), new PropertyMetadata(string.Empty));
+
+ ///
+ /// Gets/sets the text of the status dot. valid with StatusProperty set
+ ///
+ public string Text
+ {
+ get { return (string)GetValue(TextProperty); }
+ set { SetValue(TextProperty, value); }
+ }
+
+ public static readonly DependencyProperty BadgeHeightProperty =
+ DependencyProperty.Register("BadgeHeight", typeof(double), typeof(Badge), new PropertyMetadata(default(double)));
+
+ public double BadgeHeight
+ {
+ get { return (double)GetValue(BadgeHeightProperty); }
+ set { SetValue(BadgeHeightProperty, value); }
+ }
+
+ public static readonly DependencyProperty BadgeForegroundProperty =
+ DependencyProperty.Register("BadgeForeground", typeof(Brush), typeof(Badge), new PropertyMetadata(default(Brush)));
+
+ public Brush BadgeForeground
+ {
+ get { return (Brush)GetValue(BadgeForegroundProperty); }
+ set { SetValue(BadgeForegroundProperty, value); }
+ }
+
+
+ public static readonly DependencyProperty BadgeBackgroundProperty =
+ DependencyProperty.Register("BadgeBackground", typeof(Brush), typeof(Badge), new PropertyMetadata(default(Brush)));
+
+ public Brush BadgeBackground
+ {
+ get { return (Brush)GetValue(BadgeBackgroundProperty); }
+ set { SetValue(BadgeBackgroundProperty, value); }
+ }
+
+
+ #endregion
+
+ #region Constructors
+
+ static Badge()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(Badge), new FrameworkPropertyMetadata(typeof(Badge)));
+ }
+
+ #endregion
+
+ #region Overrides
+
+ public override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ badgeContainer = GetTemplateChild(PART_BadgeContainer) as FrameworkElement;
+ count = GetTemplateChild(PART_Count) as ContentPresenter;
+
+ ApplyCount();
+ }
+
+ protected override WindowSize ArrangeOverride(WindowSize arrangeBounds)
+ {
+ var result = base.ArrangeOverride(arrangeBounds);
+
+ if (badgeContainer == null) return result;
+
+ var desiredSize = badgeContainer.DesiredSize;
+
+ // System.Console.WriteLine(desiredSize);
+ // if ((desiredSize.Width <= 0.0 || desiredSize.Height <= 0.0))
+
+
+ //var containerDesiredSize = _badgeContainer.DesiredSize;
+ //if ((containerDesiredSize.Width <= 0.0 || containerDesiredSize.Height <= 0.0)
+ // && !double.IsNaN(_badgeContainer.ActualWidth) && !double.IsInfinity(_badgeContainer.ActualWidth)
+ // && !double.IsNaN(_badgeContainer.ActualHeight) && !double.IsInfinity(_badgeContainer.ActualHeight))
+ //{
+ // containerDesiredSize = new Size(_badgeContainer.ActualWidth, _badgeContainer.ActualHeight);
+ //}
+
+ var h = 0 - desiredSize.Width / 2;
+ var v = 0 - desiredSize.Height / 2;
+
+ // badgeContainer.Margin = new Thickness(0);
+ // badgeContainer.Margin = new Thickness(h, v, h, v);
+
+ return result;
+ }
+
+ #endregion
+}
+
+public enum BadgeStatus : byte
+{
+ Success, Processing, Default, Error, Warning
}
diff --git a/AntdWpf/Controls/Border.cs b/AntdWpf/Controls/Border.cs
deleted file mode 100644
index 0c564cb..0000000
--- a/AntdWpf/Controls/Border.cs
+++ /dev/null
@@ -1,750 +0,0 @@
-namespace AntdWpf.Controls
-{
- using System;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Media;
-
- using AntdWpf.Utils;
-
- ///
- /// Draws a border, background, or both around another element.
- ///
- public class Border : Decorator
- {
- #region Fields
-
- private StreamGeometry backgroundGeometryCache;
-
- private StreamGeometry upperLeftCache;
-
- private StreamGeometry upperRightCache;
-
- private StreamGeometry lowerRightCache;
-
- private StreamGeometry lowerLeftCache;
-
- private bool useComplexRender;
-
- private Pen leftPenCache;
-
- private Pen topPenCache;
-
- private Pen rightPenCache;
-
- private Pen bottomPenCache;
-
- #endregion
-
- #region Properties
-
- public static readonly DependencyProperty BackgroundProperty = DependencyProperty.Register(
- "Background",
- typeof(Brush),
- typeof(Border),
- new FrameworkPropertyMetadata(
- null,
- FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.SubPropertiesDoNotAffectRender
- ));
-
- ///
- /// Gets or sets the brush that fills the area between the bounds of a Border.
- ///
- public Brush Background
- {
- get { return (Brush)GetValue(BackgroundProperty); }
- set { SetValue(BackgroundProperty, value); }
- }
-
- public static readonly DependencyProperty BorderBrushProperty = DependencyProperty.Register(
- "BorderBrush",
- typeof(Brush),
- typeof(Border),
- new FrameworkPropertyMetadata(
- null,
- FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.SubPropertiesDoNotAffectRender,
- OnClearPenCache
- ));
-
- ///
- /// Gets or sets the brush that draws the outer border color.
- ///
- public Brush BorderBrush
- {
- get { return (Brush)GetValue(BorderBrushProperty); }
- set { SetValue(BorderBrushProperty, value); }
- }
-
- public static readonly DependencyProperty BorderThicknessProperty = DependencyProperty.Register(
- "BorderThickness",
- typeof(Thickness),
- typeof(Border),
- new FrameworkPropertyMetadata(
- new Thickness(),
- FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender,
- OnClearPenCache
- ),
- IsThicknessValid);
-
- ///
- /// Gets or sets the relative thickness of a border.
- ///
- public Thickness BorderThickness
- {
- get { return (Thickness)GetValue(BorderThicknessProperty); }
- set { SetValue(BorderThicknessProperty, value); }
- }
-
- private static void OnClearPenCache(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- var border = (Border)d;
- border.leftPenCache = border.topPenCache = border.rightPenCache = border.bottomPenCache = null;
- }
-
- private static bool IsThicknessValid(object value)
- {
- return ThicknessUtil.IsValid((Thickness)value, false, false, false, false);
- }
-
- public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.Register(
- "CornerRadius",
- typeof(CornerRadius),
- typeof(Border),
- new FrameworkPropertyMetadata(
- new CornerRadius(),
- FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender
- ),
- IsCornerRadiusValid);
-
- ///
- /// Gets or sets a value that represents the degree to which the corners of a Border are rounded.
- ///
- public CornerRadius CornerRadius
- {
- get { return (CornerRadius)GetValue(CornerRadiusProperty); }
- set { SetValue(CornerRadiusProperty, value); }
- }
-
- private static bool IsCornerRadiusValid(object value)
- {
- return CornerRadiusUtil.IsValid((CornerRadius)value, false, false, false, false);
- }
-
- public static readonly DependencyProperty PaddingProperty = DependencyProperty.Register(
- "Padding",
- typeof(Thickness),
- typeof(Border),
- new FrameworkPropertyMetadata(
- new Thickness(),
- FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender
- ),
- IsThicknessValid);
-
- ///
- /// Gets or sets a thickness value that describes the amount of space between a border and its child element.
- ///
- public Thickness Padding
- {
- get { return (Thickness)GetValue(PaddingProperty); }
- set { SetValue(PaddingProperty, value); }
- }
-
- public static readonly DependencyProperty BorderStyleProperty = DependencyProperty.Register(
- "BorderStyle",
- typeof(BorderStyle),
- typeof(Border),
- new FrameworkPropertyMetadata(
- BorderStyle.Solid,
- FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.SubPropertiesDoNotAffectRender,
- OnClearPenCache
- ));
-
- ///
- /// Gets or sets the border style.
- ///
- public BorderStyle BorderStyle
- {
- get { return (BorderStyle)GetValue(BorderStyleProperty); }
- set { SetValue(BorderStyleProperty, value); }
- }
-
- #endregion
-
- #region Overrides
-
- ///
- /// Updates DesiredSize of the Border. Called by parent UIElement. This is the first pass of layout.
- ///
- ///
- /// Border determines its desired size it needs from the specified border the child: its sizing
- /// properties, margin, and requested size.
- ///
- /// Constraint size is an "upper limit" that the return value should not exceed.
- /// The Decorator's desired size.
- protected override Size MeasureOverride(Size constraint)
- {
- var child = Child;
- var desiredSize = new Size();
- var borders = BorderThickness;
-
- if (UseLayoutRounding)
- {
- var dpi = DpiUtil.GetDpi(this);
- borders = new Thickness(UIElementUtil.RoundLayoutValue(borders.Left, dpi.DpiScaleX), UIElementUtil.RoundLayoutValue(borders.Top, dpi.DpiScaleY),
- UIElementUtil.RoundLayoutValue(borders.Right, dpi.DpiScaleX), UIElementUtil.RoundLayoutValue(borders.Bottom, dpi.DpiScaleY));
- }
-
- // Compute the total size required
- var borderSize = ThicknessUtil.CollapseThickness(borders);
- var paddingSize = ThicknessUtil.CollapseThickness(Padding);
-
- // If we have a child
- if (child != null)
- {
- // Combine into total decorating size
- var combined = new Size(borderSize.Width + paddingSize.Width, borderSize.Height + paddingSize.Height);
-
- // Remove size of border only from child's reference size.
- var childConstraint = new Size(Math.Max(0.0, constraint.Width - combined.Width),
- Math.Max(0.0, constraint.Height - combined.Height));
-
-
- child.Measure(childConstraint);
- var childSize = child.DesiredSize;
-
- // Now use the returned size to drive our size, by adding back the margins, etc.
- desiredSize.Width = childSize.Width + combined.Width;
- desiredSize.Height = childSize.Height + combined.Height;
- }
- else
- {
- // Combine into total decorating size
- desiredSize = new Size(borderSize.Width + paddingSize.Width, borderSize.Height + paddingSize.Height);
- }
-
- return desiredSize;
- }
-
- ///
- /// Border computes the position of its single child and applies its child's alignments to the child.
- ///
- /// The size reserved for this element by the parent
- /// The actual ink area of the element, typically the same as finalSize
- protected override Size ArrangeOverride(Size finalSize)
- {
- var borders = BorderThickness;
-
- if (UseLayoutRounding)
- {
- var dpi = DpiUtil.GetDpi(this);
- borders = new Thickness(UIElementUtil.RoundLayoutValue(borders.Left, dpi.DpiScaleX), UIElementUtil.RoundLayoutValue(borders.Top, dpi.DpiScaleY),
- UIElementUtil.RoundLayoutValue(borders.Right, dpi.DpiScaleX), UIElementUtil.RoundLayoutValue(borders.Bottom, dpi.DpiScaleY));
- }
-
- var boundRect = new Rect(finalSize);
- var innerRect = RectUtil.Deflate(boundRect, borders);
-
- // arrange child
- var child = Child;
- if (child != null)
- {
- Rect childRect = RectUtil.Deflate(innerRect, Padding);
- child.Arrange(childRect);
- }
-
- var radius = CornerRadius;
-
- useComplexRender = !CornerRadiusUtil.IsUniform(radius) || !ThicknessUtil.IsUniform(borders);
- backgroundGeometryCache = upperLeftCache = upperRightCache = lowerRightCache = lowerLeftCache = null;
-
- if (useComplexRender)
- {
- // calculate border / background rendering geometry
- if (!DoubleUtil.IsZero(boundRect.Width) && !DoubleUtil.IsZero(boundRect.Height))
- {
- var outerRadii = new Radii(boundRect, radius, borders, true);
-
- // Upper-right corner
- var radiusX = boundRect.TopRight.X - outerRadii.TopRight.X;
- var radiusY = outerRadii.RightTop.Y - boundRect.TopRight.Y;
- if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY))
- {
- upperRightCache = GenerateRoundedGeometry(outerRadii.TopRight, outerRadii.RightTop, new Size(radiusX, radiusY));
- }
-
- // Lower-right corner
- radiusX = boundRect.BottomRight.X - outerRadii.BottomRight.X;
- radiusY = boundRect.BottomRight.Y - outerRadii.RightBottom.Y;
- if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY))
- {
- lowerRightCache = GenerateRoundedGeometry(outerRadii.RightBottom, outerRadii.BottomRight, new Size(radiusX, radiusY));
- }
-
- // Lower-left corner
- radiusX = outerRadii.BottomLeft.X - boundRect.BottomLeft.X;
- radiusY = boundRect.BottomLeft.Y - outerRadii.LeftBottom.Y;
- if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY))
- {
- lowerLeftCache = GenerateRoundedGeometry(outerRadii.BottomLeft, outerRadii.LeftBottom, new Size(radiusX, radiusY));
- }
-
- // Upper-left corner
- radiusX = outerRadii.TopLeft.X - boundRect.TopLeft.X;
- radiusY = outerRadii.LeftTop.Y - boundRect.TopLeft.Y;
- if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY))
- {
- upperLeftCache = GenerateRoundedGeometry(outerRadii.LeftTop, outerRadii.TopLeft, new Size(radiusX, radiusY));
- }
- }
-
- if (!DoubleUtil.IsZero(innerRect.Width) && !DoubleUtil.IsZero(innerRect.Height))
- {
- var innerRadii = new Radii(innerRect, radius, borders, false);
- var backgroundGeometry = new StreamGeometry();
-
- using (StreamGeometryContext sc = backgroundGeometry.Open())
- {
- // create the border geometry
- sc.BeginFigure(innerRadii.TopLeft, true /* is filled */, true /* is closed */);
-
- // Top line
- sc.LineTo(innerRadii.TopRight, true /* is stroked */, false /* is smooth join */);
-
- // Upper-right corners
- var radiusX = innerRect.TopRight.X - innerRadii.TopRight.X;
- var radiusY = innerRadii.RightTop.Y - innerRect.TopRight.Y;
- if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY))
- {
- sc.ArcTo(innerRadii.RightTop, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise, true, false);
- }
-
- // Right line
- sc.LineTo(innerRadii.RightBottom, true /* is stroked */, false /* is smooth join */);
-
- // Lower-right corners
- radiusX = innerRect.BottomRight.X - innerRadii.BottomRight.X;
- radiusY = innerRect.BottomRight.Y - innerRadii.RightBottom.Y;
- if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY))
- {
- sc.ArcTo(innerRadii.BottomRight, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise, true, false);
- }
-
- // Bottom line
- sc.LineTo(innerRadii.BottomLeft, true /* is stroked */, false /* is smooth join */);
-
- // Lower-left corners
- radiusX = innerRadii.BottomLeft.X - innerRect.BottomLeft.X;
- radiusY = innerRect.BottomLeft.Y - innerRadii.LeftBottom.Y;
- if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY))
- {
- sc.ArcTo(innerRadii.LeftBottom, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise, true, false);
- }
-
- // Left line
- sc.LineTo(innerRadii.LeftTop, true /* is stroked */, false /* is smooth join */);
-
- // Upper-left corners
- radiusX = innerRadii.TopLeft.X - innerRect.TopLeft.X;
- radiusY = innerRadii.LeftTop.Y - innerRect.TopLeft.Y;
- if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY))
- {
- sc.ArcTo(innerRadii.TopLeft, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise, true, false);
- }
- }
-
- backgroundGeometry.Freeze();
- backgroundGeometryCache = backgroundGeometry;
- }
- }
-
- return finalSize;
- }
-
- protected override void OnRender(DrawingContext dc)
- {
- if (useComplexRender)
- {
- ComplexRender(dc);
- } else
- {
- SimpleRender(dc);
- }
- }
-
- #endregion
-
- #region Private Methods
-
- private void SimpleRender(DrawingContext dc)
- {
- var useLayoutRounding = UseLayoutRounding;
- var dpi = DpiUtil.GetDpi(this);
-
- Brush brush;
- var borderStyle = BorderStyle;
-
- var borders = BorderThickness;
- var cornerRadius = CornerRadius;
-
- var outerCornerRadius = cornerRadius.TopLeft; // Already validated that all corners have the same radius
- var roundedCorners = !DoubleUtil.IsZero(outerCornerRadius);
-
- var width = RenderSize.Width;
- var height = RenderSize.Height;
-
- // Draw border
- if (!ThicknessUtil.IsZero(borders) && (brush = BorderBrush) != null)
- {
- var pen = GetPen(brush, borderStyle, borders.Left, dpi.DpiScaleX, useLayoutRounding);
- var penThickness = pen.Thickness;
-
- double x = penThickness * 0.5;
- var rect = new Rect(x, x, width - penThickness, height - penThickness);
-
- if (roundedCorners)
- {
- dc.DrawRoundedRectangle(null, pen, rect, outerCornerRadius, outerCornerRadius);
- }
- else
- {
- dc.DrawRectangle(null, pen, rect);
- }
- }
-
- // Draw background in rectangle inside border.
- if ((brush = Background) != null)
- {
- // Intialize background
- Point ptTL, ptBR;
-
- if (useLayoutRounding)
- {
- ptTL = new Point(UIElementUtil.RoundLayoutValue(borders.Left, dpi.DpiScaleX),
- UIElementUtil.RoundLayoutValue(borders.Top, dpi.DpiScaleY));
- ptBR = new Point(width - UIElementUtil.RoundLayoutValue(borders.Right, dpi.DpiScaleX),
- height - UIElementUtil.RoundLayoutValue(borders.Bottom, dpi.DpiScaleY));
- }
- else
- {
- ptTL = new Point(borders.Left, borders.Top);
- ptBR = new Point(width - borders.Right, height - borders.Bottom);
- }
-
- // Do not draw background if the borders are so large that they overlap.
- if (ptBR.X > ptTL.X && ptBR.Y > ptTL.Y)
- {
- if (roundedCorners)
- {
- // Determine the inner edge radius
- var innerCornerRadius = Math.Max(0.0, outerCornerRadius - borders.Top * 0.5);
- dc.DrawRoundedRectangle(brush, null, new Rect(ptTL, ptBR), innerCornerRadius, innerCornerRadius);
- }
- else
- {
- dc.DrawRectangle(brush, null, new Rect(ptTL, ptBR));
- }
- }
- }
- }
-
- private void ComplexRender(DrawingContext dc)
- {
- Brush brush;
- var width = RenderSize.Width;
- var height = RenderSize.Height;
-
- //Draw border
- if (!DoubleUtil.IsZero(width) && !DoubleUtil.IsZero(height) && (brush = BorderBrush) != null)
- {
- var useLayoutRounding = UseLayoutRounding;
- var dpi = DpiUtil.GetDpi(this);
-
- var borders = BorderThickness;
- var borderStyle = BorderStyle;
- var radius = CornerRadius;
- double x, y;
-
- // Left Line
- if (!DoubleUtil.IsZero(borders.Left))
- {
- if (leftPenCache == null)
- {
- leftPenCache = GetPen(brush, borderStyle, borders.Left, dpi.DpiScaleX, useLayoutRounding);
- }
-
- x = leftPenCache.Thickness * 0.5;
- dc.DrawLine(leftPenCache, new Point(x, radius.TopLeft), new Point(x, height - radius.BottomLeft));
- }
-
- // Top Line
- if (!DoubleUtil.IsZero(borders.Top))
- {
- if (topPenCache == null)
- {
- topPenCache = GetPen(brush, borderStyle, borders.Top, dpi.DpiScaleY, useLayoutRounding);
- }
-
- y = topPenCache.Thickness * 0.5;
- dc.DrawLine(topPenCache, new Point(radius.TopLeft, y), new Point(width - radius.TopRight, y));
- }
-
- // Right Line
- if (!DoubleUtil.IsZero(borders.Right))
- {
- if (rightPenCache == null)
- {
- rightPenCache = GetPen(brush, borderStyle, borders.Right, dpi.DpiScaleX, useLayoutRounding);
- }
-
- x = width - rightPenCache.Thickness * 0.5;
- dc.DrawLine(rightPenCache, new Point(x, radius.TopRight), new Point(x, height - radius.BottomRight));
- }
-
- // Bottom Line
- if (!DoubleUtil.IsZero(borders.Bottom))
- {
- if (bottomPenCache == null)
- {
- bottomPenCache = GetPen(brush, borderStyle, borders.Bottom, dpi.DpiScaleY, useLayoutRounding);
- }
-
- y = height - bottomPenCache.Thickness * 0.5;
- dc.DrawLine(bottomPenCache, new Point(radius.BottomLeft, y), new Point(width - radius.BottomRight, y));
- }
-
- // Draw Rounded
- Pen pen;
-
- if (upperLeftCache != null && (pen = GetMaxPen(leftPenCache, topPenCache)) != null)
- {
- dc.DrawGeometry(null, pen, upperLeftCache);
- }
-
- if (upperRightCache != null && (pen = GetMaxPen(topPenCache, rightPenCache)) != null)
- {
- dc.DrawGeometry(null, pen, upperRightCache);
- }
-
- if (lowerRightCache != null && (pen = GetMaxPen(rightPenCache, bottomPenCache)) != null)
- {
- dc.DrawGeometry(null, pen, lowerRightCache);
- }
-
- if (lowerLeftCache != null && (pen = GetMaxPen(bottomPenCache, leftPenCache)) != null)
- {
- dc.DrawGeometry(null, pen, lowerLeftCache);
- }
- }
-
- // Draw background in rectangle inside border.
- if (backgroundGeometryCache != null && (brush = Background) != null)
- {
- dc.DrawGeometry(brush, null, backgroundGeometryCache);
- }
- }
-
- private Pen GetMaxPen(Pen pen1, Pen pen2)
- {
- if (pen2 == null || (pen1 != null && pen2.Thickness < pen1.Thickness))
- {
- return pen1;
- }
-
- return pen2;
- }
-
- private static StreamGeometry GenerateRoundedGeometry(Point startPoint, Point endPoint, Size size)
- {
- var streamGeometry = new StreamGeometry();
-
- using (StreamGeometryContext sc = streamGeometry.Open())
- {
- sc.BeginFigure(startPoint, true, false);
- sc.ArcTo(endPoint, size, 0, false, SweepDirection.Clockwise, true, false);
- }
-
- streamGeometry.Freeze();
- return streamGeometry;
- }
-
- private static Pen GetPen(Brush brush, BorderStyle borderStyle, double thickness, double dpi, bool useLayoutRounding)
- {
- var pen = new Pen
- {
- Brush = brush,
- DashCap = PenLineCap.Flat,
- Thickness = useLayoutRounding ? UIElementUtil.RoundLayoutValue(thickness, dpi) : thickness,
- };
-
- switch (borderStyle)
- {
- case BorderStyle.Dotted:
- pen.DashStyle = new DashStyle(new double[] { 1 }, 0d);
- break;
- case BorderStyle.Dashed:
- pen.DashStyle = new DashStyle(new double[] { 4, 2 }, 0d);
- break;
- default:
- break;
- }
-
- if (brush.IsFrozen)
- {
- pen.Freeze();
- }
-
- return pen;
- }
-
- #endregion
-
- #region Private Structures Classes
-
- private struct Radii
- {
- #region Fields
-
- internal readonly Point LeftTop;
-
- internal readonly Point LeftBottom;
-
- internal readonly Point TopLeft;
-
- internal readonly Point TopRight;
-
- internal readonly Point RightTop;
-
- internal readonly Point RightBottom;
-
- internal readonly Point BottomRight;
-
- internal readonly Point BottomLeft;
-
- #endregion
-
- internal Radii(Rect rect, CornerRadius radius, Thickness borders, bool outer)
- {
- var left = borders.Left * 0.5;
- var top = borders.Top * 0.5;
- var right = borders.Right * 0.5;
- var bottom = borders.Bottom * 0.5;
-
- LeftTop = new Point(0d, 0d);
- LeftBottom = new Point(0d, rect.Height);
-
- TopLeft = new Point(0d, 0d);
- TopRight = new Point(rect.Width, 0d);
-
- RightTop = new Point(rect.Width, 0d);
- RightBottom = new Point(rect.Width, rect.Height);
-
- BottomRight = new Point(rect.Width, rect.Height);
- BottomLeft = new Point(0d, rect.Height);
-
- if (outer)
- {
- LeftTop.X = left;
- LeftBottom.X = left;
-
- TopLeft.Y = top;
- TopRight.Y = top;
-
- RightTop.X -= right;
- RightBottom.X -= right;
-
- BottomLeft.Y -= bottom;
- BottomRight.Y -= bottom;
-
- if (!DoubleUtil.IsZero(radius.TopLeft))
- {
- TopLeft.X = radius.TopLeft; // + left;
- LeftTop.Y = radius.TopLeft;// + top;
- }
-
- if (!DoubleUtil.IsZero(radius.TopRight))
- {
- RightTop.Y = radius.TopRight;// + top;
- TopRight.X -= radius.TopRight;// + right;
- }
-
- if (!DoubleUtil.IsZero(radius.BottomRight))
- {
- BottomRight.X -= radius.BottomRight;// + right;
- RightBottom.Y -= radius.BottomRight;// + bottom; ;
- }
-
- if (!DoubleUtil.IsZero(radius.BottomLeft))
- {
- LeftBottom.Y -= radius.BottomLeft; // + bottom;
- BottomLeft.X = radius.BottomLeft;// + left;
- }
- } else
- {
- TopLeft.X = Math.Max(0.0, radius.TopLeft - left);
- LeftTop.Y = Math.Max(0.0, radius.TopLeft - top);
-
- RightTop.Y = Math.Max(0.0, radius.TopRight - top);
- TopRight.X -= Math.Max(0.0, radius.TopRight - right);
-
- BottomRight.X -= Math.Max(0.0, radius.BottomRight - right);
- RightBottom.Y -= Math.Max(0.0, radius.BottomRight - bottom);
-
- LeftBottom.Y -= Math.Max(0.0, radius.BottomLeft - bottom);
- BottomLeft.X = Math.Max(0.0, radius.BottomLeft - left);
- }
-
- // check keypoints for overlap and resolve by partitioning corners according to
- // the percentage of each one.
-
- // top edge
- if (TopLeft.X > TopRight.X)
- {
- var v = TopLeft.X / (TopLeft.X + rect.Width - TopRight.X) * rect.Width;
- TopLeft.X = v;
- TopRight.X = v;
- }
-
- // right edge
- if (RightTop.Y > RightBottom.Y)
- {
- var v = RightTop.Y / (RightTop.Y + rect.Height - RightBottom.Y) * rect.Height;
- RightTop.Y = v;
- RightBottom.Y = v;
- }
-
- // bottom edge
- if (BottomRight.X < BottomLeft.X)
- {
- var v = BottomLeft.X / (BottomLeft.X + rect.Width - BottomRight.X) * rect.Width;
- BottomRight.X = v;
- BottomLeft.X = v;
- }
-
- // left edge
- if (LeftBottom.Y < LeftTop.Y)
- {
- var v = LeftTop.Y / (LeftTop.Y + rect.Height - LeftBottom.Y) * rect.Height;
- LeftBottom.Y = v;
- LeftTop.Y = v;
- }
-
- // Apply offset
- var offset = new Vector(rect.TopLeft.X, rect.TopLeft.Y);
-
- LeftTop += offset;
- LeftBottom += offset;
-
- TopRight += offset;
- TopLeft += offset;
-
- RightTop += offset;
- RightBottom += offset;
-
- BottomRight += offset;
- BottomLeft += offset;
- }
- }
-
- #endregion Private Structures Classes
- }
-}
diff --git a/AntdWpf/Controls/Button.cs b/AntdWpf/Controls/Button.cs
deleted file mode 100644
index 4c65b82..0000000
--- a/AntdWpf/Controls/Button.cs
+++ /dev/null
@@ -1,340 +0,0 @@
-namespace AntdWpf.Controls
-{
- using System;
- using System.Windows;
- using System.Windows.Media;
- using System.Windows.Media.Animation;
- using System.Windows.Shapes;
- using ButtonBase = System.Windows.Controls.Button;
-
- ///
- /// To trigger an operation.
- ///
- [TemplatePart(Name = PART_Border, Type = typeof(FrameworkElement))]
- [TemplateVisualState(Name = "Loaded", GroupName = "LoadStates")]
- [TemplateVisualState(Name = "Unloaded", GroupName = "LoadStates")]
- public class Button : ButtonBase
- {
- #region Fields
-
- private const string PART_Border = "PART_Border";
-
- private FrameworkElement border;
-
- private VisualState mouseOverState;
-
- private VisualState pressedState;
-
- private VisualState focusedState;
-
- #endregion
-
- #region Properties
-
- public static readonly DependencyProperty GhostProperty =
- DependencyProperty.Register("Ghost", typeof(bool), typeof(Button), new PropertyMetadata(false, OnEffectBrushChanged));
-
- ///
- /// Gets/sets whether to make the background transparent and invert text and border colors.
- ///
- public bool Ghost
- {
- get { return (bool)GetValue(GhostProperty); }
- set { SetValue(GhostProperty, value); }
- }
-
- public static readonly DependencyProperty IconProperty =
- DependencyProperty.Register("Icon", typeof(string), typeof(Button), new PropertyMetadata(null));
-
- ///
- /// Gets/sets the icon type of the button.
- ///
- public string Icon
- {
- get { return (string)GetValue(IconProperty); }
- set { SetValue(IconProperty, value); }
- }
-
- public static readonly DependencyProperty LoadingProperty =
- DependencyProperty.Register("Loading", typeof(bool), typeof(Button), new PropertyMetadata(false, OnLoadingChanged));
-
- ///
- /// Gets/sets the loading state of the button.
- ///
- public bool Loading
- {
- get { return (bool)GetValue(LoadingProperty); }
- set { SetValue(LoadingProperty, value); }
- }
-
- private static void OnLoadingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- (d as Button).SetLoadVisualState();
- }
-
- private void SetLoadVisualState()
- {
- VisualStateManager.GoToState(this, (Loading ? "Loaded" : "Unloaded"), true);
- }
-
-
- public static readonly DependencyProperty ShapeProperty =
- DependencyProperty.Register("Shape", typeof(Shapes), typeof(Button), new PropertyMetadata(Shapes.Square));
-
- ///
- /// Gets/sets the shape of button.
- ///
- public Shapes Shape
- {
- get { return (Shapes)GetValue(ShapeProperty); }
- set { SetValue(ShapeProperty, value); }
- }
-
- public static readonly DependencyProperty SizeProperty =
- DependencyProperty.Register("Size", typeof(Sizes?), typeof(Button), new PropertyMetadata(null));
-
- ///
- /// Gets/sets the size of the button.
- ///
- public Sizes? Size
- {
- get { return (Sizes?)GetValue(SizeProperty); }
- set { SetValue(SizeProperty, value); }
- }
-
- public static readonly DependencyProperty TypeProperty =
- DependencyProperty.Register("Type", typeof(ButtonType?), typeof(Button), new PropertyMetadata(null));
-
- ///
- /// Gets/sets the type of the button.
- ///
- public ButtonType? Type
- {
- get { return (ButtonType?)GetValue(TypeProperty); }
- set { SetValue(TypeProperty, value); }
- }
-
- public static readonly DependencyProperty EffectBrushProperty = DependencyProperty.Register(
- "EffectBrush",
- typeof(Brush),
- typeof(Button),
- new FrameworkPropertyMetadata(
- Brushes.Transparent,
- FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.Inherits,
- OnEffectBrushChanged));
-
- ///
- /// Gets/sets the border effect brush of the button.
- ///
- public Brush EffectBrush
- {
- get { return (Brush)GetValue(EffectBrushProperty); }
- set { SetValue(EffectBrushProperty, value); }
- }
-
- private static void OnEffectBrushChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- (d as Button).SetVisualStateAnimation();
- }
-
- ///
- /// Force background transparent in Ghost state.
- ///
- private static object OnBackgroundCoerceValue(DependencyObject d, object baseValue)
- {
- var button = d as Button;
-
- if (button.Ghost)
- {
- return Brushes.Transparent;
- }
-
- return baseValue;
- }
-
- #endregion
-
- #region Constructors
-
- static Button()
- {
- DefaultStyleKeyProperty.OverrideMetadata(typeof(Button), new FrameworkPropertyMetadata(typeof(Button)));
- BackgroundProperty.OverrideMetadata(typeof(Button), new FrameworkPropertyMetadata { CoerceValueCallback = OnBackgroundCoerceValue });
- }
-
- #endregion
-
- #region Overrides
-
- public override void OnApplyTemplate()
- {
- base.OnApplyTemplate();
-
- border = GetTemplateChild(PART_Border) as FrameworkElement;
- mouseOverState = GetTemplateChild("MouseOver") as VisualState;
-
- focusedState = GetTemplateChild("Focused") as VisualState;
- pressedState = GetTemplateChild("Pressed") as VisualState;
-
- SetVisualStateAnimation();
- SetLoadVisualState();
- }
-
- #endregion
-
- #region Private Methods
-
- private void SetVisualStateAnimation()
- {
- // No initialization or no need for me to handle.
- if (border == null || mouseOverState == null && focusedState == null && pressedState == null) return;
-
- // Unable to extract color.
- if (EffectBrush is SolidColorBrush brush)
- {
- var isShape = border is Shape;
- Func