Browse Source

Documented Visual.

pull/58/head
Steven Kirk 11 years ago
parent
commit
6c2346c09a
  1. 14
      Perspex.SceneGraph/GlobalSuppressions.cs
  2. 11
      Perspex.SceneGraph/IVisual.cs
  3. 187
      Perspex.SceneGraph/Visual.cs

14
Perspex.SceneGraph/GlobalSuppressions.cs

@ -0,0 +1,14 @@
// -----------------------------------------------------------------------
// <copyright file="GlobalSuppressions.cs" company="Steven Kirk">
// Copyright 2015 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage(
"StyleCop.CSharp.MaintainabilityRules",
"SA1401:Fields must be private",
Justification = "PerspexProperty fields should not be private.")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage(
"StyleCop.CSharp.DocumentationRules",
"SA1609:Property documentation must have value",
Justification = "This rule is fscking pointless")]

11
Perspex.SceneGraph/IVisual.cs

@ -13,10 +13,10 @@ namespace Perspex
/// Represents a node in the visual scene graph.
/// </summary>
/// <remarks>
/// The <see cref="IVisual"/> interface defines the interface required for a renderer to
/// render a scene graph. You should not usually need to reference this interface unless
/// you are writing a renderer; instead use the extension methods defined in
/// <see cref="VisualExtensions"/> to traverse the scene graph. This interface is
/// The <see cref="IVisual"/> interface defines the interface required for a renderer to
/// render a scene graph. You should not usually need to reference this interface unless
/// you are writing a renderer; instead use the extension methods defined in
/// <see cref="VisualExtensions"/> to traverse the scene graph. This interface is
/// implemented by <see cref="Visual"/>. It should not be necessary to implement it
/// anywhere else.
/// </remarks>
@ -25,7 +25,6 @@ namespace Perspex
/// <summary>
/// Gets the bounds of the scene graph node.
/// </summary>
/// <returns></returns>
Rect Bounds { get; }
/// <summary>
@ -78,7 +77,7 @@ namespace Perspex
/// Returns a transform that transforms the visual's coordinates into the coordinates
/// of the specified <paramref name="visual"/>.
/// </summary>
/// <param name="visual"></param>
/// <param name="visual">The visual to translate the coordinates to.</param>
/// <returns>A <see cref="Matrix"/> containing the transform.</returns>
Matrix TransformToVisual(IVisual visual);
}

187
Perspex.SceneGraph/Visual.cs

