Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / MS / Internal / Ink / EraserBehavior.cs / 1305600 / EraserBehavior.cs
//---------------------------------------------------------------------------- // // File: EraserBehavior.cs // // Description: // ErasingBehavior for Ink // Features: // // History: // 3/15/2003 samgeo: Created // // Copyright (C) 2003 by Microsoft Corporation. All rights reserved. // //--------------------------------------------------------------------------- using System; using System.ComponentModel; using System.ComponentModel.Design; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Windows.Input; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Ink; using System.Windows.Interop; using System.Windows.Navigation; using System.Windows.Media; using Swi = System.Windows.Ink; namespace MS.Internal.Ink { ////// Eraser Behavior /// internal sealed class EraserBehavior : StylusEditingBehavior { //------------------------------------------------------------------------------- // // Constructors // //------------------------------------------------------------------------------- #region Constructors internal EraserBehavior(EditingCoordinator editingCoordinator, InkCanvas inkCanvas) : base(editingCoordinator, inkCanvas) { } #endregion Constructors //-------------------------------------------------------------------------------- // // Protected Methods // //------------------------------------------------------------------------------- #region Protected Methods ////// 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. /// /// 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; } } 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); } } } ////// StylusInputBegin /// /// stylusPoints /// true if the source eventArgs.UserInitiated flag was set to true 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); } } ////// StylusInputContinue /// /// stylusPoints /// true if the source eventArgs.UserInitiated flag was set to true protected override void StylusInputContinue(StylusPointCollection stylusPoints, bool userInitiated) { _stylusPoints.Add(stylusPoints); _incrementalStrokeHitTester.AddPoints(stylusPoints); } ////// StylusInputEnd /// /// commit protected override void StylusInputEnd(bool commit) { if ( InkCanvasEditingMode.EraseByPoint == _cachedEraseMode ) { _incrementalStrokeHitTester.StrokeHit-= new StrokeHitEventHandler(OnPointEraseResultChanged); } else { //we're in stroke hit test mode _incrementalStrokeHitTester.StrokeHit -= new StrokeHitEventHandler(OnStrokeEraseResultChanged); } _stylusPoints = null; // NTRAID#T2-26868-2004/11/1-WAYNEZEN, // Don't forget ending the current incremental hit testing. _incrementalStrokeHitTester.EndHitTesting(); _incrementalStrokeHitTester = null; } ////// Get eraser cursor. /// ///protected override Cursor GetCurrentCursor() { if ( InkCanvasEditingMode.EraseByPoint == _cachedEraseMode ) { if ( _cachedPointEraserCursor == null ) { _cachedStylusShape = InkCanvas.EraserShape; // NTRAID-WINDOWS#1430638-2006/01/04-WAYNEZEN, // The eraser cursor should respect the InkCanvas' Transform properties as the pen tip. Matrix xf = GetElementTransformMatrix(); if ( !xf.IsIdentity ) { // Zero the offsets if the element's transform in invertable. // Otherwise fallback the matrix to the identity. if ( xf.HasInverse ) { xf.OffsetX = 0; xf.OffsetY = 0; } else { xf = Matrix.Identity; } } _cachedPointEraserCursor = PenCursorManager.GetPointEraserCursor(_cachedStylusShape, xf); } return _cachedPointEraserCursor; } else { return PenCursorManager.GetStrokeEraserCursor(); } } /// /// ApplyTransformToCursor /// protected override void OnTransformChanged() { // Reset the cached point eraser cursor. ResetCachedPointEraserCursor(); } #endregion Protected Methods //-------------------------------------------------------------------------------- // // Private Methods // //-------------------------------------------------------------------------------- #region Private Methods ////// Reset the cached point eraser cursor. /// private void ResetCachedPointEraserCursor() { _cachedPointEraserCursor = null; _cachedStylusShape = null; } ////// /// /// /// private void OnStrokeEraseResultChanged(object sender, StrokeHitEventArgs e) { Debug.Assert(null != e.HitStroke); bool fSucceeded = false; // The below code calls out StrokeErasing or StrokeErased event. // The out-side code could throw exception. // We use try/finally block to protect our status. try { InkCanvasStrokeErasingEventArgs args = new InkCanvasStrokeErasingEventArgs(e.HitStroke); this.InkCanvas.RaiseStrokeErasing(args); if ( !args.Cancel ) { // Erase only if the event wasn't cancelled InkCanvas.Strokes.Remove(e.HitStroke); this.InkCanvas.RaiseInkErased(); } fSucceeded = true; } finally { if ( !fSucceeded ) { // Abort the editing. Commit(false); } } } ////// /// /// /// private void OnPointEraseResultChanged(object sender, StrokeHitEventArgs e) { Debug.Assert(null != e.HitStroke, "e.HitStroke cannot be null"); bool fSucceeded = false; // The below code might call out StrokeErasing or StrokeErased event. // The out-side code could throw exception. // We use try/finally block to protect our status. try { InkCanvasStrokeErasingEventArgs args = new InkCanvasStrokeErasingEventArgs(e.HitStroke); this.InkCanvas.RaiseStrokeErasing(args); if ( !args.Cancel ) { // Erase only if the event wasn't cancelled StrokeCollection eraseResult = e.GetPointEraseResults(); Debug.Assert(eraseResult != null, "eraseResult cannot be null"); StrokeCollection strokesToReplace = new StrokeCollection(); strokesToReplace.Add(e.HitStroke); try { // replace or remove the stroke if (eraseResult.Count > 0) { this.InkCanvas.Strokes.Replace(strokesToReplace, eraseResult); } else { this.InkCanvas.Strokes.Remove(strokesToReplace); } } catch (ArgumentException ex) { //this can happen if someone sits in an event handler //for StrokeErasing and removes the stroke. //this to harden against failure here. if (!ex.Data.Contains("System.Windows.Ink.StrokeCollection")) { //System.Windows.Ink.StrokeCollection didn't throw this, //we need to just throw the original exception throw; } } //raise ink erased this.InkCanvas.RaiseInkErased(); } fSucceeded = true; } finally { if ( !fSucceeded ) { // Abort the editing. Commit(false); } } } #endregion Private Methods //------------------------------------------------------------------------------- // // Private Fields // //-------------------------------------------------------------------------------- #region Private Fields private InkCanvasEditingMode _cachedEraseMode; private IncrementalStrokeHitTester _incrementalStrokeHitTester; private Cursor _cachedPointEraserCursor; private StylusShape _cachedStylusShape; private StylusPointCollection _stylusPoints = null; #endregion Private Fields } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- OdbcStatementHandle.cs
- DataPagerFieldItem.cs
- ImportCatalogPart.cs
- unitconverter.cs
- BrowserCapabilitiesCodeGenerator.cs
- ObjectSecurity.cs
- SetStoryboardSpeedRatio.cs
- UnsafeNativeMethodsMilCoreApi.cs
- OleDbParameterCollection.cs
- UriWriter.cs
- ArgumentNullException.cs
- HelpProvider.cs
- ByteStreamGeometryContext.cs
- OpCodes.cs
- EditorZoneBase.cs
- Clause.cs
- SmiMetaDataProperty.cs
- CorrelationService.cs
- VirtualizingStackPanel.cs
- VisualTreeUtils.cs
- SparseMemoryStream.cs
- NativeMethods.cs
- ConfigurationSettings.cs
- LogicalTreeHelper.cs
- HostProtectionException.cs
- PtsPage.cs
- TableCellCollection.cs
- SecurityTokenParameters.cs
- CommentAction.cs
- SqlConnection.cs
- XmlObjectSerializerWriteContextComplex.cs
- FixedHyperLink.cs
- XmlSerializerNamespaces.cs
- TdsValueSetter.cs
- UserCancellationException.cs
- JsonFormatWriterGenerator.cs
- ComNativeDescriptor.cs
- DataGridTextBox.cs
- HtmlElementEventArgs.cs
- ImageBrush.cs
- ConnectionStringSettingsCollection.cs
- TreeViewAutomationPeer.cs
- SizeLimitedCache.cs
- TableLayoutStyleCollection.cs
- ArrayElementGridEntry.cs
- MimeWriter.cs
- XmlDataSourceNodeDescriptor.cs
- MediaEntryAttribute.cs
- CalendarAutoFormat.cs
- BorderGapMaskConverter.cs
- DataGrid.cs
- GenericEnumerator.cs
- BinaryObjectInfo.cs
- SecUtil.cs
- DataSourceControl.cs
- SoundPlayer.cs
- WsiProfilesElement.cs
- BufferedGraphicsManager.cs
- DSASignatureFormatter.cs
- FusionWrap.cs
- DataGridViewSelectedRowCollection.cs
- HuffModule.cs
- PageFunction.cs
- XpsStructure.cs
- ExpressionLink.cs
- SafeFindHandle.cs
- BaseResourcesBuildProvider.cs
- GrammarBuilder.cs
- SafeRegistryHandle.cs
- ThreadExceptionEvent.cs
- BitmapCodecInfoInternal.cs
- OleDbConnectionInternal.cs
- Adorner.cs
- LayeredChannelListener.cs
- PermissionToken.cs
- XmlSchemaSimpleTypeRestriction.cs
- VisualTreeUtils.cs
- PersonalizationState.cs
- ConfigXmlAttribute.cs
- References.cs
- ProtocolsConfigurationEntry.cs
- FileSystemInfo.cs
- SecurityPolicySection.cs
- XpsFixedPageReaderWriter.cs
- KeyTime.cs
- CompiledQueryCacheEntry.cs
- QueryOperationResponseOfT.cs
- CacheOutputQuery.cs
- ISSmlParser.cs
- EntityDataSourceReferenceGroup.cs
- XmlnsDictionary.cs
- MessageFilterException.cs
- XmlTextEncoder.cs
- DataServiceProviderMethods.cs
- DeploymentSection.cs
- FrameworkName.cs
- ArgIterator.cs
- DesignerCategoryAttribute.cs
- EqualityComparer.cs
- SafeNativeMethods.cs