File: System\Windows\Input\Manipulations\InertiaRotationBehavior2D.cs
Web Access
Project: src\src\Microsoft.DotNet.Wpf\src\System.Windows.Input.Manipulations\System.Windows.Input.Manipulations.csproj (System.Windows.Input.Manipulations)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
namespace System.Windows.Input.Manipulations
{
    /// <summary>
    /// Describes desired rotation behavior of an inertia processor.
    /// </summary>
    public sealed class InertiaRotationBehavior2D : InertiaParameters2D
    {
        private const string desiredDecelerationName = "DesiredDeceleration";
        private const string desiredRotationName = "DesiredRotation";
        private const string initialVelocityName = "InitialVelocity";
 
        private float desiredDeceleration = float.NaN;
        private float desiredRotation = float.NaN;
        private float initialVelocity = float.NaN;
 
        /// <summary>
        /// Sets the desired angular deceleration, in radians per millisecond squared.
        /// </summary>
        /// <remarks>
        /// <para>
        /// This property represents the desired angular deceleration to be used during inertia operation.
        /// This property value is mutually exclusive with the 
        /// <strong><see cref="DesiredRotation"/></strong> property;
        /// setting this property will set <strong>DesiredRotation</strong> to <strong>NaN</strong>.
        /// The default value for both this property and
        /// <strong>DesiredRotation</strong> is <strong>NaN</strong>.
        /// You must set one or the other property before inertia processing starts.
        /// </para>
        /// <para>
        /// <strong>DesiredDeceleration</strong> must be a finite, non-negative number.
        /// </para>
        /// <para>
        /// This property cannot be set while the inertia processor is running; 
        /// otherwise, an exception is thrown.
        /// </para>
        /// </remarks>
        public float DesiredDeceleration
        {
            get { return this.desiredDeceleration; }
            set
            {
                Validations.CheckFiniteNonNegative(value, desiredDecelerationName);
                ProtectedChangeProperty(
                    () => value == this.desiredDeceleration,
                    () => { this.desiredDeceleration = value; this.desiredRotation = float.NaN; },
                    desiredDecelerationName);
            }
        }
 
        /// <summary>
        /// Sets the desired rotation, in radians.
        /// </summary>
        /// <remarks>
        /// <para>
        /// This property represents the desired ending rotation of the inertia operation.
        /// This property value is mutually exclusive with the 
        /// <strong><see cref="DesiredDeceleration"/></strong> property;
        /// setting this property will set <strong>DesiredDeceleration</strong>
        /// to <strong>NaN</strong>.
        /// The default value for both this property and
        /// <strong>DesiredDeceleration</strong> is <strong>NaN</strong>.
        /// You must set one or the other property before inertia processing starts.
        /// </para>
        /// <para>
        /// <strong>DesiredRotation</strong> must be a finite, non-negative number.
        /// The direction of rotation is determined by the 
        /// <strong><see cref="InitialVelocity"/></strong> property.
        /// </para>
        /// <para>
        /// This property cannot be set while the inertia processor is running; 
        /// otherwise, an exception is thrown.
        /// </para>
        /// </remarks>
        /// <example>
        /// In the following example, the <strong>DesiredRotation</strong>
        /// property is set to enable inertia processing to rotate an object 
        /// three-and-one-half times from its starting orientation.
        /// <code source="MPIP\ManipulationAPI\ManipulationItem.xaml.cs" region="SetDesiredRotation"/>
        /// </example>
        public float DesiredRotation
        {
            get { return this.desiredRotation; }
            set
            {
                Validations.CheckFiniteNonNegative(value, desiredRotationName);
                ProtectedChangeProperty(
                    () => value == this.desiredRotation,
                    () => { this.desiredRotation = value; this.desiredDeceleration = float.NaN; },
                    desiredRotationName);
            }
        }
 
        /// <summary>
        /// Gets or sets the initial rotational velocity, in radians
        /// per millisecond.
        /// </summary>
        /// <remarks>
        /// <para>
        /// The default value for this property is <strong>NaN</strong>. 
        /// Leaving this property unchanged from the default or setting this property to zero (0) 
        /// will disable rotational inertia.
        /// </para>
        /// <para>
        /// This property cannot be set while the inertia processor is running; 
        /// otherwise, an exception is thrown.
        /// </para>
        /// </remarks>
        public float InitialVelocity
        {
            get { return this.initialVelocity; }
            set
            {
                Validations.CheckFinite(value, initialVelocityName);
                ProtectedChangeProperty(
                    () => value == this.initialVelocity,
                    () => this.initialVelocity = value,
                    initialVelocityName);
            }
        }
 
        /// <summary>
        /// This is called when the inertia processor is about to start processing.
        /// It checks to make sure that the behavior is in a valid state. There are
        /// two possible valid states:
        /// 
        /// 1. Initial velocity is NaN, in which case rotation inertia will not
        ///    occur. Desired deceleration and rotation values are ignored.
        /// 
        /// 2. Initial velocity is set to something other than NaN, which means
        ///    that rotation inertia will occur. In this case, either the
        ///    desired deceleration or rotation values must be set.
        /// </summary>
        internal void CheckValid()
        {
            if (float.IsNaN(this.initialVelocity))
            {
                // Velocity is unspecified, so no inertia will occur. This is
                // a valid state.
                return;
            }
 
            if (float.IsNaN(this.desiredDeceleration) && float.IsNaN(this.desiredRotation))
            {
                throw Exceptions.InertiaParametersUnspecified2(
                    SubpropertyName(desiredDecelerationName),
                    SubpropertyName(desiredRotationName));
            }
        }
 
        private static string SubpropertyName(string paramName)
        {
            return "RotationBehavior." + paramName;
        }
    }
}