@ -20,35 +20,77 @@ namespace Perspex
using Serilog;
using Serilog.Core.Enrichers;
/// <summary>
/// Base class for controls that provides rendering and related visual properties.
/// </summary>
/// <remarks>
/// The <see cref="Visual"/> class acts as a node in the Perspex scene graph and holds
/// all the information needed for an <see cref="IRenderer"/> to render the control.
/// To traverse the scene graph (aka Visual Tree), use the extension methods defined
/// in <see cref="VisualExtensions"/>.
/// </remarks>
public class Visual : Animatable, IVisual
{
/// <summary>
/// Defines the <see cref="Bounds"/> property.
/// </summary>
public static readonly PerspexProperty<Rect> BoundsProperty =
PerspexProperty.Register<Visual, Rect>("Bounds");
PerspexProperty.Register<Visual, Rect>(nameof(Bounds));
/// <summary>
/// Defines the <see cref="ClipToBounds"/> property.
/// </summary>
public static readonly PerspexProperty<bool> ClipToBoundsProperty =
PerspexProperty.Register<Visual, bool>("ClipToBounds");
PerspexProperty.Register<Visual, bool>(nameof(ClipToBounds));
/// <summary>
/// Defines the <see cref="IsVisibleProperty"/> property.
/// </summary>
public static readonly PerspexProperty<bool> IsVisibleProperty =
PerspexProperty.Register<Visual, bool>("IsVisible", true);
PerspexProperty.Register<Visual, bool>(nameof(IsVisible), true);
/// <summary>
/// Defines the <see cref="Opacity"/> property.
/// </summary>
public static readonly PerspexProperty<double> OpacityProperty =
PerspexProperty.Register<Visual, double>("Opacity", 1);
PerspexProperty.Register<Visual, double>(nameof(Opacity), 1);
/// <summary>
/// Defines the <see cref="RenderTransform"/> property.
/// </summary>
public static readonly PerspexProperty<Transform> RenderTransformProperty =
PerspexProperty.Register<Visual, Transform>("RenderTransform");
PerspexProperty.Register<Visual, Transform>(nameof(RenderTransform));
/// <summary>
/// Defines the <see cref="TransformOrigin"/> property.
/// </summary>
public static readonly PerspexProperty<Origin> TransformOriginProperty =
PerspexProperty.Register<Visual, Origin>("TransformOrigin", defaultValue: Origin.Default);
PerspexProperty.Register<Visual, Origin>(nameof(TransformOrigin), defaultValue: Origin.Default);
/// <summary>
/// Defines the <see cref="ZIndex"/> property.
/// </summary>
public static readonly PerspexProperty<int> ZIndexProperty =
PerspexProperty.Register<Visual, int>("ZIndex");
PerspexProperty.Register<Visual, int>(nameof(ZIndex));
/// <summary>
/// Holds the children of the visual.
/// </summary>
private PerspexList<IVisual> visualChildren;
/// <summary>
/// Holds the parent of the visual.
/// </summary>
private Visual visualParent;
/// <summary>
/// The logger for visual-level events.
/// </summary>
private ILogger visualLogger;
/// <summary>
/// Initializes static members of the <see cref="Visual"/> class.
/// </summary>
static Visual()
{
AffectsRender(IsVisibleProperty);
@ -56,6 +98,9 @@ namespace Perspex
RenderTransformProperty.Changed.Subscribe(RenderTransformChanged);
}
/// <summary>
/// Initializes a new instance of the <see cref="Visual"/> class.
/// </summary>
public Visual()
{
this.visualLogger = Log.ForContext(new[]
@ -69,53 +114,80 @@ namespace Perspex
this.visualChildren.CollectionChanged += this.VisualChildrenChanged;
}
/// <summary>
/// Gets the bounds of the scene graph node.
/// </summary>
public Rect Bounds
{
get { return this.GetValue(BoundsProperty); }
protected set { this.SetValue(BoundsProperty, value); }
}
/// <summary>
/// Gets a value indicating whether the scene graph node should be clipped to its bounds.
/// </summary>
public bool ClipToBounds
{
get { return this.GetValue(ClipToBoundsProperty); }
set { this.SetValue(ClipToBoundsProperty, value); }
}
/// <summary>
/// Gets a value indicating whether this scene graph node is visible.
/// </summary>
public bool IsVisible
{
get { return this.GetValue(IsVisibleProperty); }
set { this.SetValue(IsVisibleProperty, value); }
}
/// <summary>
/// Gets the opacity of the scene graph node.
/// </summary>
public double Opacity
{
get { return this.GetValue(OpacityProperty); }
set { this.SetValue(OpacityProperty, value); }
}
/// <summary>
/// Gets the render transform of the scene graph node.
/// </summary>
public Transform RenderTransform
{
get { return this.GetValue(RenderTransformProperty); }
set { this.SetValue(RenderTransformProperty, value); }
}
/// <summary>
/// Gets the transform origin of the scene graph node.
/// </summary>
public Origin TransformOrigin
{
get { return this.GetValue(TransformOriginProperty); }
set { this.SetValue(TransformOriginProperty, value); }
}
/// <summary>
/// Gets the Z index of the node.
/// </summary>
public int ZIndex
{
get { return this.GetValue(ZIndexProperty); }
set { this.SetValue(ZIndexProperty, value); }
}
/// <summary>
/// Gets the scene graph node's child nodes.
/// </summary>
IPerspexReadOnlyList<IVisual> IVisual.VisualChildren
{
get { return this.visualChildren; }
}
/// <summary>
/// Gets the scene graph node's parent node.
/// </summary>
IVisual IVisual.VisualParent
{
get
@ -124,6 +196,9 @@ namespace Perspex
}
}
/// <summary>
/// Invalidates the visual and queues a repaint.
/// </summary>
public void InvalidateVisual()
{
IRenderRoot root = this.GetSelfAndVisualAncestors()
@ -136,17 +211,32 @@ namespace Perspex
}
}
/// <summary>
/// Renders the visual to a <see cref="IDrawingContext"/>.
/// </summary>
/// <param name="context">The drawing context.</param>
public virtual void Render(IDrawingContext context)
{
Contract.Requires<ArgumentNullException>(context != null);
}
/// <summary>
/// Converts a point from control coordinates to screen coordinates.
/// </summary>
/// <param name="point">The point to convert.</param>
/// <returns>The point in screen coordinates.</returns>
public Point PointToScreen(Point point)
{
var p = GetOffsetFromRoot(this);
return p.Item1.TranslatePointToScreen(point + p.Item2);
}
/// <summary>
/// Returns a transform that transforms the visual's coordinates into the coordinates
/// of the specified <paramref name="visual"/>.
/// </summary>
/// <param name="visual">The visual to translate the coordinates to.</param>
/// <returns>A <see cref="Matrix"/> containing the transform.</returns>
public Matrix TransformToVisual(IVisual visual)
{
var thisOffset = GetOffsetFromRoot(this).Item2;
@ -154,11 +244,25 @@ namespace Perspex
return Matrix.Translation(-thatOffset) * Matrix.Translation(thisOffset);
}
/// <summary>
/// Indicates that a property change should cause <see cref="InvalidateVisual"/> to be
/// called.
/// </summary>
/// <param name="property">The property.</param>
/// <remarks>
/// This method should be called in a control's static constructor for each property
/// on the control which when changed should cause a redraw. This is similar to WPF's
/// FrameworkPropertyMetadata.AffectsRender flag.
/// </remarks>
protected static void AffectsRender(PerspexProperty property)
{
property.Changed.Subscribe(AffectsRenderInvalidate);
}
/// <summary>
/// Adds a visual child to the control.
/// </summary>
/// <param name="visual">The child to add.</param>
protected void AddVisualChild(Visual visual)
{
Contract.Requires<ArgumentNullException>(visual != null);
@ -166,6 +270,10 @@ namespace Perspex
this.visualChildren.Add(visual);
}
/// <summary>
/// Adds visual children to the control.
/// </summary>
/// <param name="visuals">The children to add.</param>
protected void AddVisualChildren(IEnumerable<Visual> visuals)
{
Contract.Requires<ArgumentNullException>(visuals != null);
@ -173,11 +281,18 @@ namespace Perspex
this.visualChildren.AddRange(visuals);
}
/// <summary>
/// Removes all visual children from the control.
/// </summary>
protected void ClearVisualChildren()
{
this.visualChildren.Clear();
}
/// <summary>
/// Removes a visual child from the control;
/// </summary>
/// <param name="visual">The child to remove.</param>
protected void RemoveVisualChild(Visual visual)
{
Contract.Requires<ArgumentNullException>(visual != null);
@ -185,6 +300,10 @@ namespace Perspex
this.visualChildren.Remove(visual);
}
/// <summary>
/// Removes a visual children from the control;
/// </summary>
/// <param name="visuals">The children to remove.</param>
protected void RemoveVisualChildren(IEnumerable<Visual> visuals)
{
Contract.Requires<ArgumentNullException>(visuals != null);
@ -195,18 +314,31 @@ namespace Perspex
}
}
/// <summary>
/// Called when the control is added to a visual tree.
/// </summary>
/// <param name="root">The root of the visual tree.</param>
protected virtual void OnAttachedToVisualTree(IRenderRoot root)
{
}
protected virtual void OnDetachedFromVisualTree(IRenderRoot oldRoot)
/// <summary>
/// Called when the control is removed from a visual tree.
/// </summary>
/// <param name="root">The root of the visual tree.</param>
protected virtual void OnDetachedFromVisualTree(IRenderRoot root)
{
}
[Obsolete("Use OnAttachedToVisualTree instead")]
protected virtual void OnVisualParentChanged(Visual oldParent)
{
}
/// <summary>
/// Called when a property changes that should invalidate the visual.
/// </summary>
/// <param name="e">The event args.</param>
private static void AffectsRenderInvalidate(PerspexPropertyChangedEventArgs e)
{
Visual visual = e.Sender as Visual;
@ -217,6 +349,11 @@ namespace Perspex
}
}
/// <summary>
/// Gets the root of the controls visual tree and the distance from the root.
/// </summary>
/// <param name="v">The visual.</param>
/// <returns>A tuple containing the root and the distance from the root</returns>
private static Tuple<IRenderRoot, Vector> GetOffsetFromRoot(IVisual v)
{
var result = new Vector();
@ -235,6 +372,10 @@ namespace Perspex
return Tuple.Create((IRenderRoot)v, result);
}
/// <summary>
/// Called when a visual's <see cref="RenderTransform"/> changes.
/// </summary>
/// <param name="e">The event args.</param>
private static void RenderTransformChanged(PerspexPropertyChangedEventArgs e)
{
var sender = e.Sender as Visual;
@ -258,11 +399,20 @@ namespace Perspex
}
}
/// <summary>
/// Called when the <see cref="RenderTransform.Changed"/> event is fired.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The event args.</param>
private void RenderTransformChanged(object sender, EventArgs e)
{
this.InvalidateVisual();
}
/// <summary>
/// Sets the visual parent of the Visual.
/// </summary>
/// <param name="value">The visual parent.</param>
private void SetVisualParent(Visual value)
{
if (this.visualParent != value)
@ -291,6 +441,11 @@ namespace Perspex
}
}
/// <summary>
/// Called when the <see cref="visualChildren"/> collection changes.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The event args.</param>
private void VisualChildrenChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
@ -315,6 +470,11 @@ namespace Perspex
}
}
/// <summary>
/// Calls the <see cref="OnAttachedToVisualTree(IRenderRoot)"/> method for this control
/// and all of its visual descendents.
/// </summary>
/// <param name="root">The root of the visual tree.</param>
private void NotifyAttachedToVisualTree(IRenderRoot root)
{
this.visualLogger.Verbose("Attached to visual tree");
@ -330,17 +490,22 @@ namespace Perspex
}
}
private void NotifyDetachedFromVisualTree(IRenderRoot oldRoot)
/// <summary>
/// Calls the <see cref="OnDetachedToVisualTree(IRenderRoot)"/> method for this control
/// and all of its visual descendents.
/// </summary>
/// <param name="root">The root of the visual tree.</param>
private void NotifyDetachedFromVisualTree(IRenderRoot root)
{
this.visualLogger.Verbose("Detached from visual tree");
this.OnDetachedFromVisualTree(oldRoot);
this.OnDetachedFromVisualTree(root);
if (this.visualChildren != null)
{
foreach (Visual child in this.visualChildren.OfType<Visual>())
{
child.NotifyDetachedFromVisualTree(oldRoot);
child.NotifyDetachedFromVisualTree(root);
}
}
}

Loading…
Cancel
Save