Browse Source

Make Shapes update their geometry.

When a property that affects the Shape's geometry is changed, make sure
the DefiningGeometry gets updated.
pull/387/merge
Steven Kirk 11 years ago
parent
commit
28b6de1019
  1. 23
      src/Perspex.Controls/Shapes/Ellipse.cs
  2. 25
      src/Perspex.Controls/Shapes/Line.cs
  3. 7
      src/Perspex.Controls/Shapes/Path.cs
  4. 22
      src/Perspex.Controls/Shapes/Polygon.cs
  5. 22
      src/Perspex.Controls/Shapes/Polyline.cs
  6. 23
      src/Perspex.Controls/Shapes/Rectangle.cs
  7. 59
      src/Perspex.Controls/Shapes/Shape.cs

23
src/Perspex.Controls/Shapes/Ellipse.cs

@ -7,23 +7,16 @@ namespace Perspex.Controls.Shapes
{
public class Ellipse : Shape
{
private Geometry _geometry;
private Size _geometrySize;
public override Geometry DefiningGeometry
static Ellipse()
{
get
{
if (_geometry == null || _geometrySize != Bounds.Size)
{
var rect = new Rect(Bounds.Size).Deflate(StrokeThickness);
_geometry = new EllipseGeometry(rect);
_geometrySize = Bounds.Size;
}
AffectsGeometry(BoundsProperty);
AffectsGeometry(StrokeThicknessProperty);
}
return _geometry;
}
protected override Geometry CreateDefiningGeometry()
{
var rect = new Rect(Bounds.Size).Deflate(StrokeThickness);
return new EllipseGeometry(rect);
}
protected override Size MeasureOverride(Size availableSize)

25
src/Perspex.Controls/Shapes/Line.cs

@ -1,11 +1,6 @@
// Copyright (c) The Perspex Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Perspex.Media;
namespace Perspex.Controls.Shapes
@ -18,13 +13,11 @@ namespace Perspex.Controls.Shapes
public static readonly StyledProperty<Point> EndPointProperty =
PerspexProperty.Register<Line, Point>("EndPoint");
private LineGeometry _geometry;
private Point _startPoint;
private Point _endPoint;
static Line()
{
StrokeThicknessProperty.OverrideDefaultValue<Line>(1);
AffectsGeometry(StartPointProperty);
AffectsGeometry(EndPointProperty);
}
public Point StartPoint
@ -39,19 +32,9 @@ namespace Perspex.Controls.Shapes
set { SetValue(EndPointProperty, value); }
}
public override Geometry DefiningGeometry
protected override Geometry CreateDefiningGeometry()
{
get
{
if (_geometry == null || StartPoint != _startPoint || EndPoint != _endPoint)
{
_startPoint = StartPoint;
_endPoint = EndPoint;
_geometry = new LineGeometry(_startPoint, _endPoint);
}
return _geometry;
}
return new LineGeometry(StartPoint, EndPoint);
}
}
}

7
src/Perspex.Controls/Shapes/Path.cs

@ -11,12 +11,17 @@ namespace Perspex.Controls.Shapes
public static readonly StyledProperty<Geometry> DataProperty =
PerspexProperty.Register<Path, Geometry>("Data");
static Path()
{
AffectsGeometry(DataProperty);
}
public Geometry Data
{
get { return GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
public override Geometry DefiningGeometry => Data;
protected override Geometry CreateDefiningGeometry() => Data;
}
}

22
src/Perspex.Controls/Shapes/Polygon.cs

@ -11,24 +11,9 @@ namespace Perspex.Controls.Shapes
public static readonly StyledProperty<IList<Point>> PointsProperty =
PerspexProperty.Register<Polygon, IList<Point>>("Points");
private Geometry _geometry;
static Polygon()
{
PointsProperty.Changed.AddClassHandler<Polygon>(x => x.PointsChanged);
}
public override Geometry DefiningGeometry
{
get
{
if (_geometry == null)
{
_geometry = new PolylineGeometry(Points, true);
}
return _geometry;
}
AffectsGeometry(PointsProperty);
}
public IList<Point> Points
@ -37,10 +22,9 @@ namespace Perspex.Controls.Shapes
set { SetValue(PointsProperty, value); }
}
private void PointsChanged(PerspexPropertyChangedEventArgs e)
protected override Geometry CreateDefiningGeometry()
{
_geometry = null;
InvalidateMeasure();
return new PolylineGeometry(Points, true);
}
}
}

