Browse Source

Added support for path figures definition in xaml

pull/531/head
donandren 10 years ago
parent
commit
11f2b702de
  1. 103
      src/Perspex.SceneGraph/Media/ArcSegment.cs
  2. 65
      src/Perspex.SceneGraph/Media/BezierSegment .cs
  3. 2
      src/Perspex.SceneGraph/Media/Geometry.cs
  4. 31
      src/Perspex.SceneGraph/Media/LineSegment.cs
  5. 102
      src/Perspex.SceneGraph/Media/PathFigure.cs
  6. 123
      src/Perspex.SceneGraph/Media/PathGeometry.cs
  7. 15
      src/Perspex.SceneGraph/Media/PathGeometryCollections.cs
  8. 10
      src/Perspex.SceneGraph/Media/PathSegment.cs
  9. 46
      src/Perspex.SceneGraph/Media/QuadraticBezierSegment .cs
  10. 57
      src/Perspex.SceneGraph/Media/TransformGroup.cs
  11. 9
      src/Perspex.SceneGraph/Perspex.SceneGraph.csproj

103
src/Perspex.SceneGraph/Media/ArcSegment.cs

@ -0,0 +1,103 @@
// 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.
namespace Perspex.Media
{
public sealed class ArcSegment : PathSegment
{
/// <summary>
/// Defines the <see cref="IsLargeArc"/> property.
/// </summary>
public static readonly StyledProperty<bool> IsLargeArcProperty
= PerspexProperty.Register<ArcSegment, bool>(nameof(IsLargeArc), false);
/// <summary>
/// Defines the <see cref="Point"/> property.
/// </summary>
public static readonly StyledProperty<Point> PointProperty
= PerspexProperty.Register<ArcSegment, Point>(nameof(Point));
/// <summary>
/// Defines the <see cref="RotationAngle"/> property.
/// </summary>
public static readonly StyledProperty<double> RotationAngleProperty
= PerspexProperty.Register<ArcSegment, double>(nameof(RotationAngle), 0);
/// <summary>
/// Defines the <see cref="Size"/> property.
/// </summary>
public static readonly StyledProperty<Size> SizeProperty
= PerspexProperty.Register<ArcSegment, Size>(nameof(Size));
/// <summary>
/// Defines the <see cref="SweepDirection"/> property.
/// </summary>
public static readonly StyledProperty<SweepDirection> SweepDirectionProperty
= PerspexProperty.Register<ArcSegment, SweepDirection>(nameof(SweepDirection), SweepDirection.Clockwise);
/// <summary>
/// Gets or sets a value indicating whether this instance is large arc.
/// </summary>
/// <value>
/// <c>true</c> if this instance is large arc; otherwise, <c>false</c>.
/// </value>
public bool IsLargeArc
{
get { return GetValue(IsLargeArcProperty); }
set { SetValue(IsLargeArcProperty, value); }
}
/// <summary>
/// Gets or sets the point.
/// </summary>
/// <value>
/// The point.
/// </value>
public Point Point
{
get { return GetValue(PointProperty); }
set { SetValue(PointProperty, value); }
}
/// <summary>
/// Gets or sets the rotation angle.
/// </summary>
/// <value>
/// The rotation angle.
/// </value>
public double RotationAngle
{
get { return GetValue(RotationAngleProperty); }
set { SetValue(RotationAngleProperty, value); }
}
/// <summary>
/// Gets or sets the size.
/// </summary>
/// <value>
/// The size.
/// </value>
public Size Size
{
get { return GetValue(SizeProperty); }
set { SetValue(SizeProperty, value); }
}
/// <summary>
/// Gets or sets the sweep direction.
/// </summary>
/// <value>
/// The sweep direction.
/// </value>
public SweepDirection SweepDirection
{
get { return GetValue(SweepDirectionProperty); }
set { SetValue(SweepDirectionProperty, value); }
}
protected internal override void ApplyTo(StreamGeometryContext ctx)
{
ctx.ArcTo(Point, Size, RotationAngle, IsLargeArc, SweepDirection);
}
}
}

65
src/Perspex.SceneGraph/Media/BezierSegment .cs

