コード例 #1
0
        //-------------------------------------------------------------------------------
        //
        // Protected Methods
        //
        //-------------------------------------------------------------------------------

        #region Protected Methods

        /// <summary>
        ///     Attaching to the element, we get attached in StylusDown
        /// </summary>
        protected override void OnActivate()
        {
            _actionStarted = false;

            // Capture the mouse.
            InitializeCapture();

            // Hittest for the grab handle
            MouseDevice mouse = Mouse.PrimaryDevice;

            _hitResult = InkCanvas.SelectionAdorner.SelectionHandleHitTest(
                mouse.GetPosition((IInputElement)(InkCanvas.SelectionAdorner)));

            Debug.Assert(_hitResult != InkCanvasSelectionHitResult.None);
            EditingCoordinator.InvalidateBehaviorCursor(this);

            // Get the current selection bounds.
            _selectionRect = InkCanvas.GetSelectionBounds( );

            // Set the initial tracking position and rectangle
            _previousLocation = mouse.GetPosition(InkCanvas.SelectionAdorner);
            _previousRect     = _selectionRect;

            // Start the feedback rubber band.
            InkCanvas.InkCanvasSelection.StartFeedbackAdorner(_selectionRect, _hitResult);

            // Add handlers to the mouse events.
            InkCanvas.SelectionAdorner.AddHandler(Mouse.MouseUpEvent, new MouseButtonEventHandler(OnMouseUp));
            InkCanvas.SelectionAdorner.AddHandler(Mouse.MouseMoveEvent, new MouseEventHandler(OnMouseMove));
            InkCanvas.SelectionAdorner.AddHandler(UIElement.LostMouseCaptureEvent,
                                                  new MouseEventHandler(OnLostMouseCapture));
        }
コード例 #2
0
        /// <summary>
        /// StylusInputBegin
        /// </summary>
        /// <param name="stylusPoints">stylusPoints</param>
        /// <param name="userInitiated">true if the source eventArgs.UserInitiated flag was set to true</param>
        protected override void StylusInputBegin(StylusPointCollection stylusPoints, bool userInitiated)
        {
            _userInitiated = false;

            //we only initialize to true if the first stylusPoints were user initiated
            if (userInitiated)
            {
                _userInitiated = true;
            }

            _stylusPoints = new StylusPointCollection(stylusPoints.Description, 100);
            _stylusPoints.Add(stylusPoints);

            _strokeDrawingAttributes = this.InkCanvas.DefaultDrawingAttributes.Clone();

            // Reset the dynamic renderer if it's been flagged.
            if (_resetDynamicRenderer)
            {
                InputDevice inputDevice = EditingCoordinator.GetInputDeviceForReset();
                if (InkCanvas.InternalDynamicRenderer != null && inputDevice != null)
                {
                    StylusDevice stylusDevice = inputDevice as StylusDevice;
                    // If the input device is MouseDevice, null will be passed in Reset Method.
                    InkCanvas.InternalDynamicRenderer.Reset(stylusDevice, stylusPoints);
                }

                _resetDynamicRenderer = false;
            }

            // Call InvalidateBehaviorCursor at the end of the routine. The method will cause an external event fired.
            // So it should be invoked after we set up our states.
            EditingCoordinator.InvalidateBehaviorCursor(this);
        }
コード例 #3
0
        /// <summary>
        /// StylusInputEnd
        /// </summary>
        /// <param name="commit">commit</param>
        protected override void StylusInputEnd(bool commit)
        {
            // The follow code raises Gesture and/or StrokeCollected event
            // The out-side code could throw exception in the their handlers. We use try/finally block to protect our status.
            try
            {
                if (commit)
                {
                    //
                    // It's possible that the input may end up without any StylusPoint being collected since the behavior can be deactivated by
                    // the user code in the any event handler.
                    if (_stylusPoints != null)
                    {
                        Debug.Assert(_strokeDrawingAttributes != null, "_strokeDrawingAttributes can not be null, did we not see a down?");

                        Stroke stroke =
                            new Stroke(_stylusPoints, _strokeDrawingAttributes);

                        //we don't add the stroke to the InkCanvas stroke collection until RaiseStrokeCollected
                        //since this might be a gesture and in some modes, gestures don't get added
                        InkCanvasStrokeCollectedEventArgs argsStroke = new InkCanvasStrokeCollectedEventArgs(stroke);
                        InkCanvas.RaiseGestureOrStrokeCollected(argsStroke, _userInitiated);
                    }
                }
            }
            finally
            {
                _stylusPoints            = null;
                _strokeDrawingAttributes = null;
                _userInitiated           = false;
                EditingCoordinator.InvalidateBehaviorCursor(this);
            }
        }
