| File: System\Windows\Ink\GestureRecognizer.cs | Web Access |
| Project: src\wpf\src\Microsoft.DotNet.Wpf\src\PresentationCore\PresentationCore.csproj (PresentationCore) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using MS.Internal.Ink.GestureRecognition; using System.Collections.ObjectModel; namespace System.Windows.Ink { /// <summary> /// Performs gesture recognition on a StrokeCollection /// </summary> /// <remarks> /// No finalizer is defined because all unmanaged resources are wrapped in SafeHandle's /// NOTE: this class provides the public APIs that call into unmanaged code to perform /// recognition. There are two inputs that are accepted: /// ApplicationGesture[] and StrokeCollection. /// This class verifies the ApplicationGesture[] and StrokeCollection / Stroke are validated. /// </remarks> public sealed class GestureRecognizer : DependencyObject, IDisposable { //------------------------------------------------------------------------------- // // Constructors // //------------------------------------------------------------------------------- #region Constructors /// <summary> /// The default constructor which enables all the application gestures. /// </summary> public GestureRecognizer() : this ( new ApplicationGesture[] { ApplicationGesture.AllGestures } ) { } /// <summary> /// The constructor which take an array of the enabled application gestures. /// </summary> /// <param name="enabledApplicationGestures"></param> public GestureRecognizer(IEnumerable<ApplicationGesture> enabledApplicationGestures) { _nativeRecognizer = NativeRecognizer.CreateInstance(); if (_nativeRecognizer == null) { //just verify the gestures NativeRecognizer.GetApplicationGestureArrayAndVerify(enabledApplicationGestures); } else { // // we only set this if _nativeRecognizer is non null // (available) because there is no way to use this state // otherwise. // SetEnabledGestures(enabledApplicationGestures); } } #endregion Constructors //------------------------------------------------------------------------------- // // Public Methods // //------------------------------------------------------------------------------- #region Public Methods /// <summary> /// Set the enabled gestures /// </summary> /// <param name="applicationGestures"></param> /// <remarks> /// We wrap the System.Runtime.InteropServices.COMException with a more specific one /// /// Do wrap specific exceptions in a more descriptive exception when appropriate. /// public Int32 GetInt(Int32[] array, Int32 index){ /// try{ /// return array[index]; /// }catch(IndexOutOfRangeException e){ /// throw new ArgumentOutOfRangeException( /// Parameter index is out of range.); /// } /// } /// /// </remarks> public void SetEnabledGestures(IEnumerable<ApplicationGesture> applicationGestures) { VerifyAccess(); VerifyDisposed(); VerifyRecognizerAvailable(); //don't verfify the gestures, NativeRecognizer.SetEnabledGestures does it // since it is the TAS boundary // // we don't wrap the COM exceptions generated from the Recognizer // with our own exception // ApplicationGesture[] enabledGestures = _nativeRecognizer.SetEnabledGestures(applicationGestures); //only update the state when SetEnabledGestures succeeds (since it verifies the array) _enabledGestures = enabledGestures; } /// <summary> /// Get the enabled gestures /// </summary> /// <returns></returns> public ReadOnlyCollection<ApplicationGesture> GetEnabledGestures() { VerifyAccess(); VerifyDisposed(); VerifyRecognizerAvailable(); //can be null if the call to SetEnabledGestures failed if (_enabledGestures == null) { _enabledGestures = Array.Empty<ApplicationGesture>(); } return new ReadOnlyCollection<ApplicationGesture>(_enabledGestures); } /// <summary> /// Performs gesture recognition on the StrokeCollection if a gesture recognizer /// is present and installed on the system. If not, this method throws an InvalidOperationException. /// To determine if this method will throw an exception, only call this method if /// the RecognizerAvailable property returns true. /// /// </summary> /// <param name="strokes">The StrokeCollection to perform gesture recognition on</param> /// <returns></returns> /// <remarks>Callers must have UnmanagedCode permission to call this API.</remarks> public ReadOnlyCollection<GestureRecognitionResult> Recognize(StrokeCollection strokes) { return RecognizeImpl(strokes); } /// <summary> /// Performs gesture recognition on the StrokeCollection if a gesture recognizer /// is present and installed on the system. If not, this method throws an InvalidOperationException. /// To determine if this method will throw an exception, only call this method if /// the RecognizerAvailable property returns true. /// </summary> /// <param name="strokes">The StrokeCollection to perform gesture recognition on</param> /// <returns></returns> // Built into Core, also used by Framework. internal ReadOnlyCollection<GestureRecognitionResult> CriticalRecognize(StrokeCollection strokes) { return RecognizeImpl(strokes); } /// <summary> /// Performs gesture recognition on the StrokeCollection if a gesture recognizer /// is present and installed on the system. /// </summary> /// <param name="strokes">The StrokeCollection to perform gesture recognition on</param> /// <returns></returns> private ReadOnlyCollection<GestureRecognitionResult> RecognizeImpl(StrokeCollection strokes) { ArgumentNullException.ThrowIfNull(strokes); if (strokes.Count > 2) { throw new ArgumentException(SR.StrokeCollectionCountTooBig, nameof(strokes)); } VerifyAccess(); VerifyDisposed(); VerifyRecognizerAvailable(); return new ReadOnlyCollection<GestureRecognitionResult>(_nativeRecognizer.Recognize(strokes)); } #endregion Public Methods //------------------------------------------------------------------------------- // // Public Properties // //------------------------------------------------------------------------------- #region Public Properties /// <summary> /// Indicates if a GestureRecognizer is present and installed on the system. /// </summary> public bool IsRecognizerAvailable { get { VerifyAccess(); VerifyDisposed(); if (_nativeRecognizer == null) { return false; } return true; } } #endregion Public Properties //------------------------------------------------------------------------------- // // IDisposable // //------------------------------------------------------------------------------- #region IDisposable /// <summary> /// Dispose this GestureRecognizer /// </summary> public void Dispose() { VerifyAccess(); // A simple pattern of the dispose implementation. // There is no finalizer since the SafeHandle in the NativeRecognizer will release the context properly. if ( _disposed ) { return; } // // Since the constructor might create a null _nativeRecognizer, // here we have to make sure we do have some thing to dispose. // Otherwise just no-op. _nativeRecognizer?.Dispose(); _nativeRecognizer = null; _disposed = true; } #endregion IDisposable //------------------------------------------------------------------------------- // // Private Methods // //------------------------------------------------------------------------------- #region Private Methods //verify that there is a recognizer available, throw if not private void VerifyRecognizerAvailable() { if (_nativeRecognizer == null) { throw new InvalidOperationException(SR.GestureRecognizerNotAvailable); } } // Verify whether this object has been disposed. private void VerifyDisposed() { ObjectDisposedException.ThrowIf(_disposed, typeof(GestureRecognizer)); } #endregion Private Methods //------------------------------------------------------------------------------- // // Private Fields // //------------------------------------------------------------------------------- #region Private Fields private ApplicationGesture[] _enabledGestures; private NativeRecognizer _nativeRecognizer; private bool _disposed; #endregion Private Fields } }