@ -0,0 +1,65 @@
// 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.
namespace Perspex.Media
{
public sealed class BezierSegment : PathSegment
{
/// <summary>
/// Defines the <see cref="Point1"/> property.
/// </summary>
public static readonly StyledProperty<Point> Point1Property
= PerspexProperty.Register<BezierSegment, Point>(nameof(Point1));
/// <summary>
/// Defines the <see cref="Point2"/> property.
/// </summary>
public static readonly StyledProperty<Point> Point2Property
= PerspexProperty.Register<BezierSegment, Point>(nameof(Point2));
/// <summary>
/// Defines the <see cref="Point3"/> property.
/// </summary>
public static readonly StyledProperty<Point> Point3Property
= PerspexProperty.Register<BezierSegment, Point>(nameof(Point3));
/// <summary>
/// Gets or sets the point1.
/// </summary>
/// <value>
/// The point1.
/// </value>
public Point Point1
{
get { return GetValue(Point1Property); }
set { SetValue(Point1Property, value); }
}
/// <summary>
/// Gets or sets the point2.
/// </summary>
/// <value>
/// The point2.
/// </value>
public Point Point2
{
get { return GetValue(Point2Property); }
set { SetValue(Point2Property, value); }
}
/// <summary>
/// Gets or sets the point3.
/// </summary>
/// <value>
/// The point3.
/// </value>
public Point Point3
{
get { return GetValue(Point3Property); }
set { SetValue(Point3Property, value); }
}
protected internal override void ApplyTo(StreamGeometryContext ctx)
{
ctx.CubicBezierTo(Point1, Point2, Point3);
}
}
}

2
src/Perspex.SceneGraph/Media/Geometry.cs