22
src/Perspex.Controls/Shapes/Polyline.cs

@ -11,25 +11,10 @@ namespace Perspex.Controls.Shapes
public static readonly StyledProperty<IList<Point>> PointsProperty =
PerspexProperty.Register<Polyline, IList<Point>>("Points");
private Geometry _geometry;
static Polyline()
{
StrokeThicknessProperty.OverrideDefaultValue<Polyline>(1);
PointsProperty.Changed.AddClassHandler<Polyline>(x => x.PointsChanged);
}
public override Geometry DefiningGeometry
{
get
{
if (_geometry == null)
{
_geometry = new PolylineGeometry(Points, false);
}
return _geometry;
}
AffectsGeometry(PointsProperty);
}
public IList<Point> Points
@ -38,10 +23,9 @@ namespace Perspex.Controls.Shapes
set { SetValue(PointsProperty, value); }
}
private void PointsChanged(PerspexPropertyChangedEventArgs e)
protected override Geometry CreateDefiningGeometry()
{
_geometry = null;
InvalidateMeasure();
return new PolylineGeometry(Points, false);
}
}
}

23
src/Perspex.Controls/Shapes/Rectangle.cs

@ -7,23 +7,16 @@ namespace Perspex.Controls.Shapes
{
public class Rectangle : Shape
{
private Geometry _geometry;
private Size _geometrySize;
public override Geometry DefiningGeometry
static Rectangle()
{
get
{
if (_geometry == null || _geometrySize != Bounds.Size)
{
var rect = new Rect(Bounds.Size).Deflate(StrokeThickness);
_geometry = new RectangleGeometry(rect);
_geometrySize = Bounds.Size;
}
AffectsGeometry(BoundsProperty);
AffectsGeometry(StrokeThicknessProperty);
}
return _geometry;
}
protected override Geometry CreateDefiningGeometry()
{
var rect = new Rect(Bounds.Size).Deflate(StrokeThickness);
return new RectangleGeometry(rect);
}
protected override Size MeasureOverride(Size availableSize)

59
src/Perspex.Controls/Shapes/Shape.cs

@ -26,7 +26,7 @@ namespace Perspex.Controls.Shapes
PerspexProperty.Register<Shape, double>("StrokeThickness");
private Matrix _transform = Matrix.Identity;
private Geometry _definingGeometry;
private Geometry _renderedGeometry;
static Shape()
@ -38,9 +38,17 @@ namespace Perspex.Controls.Shapes
AffectsMeasure(StrokeThicknessProperty);
}
public abstract Geometry DefiningGeometry
public Geometry DefiningGeometry
{
get;
get
{
if (_definingGeometry == null)
{
_definingGeometry = CreateDefiningGeometry();
}
return _definingGeometry;
}
}
public Brush Fill
@ -110,6 +118,28 @@ namespace Perspex.Controls.Shapes
}
}
/// <summary>
/// Marks a property as affecting the shape's geometry.
/// </summary>
/// <param name="property">The property.</param>
/// <remarks>
/// After a call to this method in a control's static constructor, any change to the
/// property will cause <see cref="InvalidateGeometry"/> to be called on the element.
/// </remarks>
protected static void AffectsGeometry(PerspexProperty property)
{
property.Changed.Subscribe(AffectsGeometryInvalidate);
}
protected abstract Geometry CreateDefiningGeometry();
protected void InvalidateGeometry()
{
this._renderedGeometry = null;
this._definingGeometry = null;
InvalidateMeasure();
}
protected override Size MeasureOverride(Size availableSize)
{
// This should probably use GetRenderBounds(strokeThickness) but then the calculations
@ -195,5 +225,28 @@ namespace Perspex.Controls.Shapes
return new Size(shapeSize.Width * sx, shapeSize.Height * sy);
}
private static void AffectsGeometryInvalidate(PerspexPropertyChangedEventArgs e)
{
var control = e.Sender as Shape;
if (control != null)
{
// If the geometry is invalidated when Bounds changes, only invalidate when the Size
// portion changes.
if (e.Property == BoundsProperty)
{
var oldBounds = (Rect)e.OldValue;
var newBounds = (Rect)e.NewValue;
if (oldBounds.Size == newBounds.Size)
{
return;
}
}
control.InvalidateGeometry();
}
}
}
}

Loading…
Cancel
Save