Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / wpf / src / Framework / System / Windows / Controls / InkPresenter.cs / 1 / InkPresenter.cs
//----------------------------------------------------------------------------
//
// File: InkPresenter.cs
//
// Description:
// A rendering element which binds to the strokes data
//
// Features:
//
// History:
// 12/02/2004 waynezen: Created
//
// Copyright (C) 2001 by Microsoft Corporation. All rights reserved.
//
//---------------------------------------------------------------------------
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Media;
using System.Windows.Controls;
using System.Windows.Ink;
using System.Windows.Threading;
using System.Windows.Input;
using MS.Internal.Ink;
using System.Windows.Automation.Peers;
namespace System.Windows.Controls
{
///
/// Renders the specified StrokeCollection data.
///
public class InkPresenter : Decorator
{
//-------------------------------------------------------------------------------
//
// Constructors
//
//-------------------------------------------------------------------------------
#region Constructors
///
/// The constructor of InkPresenter
///
public InkPresenter()
{
// Create the internal Renderer object.
_renderer = new Ink.Renderer();
SetStrokesChangedHandlers(this.Strokes, null);
_contrastCallback = new InkPresenterHighContrastCallback(this);
// Register rti high contrast callback. Then check whether we are under the high contrast already.
HighContrastHelper.RegisterHighContrastCallback(_contrastCallback);
if ( SystemParameters.HighContrast )
{
_contrastCallback.TurnHighContrastOn(SystemColors.WindowTextColor);
}
_constraintSize = Size.Empty;
}
#endregion Constructors
//--------------------------------------------------------------------------------
//
// Public Methods
//
//-------------------------------------------------------------------------------
#region Public Methods
///
/// AttachVisual method
///
/// The stroke visual which needs to be attached
/// The DrawingAttributes of the stroke
public void AttachVisuals(Visual visual, DrawingAttributes drawingAttributes)
{
VerifyAccess();
EnsureRootVisual();
_renderer.AttachIncrementalRendering(visual, drawingAttributes);
}
///
/// DetachVisual method
///
/// The stroke visual which needs to be detached
public void DetachVisuals(Visual visual)
{
VerifyAccess();
EnsureRootVisual();
_renderer.DetachIncrementalRendering(visual);
}
#endregion Public Methods
//--------------------------------------------------------------------------------
//
// Public Properties
//
//--------------------------------------------------------------------------------
#region Public Properties
///
/// The DependencyProperty for the Strokes property.
///
public static readonly DependencyProperty StrokesProperty =
DependencyProperty.Register(
"Strokes",
typeof(StrokeCollection),
typeof(InkPresenter),
new FrameworkPropertyMetadata(
new StrokeCollectionDefaultValueFactory(),
new PropertyChangedCallback(OnStrokesChanged)),
(ValidateValueCallback)delegate(object value)
{ return value != null; });
///
/// Gets/Sets the Strokes property.
///
public StrokeCollection Strokes
{
get { return (StrokeCollection)GetValue(StrokesProperty); }
set { SetValue(StrokesProperty, value); }
}
private static void OnStrokesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
InkPresenter inkPresenter = (InkPresenter)d;
StrokeCollection oldValue = (StrokeCollection)e.OldValue;
StrokeCollection newValue = (StrokeCollection)e.NewValue;
inkPresenter.SetStrokesChangedHandlers(newValue, oldValue);
inkPresenter.OnStrokeChanged(inkPresenter, EventArgs.Empty);
}
#endregion Public Properties
//-------------------------------------------------------------------------------
//
// Protected Methods
//
//--------------------------------------------------------------------------------
#region Protected Methods
///
/// Override of
///
/// Constraint size.
/// Computed desired size.
protected override Size MeasureOverride(Size constraint)
{
// No need to call VerifyAccess since we call the method on the base here.
StrokeCollection strokes = Strokes;
// Measure the child first
Size newSize = base.MeasureOverride(constraint);
// If there are strokes in IP, we need to combine the size to final size.
if ( strokes != null && strokes.Count != 0 )
{
// Get the bounds of the stroks
Rect boundingRect = StrokesBounds;
// If we have an empty bounding box or the Right/Bottom value is negative,
// an empty size will be returned.
if ( !boundingRect.IsEmpty && boundingRect.Right > 0.0 && boundingRect.Bottom > 0.0 )
{
// The new size needs to contain the right boundary and bottom boundary.
Size sizeStrokes = new Size(boundingRect.Right, boundingRect.Bottom);
newSize.Width = Math.Max(newSize.Width, sizeStrokes.Width);
newSize.Height = Math.Max(newSize.Height, sizeStrokes.Height);
}
}
if ( Child != null )
{
_constraintSize = constraint;
}
else
{
_constraintSize = Size.Empty;
}
return newSize;
}
///
/// Override of .
///
/// Size that element should use to arrange itself and its children.
/// The InkPresenter's desired size.
protected override Size ArrangeOverride(Size arrangeSize)
{
VerifyAccess();
EnsureRootVisual();
// NTRAID-WINDOWSOS#1091908-WAYNEZEN,
// When we arrange the child, we shouldn't count in the strokes' bounds.
// We only use the constraint size for the child.
Size availableSize = arrangeSize;
if ( !_constraintSize.IsEmpty )
{
availableSize = new Size(Math.Min(arrangeSize.Width, _constraintSize.Width),
Math.Min(arrangeSize.Height, _constraintSize.Height));
}
// We arrange our child as what Decorator does
// exceopt we are using the available size computed from our cached measure size.
UIElement child = Child;
if ( child != null )
{
child.Arrange(new Rect(availableSize));
}
return arrangeSize;
}
///
/// The overridden GetLayoutClip method
///
/// Geometry to use as additional clip if ClipToBounds=true
protected override Geometry GetLayoutClip(Size layoutSlotSize)
{
// NTRAID:WINDOWSOS#1516798-2006/02/17-WAYNEZEN
// By default an FE will clip its content if the ink size exceeds the layout size (the final arrange size).
// Since we are auto growing, the ink size is same as the desired size. So it ends up the strokes will be clipped
// regardless ClipToBounds is set or not.
// We override the GetLayoutClip method so that we can bypass the default layout clip if ClipToBounds is set to false.
// So we allow the ink to be drown anywhere when no clip is set.
if ( ClipToBounds )
{
return base.GetLayoutClip(layoutSlotSize);
}
else
return null;
}
///
/// Returns the child at the specified index.
///
protected override Visual GetVisualChild(int index)
{
int count = VisualChildrenCount;
if(count == 2)
{
switch (index)
{
case 0:
return base.Child;
case 1:
return _renderer.RootVisual;
default:
throw new ArgumentOutOfRangeException("index", index, SR.Get(SRID.Visual_ArgumentOutOfRange));
}
}
else if (index == 0 && count == 1)
{
if ( _hasAddedRoot )
{
return _renderer.RootVisual;
}
else if(base.Child != null)
{
return base.Child;
}
}
throw new ArgumentOutOfRangeException("index", index, SR.Get(SRID.Visual_ArgumentOutOfRange));
}
///
/// Derived classes override this property to enable the Visual code to enumerate
/// the Visual children. Derived classes need to return the number of children
/// from this method.
///
/// By default a Visual does not have any children.
///
/// Remark: During this virtual method the Visual tree must not be modified.
///
protected override int VisualChildrenCount
{
get
{
// we can have 4 states:-
// 1. no children
// 2. only base.Child
// 3. only _renderer.RootVisual as the child
// 4. both base.Child and _renderer.RootVisual
if(base.Child != null)
{
if ( _hasAddedRoot )
{
return 2;
}
else
{
return 1;
}
}
else if ( _hasAddedRoot )
{
return 1;
}
return 0;
}
}
///
/// UIAutomation support
///
protected override AutomationPeer OnCreateAutomationPeer()
{
return new InkPresenterAutomationPeer(this);
}
#endregion Protected Methods
#region Internal Methods
///
/// Internal helper used to indicate if a visual was previously attached
/// via a call to AttachIncrementalRendering
///
internal bool ContainsAttachedVisual(Visual visual)
{
VerifyAccess();
return _renderer.ContainsAttachedIncrementalRenderingVisual(visual);
}
///
/// Internal helper used to determine if a visual is in the right spot in the visual tree
///
internal bool AttachedVisualIsPositionedCorrectly(Visual visual, DrawingAttributes drawingAttributes)
{
VerifyAccess();
return _renderer.AttachedVisualIsPositionedCorrectly(visual, drawingAttributes);
}
#endregion Internal Methods
//-----------------------------------------------------
//
// Private Classes
//
//-----------------------------------------------------
#region Private Classes
///
/// A helper class for the high contrast support
///
private class InkPresenterHighContrastCallback : HighContrastCallback
{
//-----------------------------------------------------
//
// Cnostructors
//
//------------------------------------------------------
#region Constructors
internal InkPresenterHighContrastCallback(InkPresenter inkPresenter)
{
_thisInkPresenter = inkPresenter;
}
private InkPresenterHighContrastCallback() { }
#endregion Constructors
//-----------------------------------------------------
//
// Internal Methods
//
//------------------------------------------------------
#region Internal Methods
///
/// TurnHighContrastOn
///
///
internal override void TurnHighContrastOn(Color highContrastColor)
{
_thisInkPresenter._renderer.TurnHighContrastOn(highContrastColor);
_thisInkPresenter.OnStrokeChanged();
}
///
/// TurnHighContrastOff
///
internal override void TurnHighContrastOff()
{
_thisInkPresenter._renderer.TurnHighContrastOff();
_thisInkPresenter.OnStrokeChanged();
}
#endregion Internal Methods
//------------------------------------------------------
//
// Internal Properties
//
//-----------------------------------------------------
#region Internal Properties
///
/// Returns the dispatcher if the object is associated to a UIContext.
///
internal override Dispatcher Dispatcher
{
get
{
return _thisInkPresenter.Dispatcher;
}
}
#endregion Internal Properties
//------------------------------------------------------
//
// Private Fields
//
//-----------------------------------------------------
#region Private Fields
private InkPresenter _thisInkPresenter;
#endregion Private Fields
}
#endregion Private Classes
//-------------------------------------------------------------------------------
//
// Private Methods
//
//-------------------------------------------------------------------------------
#region Private Methods
private void SetStrokesChangedHandlers(StrokeCollection newStrokes, StrokeCollection oldStrokes)
{
Debug.Assert(newStrokes != null, "Cannot set a null to InkPresenter");
// Remove the event handlers from the old stroke collection
if ( null != oldStrokes )
{
// Stop listening on events from the stroke collection.
oldStrokes.StrokesChanged -= new StrokeCollectionChangedEventHandler(OnStrokesChanged);
}
// Start listening on events from the stroke collection.
newStrokes.StrokesChanged += new StrokeCollectionChangedEventHandler(OnStrokesChanged);
// Replace the renderer stroke collection.
_renderer.Strokes = newStrokes;
SetStrokeChangedHandlers(newStrokes, oldStrokes);
}
///
/// StrokeCollectionChanged event handler
///
private void OnStrokesChanged(object sender, StrokeCollectionChangedEventArgs eventArgs)
{
System.Diagnostics.Debug.Assert(sender == this.Strokes);
SetStrokeChangedHandlers(eventArgs.Added, eventArgs.Removed);
OnStrokeChanged(this, EventArgs.Empty);
}
private void SetStrokeChangedHandlers(StrokeCollection addedStrokes, StrokeCollection removedStrokes)
{
Debug.Assert(addedStrokes != null, "The added StrokeCollection cannot be null.");
int count, i;
if ( removedStrokes != null )
{
// Deal with removed strokes first
count = removedStrokes.Count;
for ( i = 0; i < count; i++ )
{
StopListeningOnStrokeEvents(removedStrokes[i]);
}
}
// Add new strokes
count = addedStrokes.Count;
for ( i = 0; i < count; i++ )
{
StartListeningOnStrokeEvents(addedStrokes[i]);
}
}
private void OnStrokeChanged(object sender, EventArgs e)
{
OnStrokeChanged();
}
///
/// The method is called from Stroke setter, OnStrokesChanged, DrawingAttributesChanged and OnPacketsChanged
///
private void OnStrokeChanged()
{
// Recalculate the bound of the StrokeCollection
_cachedBounds = null;
// Invalidate the current measure when any change happens on the stroke or strokes.
InvalidateMeasure();
}
///
/// Attaches event handlers to stroke events
///
private void StartListeningOnStrokeEvents(Stroke stroke)
{
System.Diagnostics.Debug.Assert(stroke != null);
stroke.Invalidated += new EventHandler(OnStrokeChanged);
}
///
/// Detaches event handlers from stroke
///
private void StopListeningOnStrokeEvents(Stroke stroke)
{
System.Diagnostics.Debug.Assert(stroke != null);
stroke.Invalidated -= new EventHandler(OnStrokeChanged);
}
///
/// Ensure the renderer root to be connected. The method is called from
/// AttachVisuals
/// DetachVisuals
/// ArrangeOverride
///
private void EnsureRootVisual()
{
if ( !_hasAddedRoot )
{
AddVisualChild(_renderer.RootVisual);
_hasAddedRoot = true;
}
}
#endregion Private Methods
//--------------------------------------------------------------------------------
//
// Private Properties
//
//-------------------------------------------------------------------------------
#region Private Properties
private Rect StrokesBounds
{
get
{
if ( _cachedBounds == null )
{
_cachedBounds = Strokes.GetBounds();
}
return _cachedBounds.Value;
}
}
#endregion Private Properties
//--------------------------------------------------------------------------------
//
// Private Fields
//
//--------------------------------------------------------------------------------
#region Private Fields
private Ink.Renderer _renderer;
private Nullable _cachedBounds = null;
private bool _hasAddedRoot;
//
// HighContrast support
//
private InkPresenterHighContrastCallback _contrastCallback;
private Size _constraintSize;
#endregion Private Fields
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------------------
//
// File: InkPresenter.cs
//
// Description:
// A rendering element which binds to the strokes data
//
// Features:
//
// History:
// 12/02/2004 waynezen: Created
//
// Copyright (C) 2001 by Microsoft Corporation. All rights reserved.
//
//---------------------------------------------------------------------------
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Media;
using System.Windows.Controls;
using System.Windows.Ink;
using System.Windows.Threading;
using System.Windows.Input;
using MS.Internal.Ink;
using System.Windows.Automation.Peers;
namespace System.Windows.Controls
{
///
/// Renders the specified StrokeCollection data.
///
public class InkPresenter : Decorator
{
//-------------------------------------------------------------------------------
//
// Constructors
//
//-------------------------------------------------------------------------------
#region Constructors
///
/// The constructor of InkPresenter
///
public InkPresenter()
{
// Create the internal Renderer object.
_renderer = new Ink.Renderer();
SetStrokesChangedHandlers(this.Strokes, null);
_contrastCallback = new InkPresenterHighContrastCallback(this);
// Register rti high contrast callback. Then check whether we are under the high contrast already.
HighContrastHelper.RegisterHighContrastCallback(_contrastCallback);
if ( SystemParameters.HighContrast )
{
_contrastCallback.TurnHighContrastOn(SystemColors.WindowTextColor);
}
_constraintSize = Size.Empty;
}
#endregion Constructors
//--------------------------------------------------------------------------------
//
// Public Methods
//
//-------------------------------------------------------------------------------
#region Public Methods
///
/// AttachVisual method
///
/// The stroke visual which needs to be attached
/// The DrawingAttributes of the stroke
public void AttachVisuals(Visual visual, DrawingAttributes drawingAttributes)
{
VerifyAccess();
EnsureRootVisual();
_renderer.AttachIncrementalRendering(visual, drawingAttributes);
}
///
/// DetachVisual method
///
/// The stroke visual which needs to be detached
public void DetachVisuals(Visual visual)
{
VerifyAccess();
EnsureRootVisual();
_renderer.DetachIncrementalRendering(visual);
}
#endregion Public Methods
//--------------------------------------------------------------------------------
//
// Public Properties
//
//--------------------------------------------------------------------------------
#region Public Properties
///
/// The DependencyProperty for the Strokes property.
///
public static readonly DependencyProperty StrokesProperty =
DependencyProperty.Register(
"Strokes",
typeof(StrokeCollection),
typeof(InkPresenter),
new FrameworkPropertyMetadata(
new StrokeCollectionDefaultValueFactory(),
new PropertyChangedCallback(OnStrokesChanged)),
(ValidateValueCallback)delegate(object value)
{ return value != null; });
///
/// Gets/Sets the Strokes property.
///
public StrokeCollection Strokes
{
get { return (StrokeCollection)GetValue(StrokesProperty); }
set { SetValue(StrokesProperty, value); }
}
private static void OnStrokesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
InkPresenter inkPresenter = (InkPresenter)d;
StrokeCollection oldValue = (StrokeCollection)e.OldValue;
StrokeCollection newValue = (StrokeCollection)e.NewValue;
inkPresenter.SetStrokesChangedHandlers(newValue, oldValue);
inkPresenter.OnStrokeChanged(inkPresenter, EventArgs.Empty);
}
#endregion Public Properties
//-------------------------------------------------------------------------------
//
// Protected Methods
//
//--------------------------------------------------------------------------------
#region Protected Methods
///
/// Override of
///
/// Constraint size.
/// Computed desired size.
protected override Size MeasureOverride(Size constraint)
{
// No need to call VerifyAccess since we call the method on the base here.
StrokeCollection strokes = Strokes;
// Measure the child first
Size newSize = base.MeasureOverride(constraint);
// If there are strokes in IP, we need to combine the size to final size.
if ( strokes != null && strokes.Count != 0 )
{
// Get the bounds of the stroks
Rect boundingRect = StrokesBounds;
// If we have an empty bounding box or the Right/Bottom value is negative,
// an empty size will be returned.
if ( !boundingRect.IsEmpty && boundingRect.Right > 0.0 && boundingRect.Bottom > 0.0 )
{
// The new size needs to contain the right boundary and bottom boundary.
Size sizeStrokes = new Size(boundingRect.Right, boundingRect.Bottom);
newSize.Width = Math.Max(newSize.Width, sizeStrokes.Width);
newSize.Height = Math.Max(newSize.Height, sizeStrokes.Height);
}
}
if ( Child != null )
{
_constraintSize = constraint;
}
else
{
_constraintSize = Size.Empty;
}
return newSize;
}
///
/// Override of .
///
/// Size that element should use to arrange itself and its children.
/// The InkPresenter's desired size.
protected override Size ArrangeOverride(Size arrangeSize)
{
VerifyAccess();
EnsureRootVisual();
// NTRAID-WINDOWSOS#1091908-WAYNEZEN,
// When we arrange the child, we shouldn't count in the strokes' bounds.
// We only use the constraint size for the child.
Size availableSize = arrangeSize;
if ( !_constraintSize.IsEmpty )
{
availableSize = new Size(Math.Min(arrangeSize.Width, _constraintSize.Width),
Math.Min(arrangeSize.Height, _constraintSize.Height));
}
// We arrange our child as what Decorator does
// exceopt we are using the available size computed from our cached measure size.
UIElement child = Child;
if ( child != null )
{
child.Arrange(new Rect(availableSize));
}
return arrangeSize;
}
///
/// The overridden GetLayoutClip method
///
/// Geometry to use as additional clip if ClipToBounds=true
protected override Geometry GetLayoutClip(Size layoutSlotSize)
{
// NTRAID:WINDOWSOS#1516798-2006/02/17-WAYNEZEN
// By default an FE will clip its content if the ink size exceeds the layout size (the final arrange size).
// Since we are auto growing, the ink size is same as the desired size. So it ends up the strokes will be clipped
// regardless ClipToBounds is set or not.
// We override the GetLayoutClip method so that we can bypass the default layout clip if ClipToBounds is set to false.
// So we allow the ink to be drown anywhere when no clip is set.
if ( ClipToBounds )
{
return base.GetLayoutClip(layoutSlotSize);
}
else
return null;
}
///
/// Returns the child at the specified index.
///
protected override Visual GetVisualChild(int index)
{
int count = VisualChildrenCount;
if(count == 2)
{
switch (index)
{
case 0:
return base.Child;
case 1:
return _renderer.RootVisual;
default:
throw new ArgumentOutOfRangeException("index", index, SR.Get(SRID.Visual_ArgumentOutOfRange));
}
}
else if (index == 0 && count == 1)
{
if ( _hasAddedRoot )
{
return _renderer.RootVisual;
}
else if(base.Child != null)
{
return base.Child;
}
}
throw new ArgumentOutOfRangeException("index", index, SR.Get(SRID.Visual_ArgumentOutOfRange));
}
///
/// Derived classes override this property to enable the Visual code to enumerate
/// the Visual children. Derived classes need to return the number of children
/// from this method.
///
/// By default a Visual does not have any children.
///
/// Remark: During this virtual method the Visual tree must not be modified.
///
protected override int VisualChildrenCount
{
get
{
// we can have 4 states:-
// 1. no children
// 2. only base.Child
// 3. only _renderer.RootVisual as the child
// 4. both base.Child and _renderer.RootVisual
if(base.Child != null)
{
if ( _hasAddedRoot )
{
return 2;
}
else
{
return 1;
}
}
else if ( _hasAddedRoot )
{
return 1;
}
return 0;
}
}
///
/// UIAutomation support
///
protected override AutomationPeer OnCreateAutomationPeer()
{
return new InkPresenterAutomationPeer(this);
}
#endregion Protected Methods
#region Internal Methods
///
/// Internal helper used to indicate if a visual was previously attached
/// via a call to AttachIncrementalRendering
///
internal bool ContainsAttachedVisual(Visual visual)
{
VerifyAccess();
return _renderer.ContainsAttachedIncrementalRenderingVisual(visual);
}
///
/// Internal helper used to determine if a visual is in the right spot in the visual tree
///
internal bool AttachedVisualIsPositionedCorrectly(Visual visual, DrawingAttributes drawingAttributes)
{
VerifyAccess();
return _renderer.AttachedVisualIsPositionedCorrectly(visual, drawingAttributes);
}
#endregion Internal Methods
//-----------------------------------------------------
//
// Private Classes
//
//-----------------------------------------------------
#region Private Classes
///
/// A helper class for the high contrast support
///
private class InkPresenterHighContrastCallback : HighContrastCallback
{
//-----------------------------------------------------
//
// Cnostructors
//
//------------------------------------------------------
#region Constructors
internal InkPresenterHighContrastCallback(InkPresenter inkPresenter)
{
_thisInkPresenter = inkPresenter;
}
private InkPresenterHighContrastCallback() { }
#endregion Constructors
//-----------------------------------------------------
//
// Internal Methods
//
//------------------------------------------------------
#region Internal Methods
///
/// TurnHighContrastOn
///
///
internal override void TurnHighContrastOn(Color highContrastColor)
{
_thisInkPresenter._renderer.TurnHighContrastOn(highContrastColor);
_thisInkPresenter.OnStrokeChanged();
}
///
/// TurnHighContrastOff
///
internal override void TurnHighContrastOff()
{
_thisInkPresenter._renderer.TurnHighContrastOff();
_thisInkPresenter.OnStrokeChanged();
}
#endregion Internal Methods
//------------------------------------------------------
//
// Internal Properties
//
//-----------------------------------------------------
#region Internal Properties
///
/// Returns the dispatcher if the object is associated to a UIContext.
///
internal override Dispatcher Dispatcher
{
get
{
return _thisInkPresenter.Dispatcher;
}
}
#endregion Internal Properties
//------------------------------------------------------
//
// Private Fields
//
//-----------------------------------------------------
#region Private Fields
private InkPresenter _thisInkPresenter;
#endregion Private Fields
}
#endregion Private Classes
//-------------------------------------------------------------------------------
//
// Private Methods
//
//-------------------------------------------------------------------------------
#region Private Methods
private void SetStrokesChangedHandlers(StrokeCollection newStrokes, StrokeCollection oldStrokes)
{
Debug.Assert(newStrokes != null, "Cannot set a null to InkPresenter");
// Remove the event handlers from the old stroke collection
if ( null != oldStrokes )
{
// Stop listening on events from the stroke collection.
oldStrokes.StrokesChanged -= new StrokeCollectionChangedEventHandler(OnStrokesChanged);
}
// Start listening on events from the stroke collection.
newStrokes.StrokesChanged += new StrokeCollectionChangedEventHandler(OnStrokesChanged);
// Replace the renderer stroke collection.
_renderer.Strokes = newStrokes;
SetStrokeChangedHandlers(newStrokes, oldStrokes);
}
///
/// StrokeCollectionChanged event handler
///
private void OnStrokesChanged(object sender, StrokeCollectionChangedEventArgs eventArgs)
{
System.Diagnostics.Debug.Assert(sender == this.Strokes);
SetStrokeChangedHandlers(eventArgs.Added, eventArgs.Removed);
OnStrokeChanged(this, EventArgs.Empty);
}
private void SetStrokeChangedHandlers(StrokeCollection addedStrokes, StrokeCollection removedStrokes)
{
Debug.Assert(addedStrokes != null, "The added StrokeCollection cannot be null.");
int count, i;
if ( removedStrokes != null )
{
// Deal with removed strokes first
count = removedStrokes.Count;
for ( i = 0; i < count; i++ )
{
StopListeningOnStrokeEvents(removedStrokes[i]);
}
}
// Add new strokes
count = addedStrokes.Count;
for ( i = 0; i < count; i++ )
{
StartListeningOnStrokeEvents(addedStrokes[i]);
}
}
private void OnStrokeChanged(object sender, EventArgs e)
{
OnStrokeChanged();
}
///
/// The method is called from Stroke setter, OnStrokesChanged, DrawingAttributesChanged and OnPacketsChanged
///
private void OnStrokeChanged()
{
// Recalculate the bound of the StrokeCollection
_cachedBounds = null;
// Invalidate the current measure when any change happens on the stroke or strokes.
InvalidateMeasure();
}
///
/// Attaches event handlers to stroke events
///
private void StartListeningOnStrokeEvents(Stroke stroke)
{
System.Diagnostics.Debug.Assert(stroke != null);
stroke.Invalidated += new EventHandler(OnStrokeChanged);
}
///
/// Detaches event handlers from stroke
///
private void StopListeningOnStrokeEvents(Stroke stroke)
{
System.Diagnostics.Debug.Assert(stroke != null);
stroke.Invalidated -= new EventHandler(OnStrokeChanged);
}
///
/// Ensure the renderer root to be connected. The method is called from
/// AttachVisuals
/// DetachVisuals
/// ArrangeOverride
///
private void EnsureRootVisual()
{
if ( !_hasAddedRoot )
{
AddVisualChild(_renderer.RootVisual);
_hasAddedRoot = true;
}
}
#endregion Private Methods
//--------------------------------------------------------------------------------
//
// Private Properties
//
//-------------------------------------------------------------------------------
#region Private Properties
private Rect StrokesBounds
{
get
{
if ( _cachedBounds == null )
{
_cachedBounds = Strokes.GetBounds();
}
return _cachedBounds.Value;
}
}
#endregion Private Properties
//--------------------------------------------------------------------------------
//
// Private Fields
//
//--------------------------------------------------------------------------------
#region Private Fields
private Ink.Renderer _renderer;
private Nullable _cachedBounds = null;
private bool _hasAddedRoot;
//
// HighContrast support
//
private InkPresenterHighContrastCallback _contrastCallback;
private Size _constraintSize;
#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
- MarkupObject.cs
- AnnotationAdorner.cs
- DrawingAttributes.cs
- CertificateElement.cs
- QueryCreatedEventArgs.cs
- ClipboardData.cs
- MailSettingsSection.cs
- EncryptionUtility.cs
- StopRoutingHandler.cs
- RegisteredDisposeScript.cs
- BevelBitmapEffect.cs
- MappingException.cs
- TrustManagerPromptUI.cs
- HtmlInputHidden.cs
- StringWriter.cs
- ClientSettings.cs
- DbgCompiler.cs
- cookiecontainer.cs
- GridViewRowCollection.cs
- UpdateEventArgs.cs
- DWriteFactory.cs
- UnaryOperationBinder.cs
- HtmlPanelAdapter.cs
- ProcessThreadCollection.cs
- CommandValueSerializer.cs
- EntityContainerRelationshipSetEnd.cs
- FullTextState.cs
- MatrixTransform3D.cs
- CollectionViewGroupRoot.cs
- AssemblySettingAttributes.cs
- CodeNamespace.cs
- PrintPreviewGraphics.cs
- ContractBase.cs
- XmlEncodedRawTextWriter.cs
- SettingsProperty.cs
- PartialClassGenerationTaskInternal.cs
- SafeWaitHandle.cs
- QuadTree.cs
- DesignerEditorPartChrome.cs
- TextViewSelectionProcessor.cs
- NotSupportedException.cs
- ListBindingHelper.cs
- Parameter.cs
- XmlSchemaImporter.cs
- ClientUrlResolverWrapper.cs
- OleDbConnectionPoolGroupProviderInfo.cs
- UntypedNullExpression.cs
- Monitor.cs
- SchemaEntity.cs
- SecurityKeyIdentifierClause.cs
- SqlEnums.cs
- HtmlAnchor.cs
- ConsumerConnectionPointCollection.cs
- XmlQualifiedNameTest.cs
- WebEventCodes.cs
- BoundsDrawingContextWalker.cs
- BadImageFormatException.cs
- WorkflowRuntimeServiceElement.cs
- SelectionProviderWrapper.cs
- PassportIdentity.cs
- regiisutil.cs
- SequentialUshortCollection.cs
- MarkupExtensionReturnTypeAttribute.cs
- PrivilegeNotHeldException.cs
- SessionIDManager.cs
- DebugInfoExpression.cs
- BrowserCapabilitiesCodeGenerator.cs
- DataGridCellItemAutomationPeer.cs
- DbConnectionPoolIdentity.cs
- SafeHandles.cs
- FixedStringLookup.cs
- CompilationRelaxations.cs
- DataAccessException.cs
- MetaTableHelper.cs
- ParsedAttributeCollection.cs
- XmlCharType.cs
- DataObjectCopyingEventArgs.cs
- AddInPipelineAttributes.cs
- SoapSchemaMember.cs
- _ReceiveMessageOverlappedAsyncResult.cs
- BlockCollection.cs
- NameValuePermission.cs
- ReverseInheritProperty.cs
- Helpers.cs
- ZoneLinkButton.cs
- HtmlImage.cs
- CanonicalXml.cs
- ValidatedControlConverter.cs
- DecoderReplacementFallback.cs
- SafeCryptoHandles.cs
- RotateTransform.cs
- ChangePassword.cs
- SHA384.cs
- DataGridViewColumnCollection.cs
- ScrollProviderWrapper.cs
- PenLineJoinValidation.cs
- WindowsFormsHelpers.cs
- GraphicsContainer.cs
- EventItfInfo.cs
- CommonProperties.cs