//------------------------------------------------------------------------------- // // 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)); }
/// <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); }
/// <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); } }
/// <summary> /// UpdateTransform /// Called by: EditingCoordinator.InvalidateBehaviorCursor /// </summary> public void UpdateTransform() { if (!EditingCoordinator.IsTransformValid(this)) { OnTransformChanged(); } }
//------------------------------------------------------------------------------- // // 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); } }
/// <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(); }
/// <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); }
/// <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); } }
//------------------------------------------------------------------------------- // // 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; }
//------------------------------------------------------------------------------- // // 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; } }
//------------------------------------------------------------------------------- // // 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); } }
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); } } }
/// <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); } }
// Token: 0x06006D62 RID: 28002 RVA: 0x001F66C8 File Offset: 0x001F48C8 internal EraserBehavior(EditingCoordinator editingCoordinator, InkCanvas inkCanvas) : base(editingCoordinator, inkCanvas) { }
//------------------------------------------------------------------------------- // // Constructors // //------------------------------------------------------------------------------- #region Constructors internal InkCollectionBehavior(EditingCoordinator editingCoordinator, InkCanvas inkCanvas) : base(editingCoordinator, inkCanvas) { _stylusPoints = null; _userInitiated = false; }
/// <summary> /// Unload the dynamic behavior. The method should be only called from: /// SelectionEditingBehavior /// LassoSelectionBehavior /// </summary> protected void SelfDeactivate() { EditingCoordinator.DeactivateDynamicBehavior(); }
//------------------------------------------------------------------------------- // // 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; } }
//------------------------------------------------------------------------------- // // Constructors // //------------------------------------------------------------------------------- #region Constructors /// <summary> /// Constructor /// </summary> /// <param name="editingCoordinator"></param> /// <param name="inkCanvas"></param> internal StylusEditingBehavior(EditingCoordinator editingCoordinator, InkCanvas inkCanvas) : base(editingCoordinator, inkCanvas) { }
//------------------------------------------------------------------------------- // // Constructors // //------------------------------------------------------------------------------- #region Constructors /// <summary> /// SelectionEditor constructor /// </summary> internal SelectionEditor(EditingCoordinator editingCoordinator, InkCanvas inkCanvas) : base (editingCoordinator, inkCanvas) { }
/// <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); }
//------------------------------------------------------------------------------- // // Constructors // //------------------------------------------------------------------------------- #region Constructors internal LassoSelectionBehavior(EditingCoordinator editingCoordinator, InkCanvas inkCanvas) : base(editingCoordinator, inkCanvas) { }
//------------------------------------------------------------------------------- // // 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; } }