@ -36,7 +36,7 @@ namespace Perspex.Media
/// <summary>
/// Gets the platform-specific implementation of the geometry.
/// </summary>
public IGeometryImpl PlatformImpl
public virtual IGeometryImpl PlatformImpl
{
get;
protected set;

31
src/Perspex.SceneGraph/Media/LineSegment.cs

@ -0,0 +1,31 @@
// 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.
namespace Perspex.Media
{
public sealed class LineSegment : PathSegment
{
/// <summary>
/// Defines the <see cref="Point"/> property.
/// </summary>
public static readonly StyledProperty<Point> PointProperty
= PerspexProperty.Register<LineSegment, Point>(nameof(Point));
/// <summary>
/// Gets or sets the point.
/// </summary>
/// <value>
/// The point.
/// </value>
public Point Point
{
get { return GetValue(PointProperty); }
set { SetValue(PointProperty, value); }
}
protected internal override void ApplyTo(StreamGeometryContext ctx)
{
ctx.LineTo(Point);
}
}
}

102
src/Perspex.SceneGraph/Media/PathFigure.cs

@ -0,0 +1,102 @@
// 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 Perspex.Metadata;
namespace Perspex.Media
{
public sealed class PathFigure : PerspexObject
{
/// <summary>
/// Defines the <see cref="IsClosed"/> property.
/// </summary>
public static readonly StyledProperty<bool> IsClosedProperty
= PerspexProperty.Register<PathFigure, bool>(nameof(IsClosed), true);
/// <summary>
/// Defines the <see cref="IsFilled"/> property.
/// </summary>
public static readonly StyledProperty<bool> IsFilledProperty
= PerspexProperty.Register<PathFigure, bool>(nameof(IsFilled), true);
/// <summary>
/// Defines the <see cref="Segments"/> property.
/// </summary>
public static readonly DirectProperty<PathFigure, PathSegments> SegmentsProperty
= PerspexProperty.RegisterDirect<PathFigure, PathSegments>(nameof(Segments), f => f.Segments, (f, s) => f.Segments = s);
/// <summary>
/// Defines the <see cref="StartPoint"/> property.
/// </summary>
public static readonly StyledProperty<Point> StartPointProperty
= PerspexProperty.Register<PathFigure, Point>(nameof(StartPoint));
/// <summary>
/// Initializes a new instance of the <see cref="PathFigure"/> class.
/// </summary>
public PathFigure()
{
Segments = new PathSegments();
}
/// <summary>
/// Gets or sets a value indicating whether this instance is closed.
/// </summary>
/// <value>
/// <c>true</c> if this instance is closed; otherwise, <c>false</c>.
/// </value>
public bool IsClosed
{
get { return GetValue(IsClosedProperty); }
set { SetValue(IsClosedProperty, value); }
}
/// <summary>
/// Gets or sets a value indicating whether this instance is filled.
/// </summary>
/// <value>
/// <c>true</c> if this instance is filled; otherwise, <c>false</c>.
/// </value>
public bool IsFilled
{
get { return GetValue(IsFilledProperty); }
set { SetValue(IsFilledProperty, value); }
}
/// <summary>
/// Gets or sets the segments.
/// </summary>
/// <value>
/// The segments.
/// </value>
[Content]
public PathSegments Segments
{
get { return _segments; }
set { SetAndRaise(SegmentsProperty, ref _segments, value); }
}
/// <summary>
/// Gets or sets the start point.
/// </summary>
/// <value>
/// The start point.
/// </value>
public Point StartPoint
{
get { return GetValue(StartPointProperty); }
set { SetValue(StartPointProperty, value); }
}
internal void ApplyTo(StreamGeometryContext ctx)
{
ctx.BeginFigure(StartPoint, IsFilled);
foreach (var segment in Segments)
{
segment.ApplyTo(ctx);
}
ctx.EndFigure(IsClosed);
}
private PathSegments _segments;
}
}

123
src/Perspex.SceneGraph/Media/PathGeometry.cs

@ -0,0 +1,123 @@
// 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 Perspex.Collections;
using Perspex.Metadata;
using Perspex.Platform;
using System;
namespace Perspex.Media
{
public class PathGeometry : StreamGeometry
{
/// <summary>
/// Defines the <see cref="Figures"/> property.
/// </summary>
public static readonly DirectProperty<PathGeometry, PathFigures> FiguresProperty =
PerspexProperty.RegisterDirect<PathGeometry, PathFigures>(nameof(Figures), g => g.Figures, (g, f) => g.Figures = f);
/// <summary>
/// Defines the <see cref="FillRule"/> property.
/// </summary>
public static readonly StyledProperty<FillRule> FillRuleProperty =
PerspexProperty.Register<PathGeometry, FillRule>(nameof(FillRule));
static PathGeometry()
{
FiguresProperty.Changed.Subscribe(onNext: v =>
{
(v.Sender as PathGeometry)?.OnFiguresChanged(v.OldValue as PathFigures, v.NewValue as PathFigures);
});
}
/// <summary>
/// Initializes a new instance of the <see cref="PathGeometry"/> class.
/// </summary>
public PathGeometry()
{
Figures = new PathFigures();
}
/// <summary>
/// Gets or sets the figures.
/// </summary>
/// <value>
/// The figures.
/// </value>
[Content]
public PathFigures Figures
{
get { return _figures; }
set { SetAndRaise(FiguresProperty, ref _figures, value); }
}
/// <summary>
/// Gets or sets the fill rule.
/// </summary>
/// <value>
/// The fill rule.
/// </value>
public FillRule FillRule
{
get { return GetValue(FillRuleProperty); }
set { SetValue(FillRuleProperty, value); }
}
public override IGeometryImpl PlatformImpl
{
get
{
PrepareIfNeeded();
return base.PlatformImpl;
}
protected set
{
base.PlatformImpl = value;
}
}
public override Geometry Clone()
{
PrepareIfNeeded();
return base.Clone();
}
public void PrepareIfNeeded()
{
if (_isDirty)
{
_isDirty = false;
using (var ctx = Open())
{
ctx.SetFillRule(FillRule);
foreach (var f in Figures)
{
f.ApplyTo(ctx);
}
}
}
}
internal void NotifyChanged()
{
_isDirty = true;
}
private PathFigures _figures;
private IDisposable _figuresObserver = null;
private IDisposable _figuresPropertiesObserver = null;
private bool _isDirty = true;
private void OnFiguresChanged(PathFigures oldValue, PathFigures newValue)
{
_figuresObserver?.Dispose();
_figuresPropertiesObserver?.Dispose();
_figuresObserver = newValue?.ForEachItem(f => NotifyChanged(), f => NotifyChanged(), () => NotifyChanged());
_figuresPropertiesObserver = newValue?.TrackItemPropertyChanged(t => NotifyChanged());
}
}
}

15
src/Perspex.SceneGraph/Media/PathGeometryCollections.cs

@ -0,0 +1,15 @@
// 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 Perspex.Collections;
namespace Perspex.Media
{
public sealed class PathFigures : PerspexList<PathFigure>
{
}
public sealed class PathSegments : PerspexList<PathSegment>
{
}
}

10
src/Perspex.SceneGraph/Media/PathSegment.cs

@ -0,0 +1,10 @@
// 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.
namespace Perspex.Media
{
public abstract class PathSegment : PerspexObject
{
protected internal abstract void ApplyTo(StreamGeometryContext ctx);
}
}

46
src/Perspex.SceneGraph/Media/QuadraticBezierSegment .cs

@ -0,0 +1,46 @@
namespace Perspex.Media
{
public sealed class QuadraticBezierSegment : PathSegment
{
/// <summary>
/// Defines the <see cref="Point1"/> property.
/// </summary>
public static readonly StyledProperty<Point> Point1Property
= PerspexProperty.Register<QuadraticBezierSegment, Point>(nameof(Point1));
/// <summary>
/// Defines the <see cref="Point2"/> property.
/// </summary>
public static readonly StyledProperty<Point> Point2Property
= PerspexProperty.Register<QuadraticBezierSegment, Point>(nameof(Point2));
/// <summary>
/// Gets or sets the point1.
/// </summary>
/// <value>
/// The point1.
/// </value>
public Point Point1
{
get { return GetValue(Point1Property); }
set { SetValue(Point1Property, value); }
}
/// <summary>
/// Gets or sets the point2.
/// </summary>
/// <value>
/// The point2.
/// </value>
public Point Point2
{
get { return GetValue(Point2Property); }
set { SetValue(Point2Property, value); }
}
protected internal override void ApplyTo(StreamGeometryContext ctx)
{
ctx.QuadraticBezierTo(Point1, Point2);
}
}
}

57
src/Perspex.SceneGraph/Media/TransformGroup.cs

@ -0,0 +1,57 @@
// 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 Perspex.Collections;
using Perspex.Metadata;
namespace Perspex.Media
{
public class TransformGroup : Transform
{
/// <summary>
/// Defines the <see cref="Children"/> property.
/// </summary>
public static readonly PerspexProperty<Transforms> ChildrenProperty =
PerspexProperty.Register<TransformGroup, Transforms>(nameof(Children));
public TransformGroup()
{
Children = new Transforms();
}
/// <summary>
/// Gets or sets the children.
/// </summary>
/// <value>
/// The children.
/// </value>
[Content]
public Transforms Children
{
get { return GetValue(ChildrenProperty); }
set { SetValue(ChildrenProperty, value); }
}
/// <summary>
/// Gets the tranform's <see cref="Matrix" />.
/// </summary>
public override Matrix Value
{
get
{
Matrix result = Matrix.Identity;
foreach (var t in Children)
{
result *= t.Value;
}
return result;
}
}
}
public sealed class Transforms : PerspexList<Transform>
{
}
}

9
src/Perspex.SceneGraph/Perspex.SceneGraph.csproj

@ -61,11 +61,14 @@
<Compile Include="Matrix.cs" />
<Compile Include="Media\AlignmentY.cs" />
<Compile Include="Media\AlignmentX.cs" />
<Compile Include="Media\ArcSegment.cs" />
<Compile Include="Media\BezierSegment .cs" />
<Compile Include="Media\Brush.cs" />
<Compile Include="Media\Brushes.cs" />
<Compile Include="Media\BrushMappingMode.cs" />
<Compile Include="Media\Color.cs" />
<Compile Include="Media\Colors.cs" />
<Compile Include="Media\TransformGroup.cs" />
<Compile Include="Media\DashStyle.cs" />
<Compile Include="Media\DrawingContext.cs" />
<Compile Include="Media\FillRule.cs" />
@ -75,9 +78,15 @@
<Compile Include="Media\IBrush.cs" />
<Compile Include="Media\ISolidColorBrush.cs" />
<Compile Include="Media\LineGeometry.cs" />
<Compile Include="Media\LineSegment.cs" />
<Compile Include="Media\Mutable\SolidColorBrush.cs" />
<Compile Include="Media\PathGeometryCollections.cs" />
<Compile Include="Media\PathFigure.cs" />
<Compile Include="Media\PathGeometry.cs" />
<Compile Include="Media\PathSegment.cs" />
<Compile Include="Media\PenLineJoin.cs" />
<Compile Include="Media\PolylineGeometry.cs" />
<Compile Include="Media\QuadraticBezierSegment .cs" />
<Compile Include="Media\RadialGradientBrush.cs" />
<Compile Include="Media\LinearGradientBrush.cs" />
<Compile Include="Media\MediaExtensions.cs" />

Loading…
Cancel
Save