コード例 #4
0
 /// <summary>
 /// UpdateTransform
 ///     Called by: EditingCoordinator.InvalidateBehaviorCursor
 /// </summary>
 public void UpdateTransform()
 {
     if (!EditingCoordinator.IsTransformValid(this))
     {
         OnTransformChanged();
     }
 }
コード例 #5
0
        //-------------------------------------------------------------------------------
        //
        // Private Methods
        //
        //-------------------------------------------------------------------------------

        #region Private Methods


        /// <summary>
        /// SelectionAdorner MouseButtonDown
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void OnAdornerMouseButtonDownEvent(object sender, MouseButtonEventArgs args)
        {
            // If the ButtonDown is raised by RightMouse, we should just bail out.
            if ( (args.StylusDevice == null && args.LeftButton != MouseButtonState.Pressed) )
            {
                return;
            }

            Point pointOnSelectionAdorner = args.GetPosition(InkCanvas.SelectionAdorner);

            InkCanvasSelectionHitResult hitResult = InkCanvasSelectionHitResult.None;

            // Check if we should start resizing/moving
            hitResult = HitTestOnSelectionAdorner(pointOnSelectionAdorner);
            if ( hitResult != InkCanvasSelectionHitResult.None )
            {
                // We always use MouseDevice for the selection editing.
                EditingCoordinator.ActivateDynamicBehavior(EditingCoordinator.SelectionEditingBehavior, args.Device);
            }
            else
            {
                //
                //push selection and we're done
                //
                // If the current captured device is Stylus, we should activate the LassoSelectionBehavior with
                // the Stylus. Otherwise, use mouse.
                EditingCoordinator.ActivateDynamicBehavior(EditingCoordinator.LassoSelectionBehavior,
                    args.StylusDevice != null ? args.StylusDevice : args.Device);
            }
        }
コード例 #6
0
        /// <summary>
        /// An internal method which should be called from:
        ///     EditingCoordinator.PushEditingBehavior
        ///     EditingCoordinator.PopEditingBehavior
        /// The mehod's called when the behavior switching occurs.
        /// </summary>
        public void Deactivate()
        {
            // Debug verification which will never be compiled into release bits.
            EditingCoordinator.DebugCheckActiveBehavior(this);

            // Invoke the virtual OnDeactivate method.
            OnDeactivate();
        }
コード例 #7
0
        /// <summary>
        /// An internal method which should be called from:
        ///     EditingCoordinator.OnInkCanvasStylusUp
        ///     EditingCoordinator.OnInkCanvasLostStylusCapture
        ///     EditingCoordinator.UpdateEditingState
        /// The mehod's called when the current editing state is committed or discarded.
        /// </summary>
        /// <param name="commit">A flag which indicates either editing is committed or discarded</param>
        public void Commit(bool commit)
        {
            // Debug verification which will never be compiled into release bits.
            EditingCoordinator.DebugCheckActiveBehavior(this);

            // Invoke the virtual OnCommit method.
            OnCommit(commit);
        }
コード例 #8
0
 /// <summary>
 /// This method updates the cursor when the mouse is hovering ont the selection adorner.
 /// It is called from
 ///  OnAdornerMouseLeaveEvent
 ///  OnAdornerMouseEvent
 /// </summary>
 /// <param name="hitPoint">the handle is being hit</param>
 private void UpdateSelectionCursor(Point hitPoint)
 {
     InkCanvasSelectionHitResult hitResult = HitTestOnSelectionAdorner(hitPoint);
     if ( _hitResult != hitResult )
     {
         // Keep the current handle
         _hitResult = hitResult;
         EditingCoordinator.InvalidateBehaviorCursor(this);
     }
 }
