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
- Common.cs
- CertificateManager.cs
- GacUtil.cs
- RectangleConverter.cs
- DefaultHttpHandler.cs
- Tracer.cs
- GridViewPageEventArgs.cs
- WeakEventManager.cs
- HuffmanTree.cs
- Control.cs
- DataChangedEventManager.cs
- AttachedAnnotation.cs
- DbParameterCollection.cs
- StateWorkerRequest.cs
- SafeFileHandle.cs
- ListItemConverter.cs
- X509CertificateStore.cs
- HandoffBehavior.cs
- CSharpCodeProvider.cs
- ConfigurationLockCollection.cs
- DirectoryObjectSecurity.cs
- Control.cs
- _CookieModule.cs
- SystemResourceKey.cs
- ListViewInsertionMark.cs
- DataObjectSettingDataEventArgs.cs
- TransformDescriptor.cs
- DataGridRelationshipRow.cs
- TextRenderer.cs
- DSACryptoServiceProvider.cs
- DrawingAttributesDefaultValueFactory.cs
- QilStrConcatenator.cs
- FormatterConverter.cs
- Ray3DHitTestResult.cs
- DetailsViewDeletedEventArgs.cs
- SchemaNames.cs
- FileDataSourceCache.cs
- ScriptDescriptor.cs
- GlyphingCache.cs
- WorkflowFormatterBehavior.cs
- MissingManifestResourceException.cs
- FormViewRow.cs
- tooltip.cs
- Parallel.cs
- Figure.cs
- DataStreamFromComStream.cs
- FuncTypeConverter.cs
- SqlInfoMessageEvent.cs
- XmlEntity.cs
- FilteredAttributeCollection.cs
- WriteFileContext.cs
- ServiceMetadataBehavior.cs
- FrameworkTextComposition.cs
- ReachFixedDocumentSerializer.cs
- GeneralTransform.cs
- XPathNodeHelper.cs
- CodeExpressionStatement.cs
- WindowsScroll.cs
- KeyEventArgs.cs
- CachedFontFace.cs
- Int64Storage.cs
- ReversePositionQuery.cs
- WorkflowWebHostingModule.cs
- Property.cs
- RegexInterpreter.cs
- LocatorPart.cs
- TranslateTransform3D.cs
- Splitter.cs
- MediaSystem.cs
- ToolBarTray.cs
- Math.cs
- IisTraceListener.cs
- validation.cs
- DockPanel.cs
- AlignmentYValidation.cs
- PixelShader.cs
- XmlElementList.cs
- BinHexEncoder.cs
- XsltLoader.cs
- TextMetrics.cs
- WriterOutput.cs
- FusionWrap.cs
- HtmlHead.cs
- AbsoluteQuery.cs
- M3DUtil.cs
- ZipIOExtraField.cs
- HttpModuleAction.cs
- NotFiniteNumberException.cs
- StatusBar.cs
- ReplyChannelBinder.cs
- RefType.cs
- RoutedEvent.cs
- DataFormats.cs
- SyndicationCategory.cs
- StaticContext.cs
- NotificationContext.cs
- SyndicationSerializer.cs
- NavigationWindowAutomationPeer.cs
- ResourceSetExpression.cs
- InfoCardMasterKey.cs