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