コード例 #9
0
        //-------------------------------------------------------------------------------
        //
        // Constructors
        //
        //-------------------------------------------------------------------------------

        #region Constructors

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="editingCoordinator">EditngCoordinator instance</param>
        /// <param name="inkCanvas">InkCanvas instance</param>
        internal EditingBehavior(EditingCoordinator editingCoordinator, InkCanvas inkCanvas)
        {
            if (inkCanvas == null)
            {
                throw new ArgumentNullException("inkCanvas");
            }
            if (editingCoordinator == null)
            {
                throw new ArgumentNullException("editingCoordinator");
            }
            _inkCanvas          = inkCanvas;
            _editingCoordinator = editingCoordinator;
        }
コード例 #10
0
        //-------------------------------------------------------------------------------
        //
        // Protected Methods
        //
        //-------------------------------------------------------------------------------

        #region Protected Methods

        /// <summary>
        /// Overrides SwitchToMode as the following expectations
        /// 31. From Select To InkAndGesture
        ///     Lasso is discarded. After mode change ink is being collected, gesture event fires. If its not a gesture, StrokeCollected event fires.
        /// 32. From Select To GestureOnly
        ///     Lasso is discarded. After mode change ink is being collected. On StylusUp gesture event fires. Stroke gets removed on StylusUp even if its not a gesture.
        /// 33. From Select To EraseByPoint
        ///     Lasso is discarded. PointErasing is performed after changing the mode.
        /// 34. From Select To EraseByStroke
        ///     Lasso is discarded. StrokeErasing is performed after changing the mode.
        /// 35. From Select To Ink
        ///     Ink collection starts when changing the mode.
        /// 36. From Select To None
        ///     Nothing gets selected.
        /// </summary>
        /// <param name="mode"></param>
        protected override void OnSwitchToMode(InkCanvasEditingMode mode)
        {
            Debug.Assert(EditingCoordinator.IsInMidStroke, "SwitchToMode should only be called in a mid-stroke");

            switch (mode)
            {
            case InkCanvasEditingMode.Ink:
            case InkCanvasEditingMode.InkAndGesture:
            case InkCanvasEditingMode.GestureOnly:
            {
                // Discard the lasso
                Commit(false);

                // Change the mode. The dynamic renderer will be reset automatically.
                EditingCoordinator.ChangeStylusEditingMode(this, mode);
                break;
            }

            case InkCanvasEditingMode.EraseByPoint:
            case InkCanvasEditingMode.EraseByStroke:
            {
                // Discard the lasso
                Commit(false);

                // Change the mode
                EditingCoordinator.ChangeStylusEditingMode(this, mode);

                break;
            }

            case InkCanvasEditingMode.Select:
            {
                Debug.Assert(false, "Cannot switch from Select to Select in mid-stroke");
                break;
            }

            case InkCanvasEditingMode.None:
            {
                // Discard the lasso.
                Commit(false);

                // Change to the None mode
                EditingCoordinator.ChangeStylusEditingMode(this, mode);
                break;
            }

            default:
                Debug.Assert(false, "Unknown InkCanvasEditingMode!");
                break;
            }
        }
コード例 #11
0
ファイル: StylusEditingBehavior.cs プロジェクト: sososu/wpf
        //-------------------------------------------------------------------------------
        //
        // IStylusEditing Interface
        //
        //-------------------------------------------------------------------------------

        #region IStylusEditing Interface

        /// <summary>
        /// IStylusEditing.AddStylusPoints
        /// </summary>
        /// <param name="stylusPoints">stylusPoints</param>
        /// <param name="userInitiated">true if the eventArgs source had UserInitiated set to true</param>
        void IStylusEditing.AddStylusPoints(StylusPointCollection stylusPoints, bool userInitiated)
        {
            EditingCoordinator.DebugCheckActiveBehavior(this);

            // Don't process if SwitchToMode is called during the mid-stroke.
            if (_disableInput)
            {
                return;
            }

            if (!EditingCoordinator.UserIsEditing)
            {
                EditingCoordinator.UserIsEditing = true;
                StylusInputBegin(stylusPoints, userInitiated);
            }
            else
            {
                StylusInputContinue(stylusPoints, userInitiated);
            }
        }
