using System; using System.Collections.Generic; using Avalonia.Media; using Avalonia.Media.Immutable; using Avalonia.Platform; using Avalonia.VisualTree; namespace Avalonia.Rendering.SceneGraph { /// /// A node in the scene graph which represents a rectangle draw. /// internal class RectangleNode : BrushDrawOperation { /// /// Initializes a new instance of the class. /// /// The transform. /// The fill brush. /// The stroke pen. /// The rectangle to draw. /// The box shadow parameters /// Child scenes for drawing visual brushes. public RectangleNode( Matrix transform, IBrush brush, IPen pen, RoundedRect rect, BoxShadows boxShadows, IDictionary childScenes = null) : base(boxShadows.TransformBounds(rect.Rect).Inflate((pen?.Thickness ?? 0) / 2), transform) { Transform = transform; Brush = brush?.ToImmutable(); Pen = pen?.ToImmutable(); Rect = rect; ChildScenes = childScenes; BoxShadows = boxShadows; } /// /// Gets the transform with which the node will be drawn. /// public Matrix Transform { get; } /// /// Gets the fill brush. /// public IBrush Brush { get; } /// /// Gets the stroke pen. /// public ImmutablePen Pen { get; } /// /// Gets the rectangle to draw. /// public RoundedRect Rect { get; } /// /// The parameters for the box-shadow effect /// public BoxShadows BoxShadows { get; } /// public override IDictionary ChildScenes { get; } /// /// Determines if this draw operation equals another. /// /// The transform of the other draw operation. /// The fill of the other draw operation. /// The stroke of the other draw operation. /// The rectangle of the other draw operation. /// The box shadow parameters of the other draw operation /// True if the draw operations are the same, otherwise false. /// /// The properties of the other draw operation are passed in as arguments to prevent /// allocation of a not-yet-constructed draw operation object. /// public bool Equals(Matrix transform, IBrush brush, IPen pen, RoundedRect rect, BoxShadows boxShadows) { return transform == Transform && Equals(brush, Brush) && Equals(Pen, pen) && Media.BoxShadows.Equals(BoxShadows, boxShadows) && rect.Equals(Rect); } /// public override void Render(IDrawingContextImpl context) { context.Transform = Transform; context.DrawRectangle(Brush, Pen, Rect, BoxShadows); } /// public override bool HitTest(Point p) { // TODO: This doesn't respect CornerRadius yet. if (Transform.HasInverse) { p *= Transform.Invert(); if (Brush != null) { var rect = Rect.Rect.Inflate((Pen?.Thickness / 2) ?? 0); return rect.Contains(p); } else { var borderRect = Rect.Rect.Inflate((Pen?.Thickness / 2) ?? 0); var emptyRect = Rect.Rect.Deflate((Pen?.Thickness / 2) ?? 0); return borderRect.Contains(p) && !emptyRect.Contains(p); } } return false; } } }