コード例 #12
0
        protected override void OnActivate()
        {
            base.OnActivate();
            InkCanvasEditingMode newEraseMode = EditingCoordinator.ActiveEditingMode;

            Debug.Assert(newEraseMode == InkCanvasEditingMode.EraseByPoint ||
                         newEraseMode == InkCanvasEditingMode.EraseByStroke);

            // Check whether we have to update cursor.
            if (_cachedEraseMode != newEraseMode)
            {
                // EraseMode is changed
                _cachedEraseMode = newEraseMode;
                EditingCoordinator.InvalidateBehaviorCursor(this);
            }
            else if (newEraseMode == InkCanvasEditingMode.EraseByPoint)
            {
                // Invalidate the PointEraser if we don't have the cache yet.
                bool isPointEraserCursorValid = _cachedStylusShape != null;

                // NTRAID:WINDOWSOS#1673398-2006/05/23-WAYNEZEN,
                // If the cached EraserShape is different from the current EraserShape, we shoud just reset the cache.
                // The new cursor will be generated when it's needed later.
                if (isPointEraserCursorValid &&
                    (_cachedStylusShape.Width != InkCanvas.EraserShape.Width ||
                     _cachedStylusShape.Height != InkCanvas.EraserShape.Height ||
                     _cachedStylusShape.Rotation != InkCanvas.EraserShape.Rotation ||
                     _cachedStylusShape.GetType() != InkCanvas.EraserShape.GetType()))
                {
                    Debug.Assert(_cachedPointEraserCursor != null, "_cachedPointEraserCursor shouldn't be null.");
                    ResetCachedPointEraserCursor();
                    isPointEraserCursorValid = false;
                }

                if (!isPointEraserCursorValid)
                {
                    // EraserShape is changed when the new mode is EraseByPoint
                    EditingCoordinator.InvalidateBehaviorCursor(this);
                }
            }
        }
コード例 #13
0
        /// <summary>
        /// StylusInputBegin
        /// </summary>
        /// <param name="stylusPoints">stylusPoints</param>
        /// <param name="userInitiated">true if the source eventArgs.UserInitiated flag was set to true</param>
        protected override void StylusInputBegin(StylusPointCollection stylusPoints, bool userInitiated)
        {
            //
            // get a disposable dynamic hit-tester and add event handler
            //
            _incrementalStrokeHitTester =
                this.InkCanvas.Strokes.GetIncrementalStrokeHitTester(this.InkCanvas.EraserShape);


            if (InkCanvasEditingMode.EraseByPoint == _cachedEraseMode)
            {
                _incrementalStrokeHitTester.StrokeHit += new StrokeHitEventHandler(OnPointEraseResultChanged);
            }
            else
            {
                //we're in stroke hit test mode
                _incrementalStrokeHitTester.StrokeHit += new StrokeHitEventHandler(OnStrokeEraseResultChanged);
            }

            _stylusPoints = new StylusPointCollection(stylusPoints.Description, 100);
            _stylusPoints.Add(stylusPoints);

            //
            // start erasing
            //
            _incrementalStrokeHitTester.AddPoints(stylusPoints);

            // NTRAID:WINDOWSOS#1642274-2006/05/10-WAYNEZEN,
            // Since InkCanvas will ignore the animated tranforms when it receives the property changes.
            // So we should update our cursor when the stylus is down if there are animated transforms applied to InkCanvas.
            if (InkCanvasEditingMode.EraseByPoint == _cachedEraseMode)
            {
                // Call InvalidateBehaviorCursor at the end of the routine. The method will cause an external event fired.
                // So it should be invoked after we set up our states.
                EditingCoordinator.InvalidateBehaviorCursor(this);
            }
        }
コード例 #14
0
 // Token: 0x06006D62 RID: 28002 RVA: 0x001F66C8 File Offset: 0x001F48C8
 internal EraserBehavior(EditingCoordinator editingCoordinator, InkCanvas inkCanvas) : base(editingCoordinator, inkCanvas)
 {
 }
コード例 #15
0
        //-------------------------------------------------------------------------------
        //
        // Constructors
        //
        //-------------------------------------------------------------------------------

        #region Constructors

        internal InkCollectionBehavior(EditingCoordinator editingCoordinator, InkCanvas inkCanvas)
            : base(editingCoordinator, inkCanvas)
        {
            _stylusPoints  = null;
            _userInitiated = false;
        }
コード例 #16
0
 /// <summary>
 /// Unload the dynamic behavior. The method should be only called from:
 ///     SelectionEditingBehavior
 ///     LassoSelectionBehavior
 /// </summary>
 protected void SelfDeactivate()
 {
     EditingCoordinator.DeactivateDynamicBehavior();
 }
コード例 #17
0
        //-------------------------------------------------------------------------------
        //
        // Protected Methods
        //
        //-------------------------------------------------------------------------------

        #region Protected Methods

        /// <summary>
        /// Overrides SwitchToMode
        /// As the following expected results
        ///  1. From Ink To InkAndGesture
        ///     Packets between StylusDown and StylusUp are sent to the gesture reco. On StylusUp gesture event fires. If it’s not a gesture, StrokeCollected event fires.
        ///  2. From Ink To GestureOnly
        ///     Packets between StylusDown and StylusUp are send to the gesture reco. On StylusUp gesture event fires. Stroke gets removed on StylusUp even if it’s not a gesture.
        ///  3. From Ink To EraseByPoint
        ///     Stroke is discarded. PointErasing is performed after changing the mode.
        ///  4. From Ink To EraseByStroke
        ///      Stroke is discarded. StrokeErasing is performed after changing the mode.
        ///  5. From Ink To Select
        ///     Stroke is discarded. Lasso is drawn for all packets between StylusDown and StylusUp. Strokes/elements within the lasso will be selected.
        ///  6. From Ink To None
        ///     Stroke is discarded.
        ///  7. From InkAndGesture To Ink
        ///     Stroke is collected for all packets between StylusDown and StylusUp. Gesture event does not fire.
        ///  8. From InkAndGesture To GestureOnly
        ///     Packets between StylusDown and StylusUp are sent to the gesture reco. Stroke gets removed on StylusUp even if it’s not a gesture.
        ///  9. From InkAndGesture To EraseByPoint
        ///     Stroke is discarded. PointErasing is performed after changing the mode, gesture event does not fire.
        /// 10. From InkAndGesture To EraseByStroke
        ///     Stroke is discarded. StrokeErasing is performed after changing the mode, gesture event does not fire.
        /// 11. From InkAndGesture To Select
        ///     Lasso is drawn for all packets between StylusDown and StylusUp. Strokes/elements within the lasso will be selected.
        /// 12. From InkAndGesture To None
        ///     Stroke is discarded, no gesture is recognized.
        /// 13. From GestureOnly To InkAndGesture
        ///     Packets between StylusDown and StylusUp are sent to the gesture reco. On StylusUp gesture event fires. If it’s not a gesture, StrokeCollected event fires.
        /// 14. From GestureOnly To Ink
        ///     Stroke is collected. Gesture event does not fire.
        /// 15. From GestureOnly To EraseByPoint
        ///     Stroke is discarded PointErasing is performed after changing the mode, gesture event does not fire
        /// 16. From GestureOnly To EraseByStroke
        ///     Stroke is discarded. StrokeErasing is performed after changing the mode, gesture event does not fire.
        /// 17. From GestureOnly To Select
        ///     Lasso is drawn for all packets between StylusDown and StylusUp. Strokes/elements within the lasso will be selected.
        /// 18. From GestureOnly To None
        ///     Stroke is discarded. Gesture event does not fire.
        /// </summary>
        /// <param name="mode"></param>
        protected override void OnSwitchToMode(InkCanvasEditingMode mode)
        {
            Debug.Assert(EditingCoordinator.IsInMidStroke, "SwitchToMode should only be called in a mid-stroke");

            switch (mode)
            {
            case InkCanvasEditingMode.Ink:
            case InkCanvasEditingMode.InkAndGesture:
            case InkCanvasEditingMode.GestureOnly:
            {
                // We are under one of those Ink modes now. Nothing to change here except raising the mode change event.
                InkCanvas.RaiseActiveEditingModeChanged(new RoutedEventArgs(InkCanvas.ActiveEditingModeChangedEvent, InkCanvas));
                break;
            }

            case InkCanvasEditingMode.EraseByPoint:
            case InkCanvasEditingMode.EraseByStroke:
            {
                // Discard the collected ink.
                Commit(false);

                // Change the Erase mode
                EditingCoordinator.ChangeStylusEditingMode(this, mode);
                break;
            }

            case InkCanvasEditingMode.Select:
            {
                // Make a copy of the current cached points.
                StylusPointCollection cachedPoints = _stylusPoints != null?
                                                     _stylusPoints.Clone() : null;

                // Discard the collected ink.
                Commit(false);

                // Change the Select mode
                IStylusEditing newBehavior = EditingCoordinator.ChangeStylusEditingMode(this, mode);

                if (cachedPoints != null
                    // NOTICE-2006/04/27-WAYNEZEN,
                    // EditingCoordinator.ChangeStylusEditingMode raises external event.
                    // The user code could take any arbitrary action for instance calling InkCanvas.ReleaseMouseCapture()
                    // So there is no guarantee that we could receive the newBehavior.
                    && newBehavior != null)
                {
                    // Now add the previous points to the lasso behavior
                    // The SelectionBehavior doesn't check userInitiated, pass false
                    // even if our _userInitiated flag is true
                    newBehavior.AddStylusPoints(cachedPoints, false /*userInitiated*/);
                }

                break;
            }

            case InkCanvasEditingMode.None:
            {
                // Discard the collected ink.
                Commit(false);

                // Change to the None mode
                EditingCoordinator.ChangeStylusEditingMode(this, mode);
                break;
            }

            default:
                Debug.Assert(false, "Unknown InkCanvasEditingMode!");
                break;
            }
        }
コード例 #18
0
ファイル: StylusEditingBehavior.cs プロジェクト: sososu/wpf
        //-------------------------------------------------------------------------------
        //
        // Constructors
        //
        //-------------------------------------------------------------------------------

        #region Constructors

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="editingCoordinator"></param>
        /// <param name="inkCanvas"></param>
        internal StylusEditingBehavior(EditingCoordinator editingCoordinator, InkCanvas inkCanvas)
            : base(editingCoordinator, inkCanvas)
        {
        }
コード例 #19
0
        //-------------------------------------------------------------------------------
        //
        // Constructors
        //
        //-------------------------------------------------------------------------------

        #region Constructors

        /// <summary>
        /// SelectionEditor constructor
        /// </summary>
        internal SelectionEditor(EditingCoordinator editingCoordinator, InkCanvas inkCanvas) : base (editingCoordinator, inkCanvas)
        {
        }
コード例 #20
0
 /// <summary>
 /// Adorner MouseLeave Handler
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="args"></param>
 private void OnAdornerMouseLeaveEvent(object sender, MouseEventArgs args)
 {
     // We are leaving the adorner, update our cursor.
     EditingCoordinator.InvalidateBehaviorCursor(this);
 }
コード例 #21
0
        //-------------------------------------------------------------------------------
        //
        // Constructors
        //
        //-------------------------------------------------------------------------------

        #region Constructors

        internal LassoSelectionBehavior(EditingCoordinator editingCoordinator, InkCanvas inkCanvas)
            : base(editingCoordinator, inkCanvas)
        {
        }
コード例 #22
0
        //-------------------------------------------------------------------------------
        //
        // Protected Methods
        //
        //-------------------------------------------------------------------------------

        #region Protected Methods

        /// <summary>
        /// Overrides SwitchToMode as the following expectations
        /// 19. From EraseByPoint To InkAndGesture
        ///     After mode change ink is being collected. On StylusUp gesture event fires. If it’s not a gesture, StrokeCollected event fires.
        /// 20. From EraseByPoint To GestureOnly
        ///     After mode change ink is being collected. On StylusUp gesture event fires. Stroke gets removed on StylusUp even if it’s not a gesture.
        /// 21. From EraseByPoint To Ink
        ///     Ink collection starts when changing the mode.
        /// 22. From EraseByPoint To EraseByStroke
        ///     After mode change StrokeErasing is performed.
        /// 23. From EraseByPoint To Select
        ///     Lasso is drawn for all packets between StylusDown and StylusUp. Strokes/elements within the lasso will be selected.
        /// 24. From EraseByPoint To None
        ///     No erasing is performed after mode change.
        /// 25. From EraseByStroke To InkAndGesture
        ///     After mode change ink is being collected. On StylusUp gesture event fires. If it’s not a gesture, StrokeCollected event fires.
        /// 26. From EraseByStroke To GestureOnly
        ///     After mode change ink is being collected. On StylusUp gesture event fires. Stroke gets removed on StylusUp even if it’s not a gesture.
        /// 27. From EraseByStroke To EraseByPoint
        ///     After mode change PointErasing is performed.
        /// 28. From EraseByStroke To Ink
        ///     Ink collection starts when changing the mode.
        /// 29. From EraseByStroke To Select
        ///     Lasso is drawn for all packets between StylusDown and StylusUp. Strokes/elements within the lasso will be selected
        /// 30. From EraseByStroke To None
        ///     No erasing is performed after mode change.
        /// </summary>
        /// <param name="mode"></param>
        protected override void OnSwitchToMode(InkCanvasEditingMode mode)
        {
            Debug.Assert(EditingCoordinator.IsInMidStroke, "SwitchToMode should only be called in a mid-stroke");

            switch (mode)
            {
            case InkCanvasEditingMode.Ink:
            case InkCanvasEditingMode.InkAndGesture:
            case InkCanvasEditingMode.GestureOnly:
            {
                // Commit the current behavior
                Commit(true);

                // Change the mode. The dynamic renderer will be reset automatically.
                EditingCoordinator.ChangeStylusEditingMode(this, mode);
                break;
            }

            case InkCanvasEditingMode.EraseByPoint:
            case InkCanvasEditingMode.EraseByStroke:
            {
                Debug.Assert(_cachedEraseMode != mode);

                // Commit the current behavior
                Commit(true);

                // Change the mode
                EditingCoordinator.ChangeStylusEditingMode(this, mode);

                break;
            }

            case InkCanvasEditingMode.Select:
            {
                // Make a copy of the current cached points.
                StylusPointCollection cachedPoints = _stylusPoints != null?
                                                     _stylusPoints.Clone() : null;

                // Commit the current behavior.
                Commit(true);

                // Change the Select mode
                IStylusEditing newBehavior = EditingCoordinator.ChangeStylusEditingMode(this, mode);

                if (cachedPoints != null
                    // NOTICE-2006/04/27-WAYNEZEN,
                    // EditingCoordinator.ChangeStylusEditingMode raises external event.
                    // The user code could take any arbitrary action for instance calling InkCanvas.ReleaseMouseCapture()
                    // So there is no guarantee that we could receive the newBehavior.
                    && newBehavior != null)
                {
                    // Now add the previous points to the lasso behavior
                    newBehavior.AddStylusPoints(cachedPoints, false /*userInitiated*/);
                }

                break;
            }

            case InkCanvasEditingMode.None:
            {
                // Discard the collected ink.
                Commit(true);

                // Change to the None mode
                EditingCoordinator.ChangeStylusEditingMode(this, mode);
                break;
            }

            default:
                Debug.Assert(false, "Unknown InkCanvasEditingMode!");
                break;
            }
        }