Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Framework / MS / Internal / Annotations / Anchoring / TextSelectionHelper.cs / 1 / TextSelectionHelper.cs
//------------------------------------------------------------------------------
//
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//
// Description:
// TextSelectionHelper is a helper class used by TextSelectionProvcrssor
// and DynamicSelectionProcessor
//
// History:
// 03/28/2004: [....]: Created based on TextSelectionProcessor code
//
//-----------------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Windows;
using System.Windows.Annotations;
using System.Windows.Annotations.Storage;
using MS.Internal.Annotations.Component;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Documents;
using System.Windows.Media;
using System.Xml;
using MS.Internal.Documents;
using MS.Utility;
namespace MS.Internal.Annotations.Anchoring
{
///
/// TextSelectionHelper uses TextAnchors to represent portions
/// of text that are anchors. It produces locator parts that
/// represent these TextAnchors and can generate TextAnchors from
/// the locator parts.
///
internal class TextSelectionHelper
{
//-----------------------------------------------------
//
// Constructors
//
//-----------------------------------------------------
#region Constructors
///
/// This ctor is added to prevent the compiler from
/// generating a public default ctor. This class
/// should not be instantiated
///
private TextSelectionHelper() { }
#endregion Constructors
//------------------------------------------------------
//
// Public Methods
//
//-----------------------------------------------------
#region Public Methods
///
/// Merges the two anchors into one, if possible.
///
/// anchor to merge
/// other anchor to merge
/// new anchor that contains the data from both
/// anchor1 and anchor2
/// true if the anchors were merged, false otherwise
///
/// anchor1 or anchor2 are null
public static bool MergeSelections(Object anchor1, Object anchor2, out Object newAnchor)
{
TextAnchor firstAnchor = anchor1 as TextAnchor;
TextAnchor secondAnchor = anchor2 as TextAnchor;
if ((anchor1 != null) && (firstAnchor == null))
throw new ArgumentException(SR.Get(SRID.WrongSelectionType), "anchor1: type = " + anchor1.GetType().ToString());
if ((anchor2 != null) && (secondAnchor == null))
throw new ArgumentException(SR.Get(SRID.WrongSelectionType), "Anchor2: type = " + anchor2.GetType().ToString());
if (firstAnchor == null)
{
newAnchor = secondAnchor;
return newAnchor != null;
}
if (secondAnchor == null)
{
newAnchor = firstAnchor;
return newAnchor != null;
}
newAnchor = TextAnchor.ExclusiveUnion(firstAnchor, secondAnchor);
return true;
}
///
/// Gets the tree elements spanned by the selection.
///
/// the selection to examine
/// a list of elements spanned by the selection; never returns
/// null
/// selection is null
/// selection is of wrong type
public static IList GetSelectedNodes(Object selection)
{
if (selection == null)
throw new ArgumentNullException("selection");
IList segments;
ITextPointer start = null;
ITextPointer end = null;
CheckSelection(selection, out start, out end, out segments);
IList list = new List();
// If the selection is of length 0, then we simply add the parent of the
// text container and return.
if (start.CompareTo(end) == 0)
{
list.Add(((TextPointer)start).Parent);
return list;
}
TextPointer current = (TextPointer)start.CreatePointer();
while (((ITextPointer)current).CompareTo(end) < 0)
{
DependencyObject node = current.Parent;
if (!list.Contains(node))
{
list.Add(node);
}
current.MoveToNextContextPosition(LogicalDirection.Forward);
}
return list;
}
///
/// Gets the parent element of this selection.
///
/// the selection to examine
/// the parent element of the selection; can be null
/// selection is null
/// selection is of wrong type
public static UIElement GetParent(Object selection)
{
if (selection == null)
throw new ArgumentNullException("selection");
ITextPointer start = null;
ITextPointer end = null;
IList segments;
CheckSelection(selection, out start, out end, out segments);
return GetParent(start);
}
///
/// Gets the parent element of ITextPointer.
///
/// the pointer to examine
/// the parent element of this pointer; can be null
/// pointer is null
public static UIElement GetParent(ITextPointer pointer)
{
if (pointer == null)
throw new ArgumentNullException("pointer");
DependencyObject document = pointer.TextContainer.Parent;
DependencyObject parent = PathNode.GetParent(document);
FlowDocumentScrollViewer scrollViewer = parent as FlowDocumentScrollViewer;
if (scrollViewer != null)
{
return (UIElement)scrollViewer.ScrollViewer.Content;
}
// Special case - for paginated content we want the DocumentPageHost for the
// specific page instead of the viewer.
DocumentViewerBase documentViewerBase = parent as DocumentViewerBase;
if (documentViewerBase != null)
{
int pageNumber;
// We get the content again here GetPointerPage handles
// special cases like FixedDocumentSequences
IDocumentPaginatorSource content = GetPointerPage(pointer.CreatePointer(LogicalDirection.Forward), out pageNumber);
if (pageNumber >= 0)
{
foreach (DocumentPageView dpv in documentViewerBase.PageViews)
{
if (dpv.PageNumber == pageNumber)
{
// DPVs always have one child - the DocumentPageHost
int count = VisualTreeHelper.GetChildrenCount(dpv);
Invariant.Assert(count == 1);
return VisualTreeHelper.GetChild(dpv, 0) as DocumentPageHost;
}
}
// Page must not be visible.
return null;
}
}
return parent as UIElement;
}
///
/// Gets the anchor point for the selection
///
/// the anchor to examine
///
/// The anchor point of the selection;
/// If there is no valid AnchorPoint returns Point(Double.NaN, Double.NaN).
///
/// anchor is null
/// anchor is of wrong type
public static Point GetAnchorPoint(Object selection)
{
if (selection == null)
throw new ArgumentNullException("selection");
TextAnchor anchor = selection as TextAnchor;
if (anchor == null)
throw new ArgumentException(SR.Get(SRID.WrongSelectionType), "selection");
return GetAnchorPointForPointer(anchor.Start.CreatePointer(LogicalDirection.Forward));
}
///
/// Gets the anchor point for the text pointer
///
/// the pointer to examine
///
/// The anchor point of the text pointer
///
/// pointer is null
public static Point GetAnchorPointForPointer(ITextPointer pointer)
{
if (pointer == null)
throw new ArgumentNullException("pointer");
Rect rect = GetAnchorRectangle(pointer);
if (rect != Rect.Empty)
{
return new Point(rect.Left, rect.Top + rect.Height);
}
return new Point(0, 0);
}
///
/// Gets a point for the text pointer that can be turned back into
/// the TextPointer at a later time.
///
/// the pointer to examine
///
/// A point that can be turned back into the TextPointer at a later time
///
/// pointer is null
public static Point GetPointForPointer(ITextPointer pointer)
{
if (pointer == null)
throw new ArgumentNullException("pointer");
Rect rect = GetAnchorRectangle(pointer);
if (rect != Rect.Empty)
{
return new Point(rect.Left, rect.Top + rect.Height / 2);
}
return new Point(0, 0);
}
///
/// Gets the rectangle for this ITextPointer
///
/// the pointer to examine
///
/// The anchor point of the selection;
/// If there is no valid AnchorPoint returns Point(Double.NaN, Double.NaN).
///
/// pointer is null
public static Rect GetAnchorRectangle(ITextPointer pointer)
{
if (pointer == null)
throw new ArgumentNullException("pointer");
bool extension = false;
ITextView textView = GetDocumentPageTextView(pointer);
if (pointer.CompareTo(pointer.TextContainer.End) == 0)
{
//we can not get rectangle for the end of the TextContainer
//so get the last symbol
Point endPoint = new Point(Double.MaxValue, Double.MaxValue);
pointer = textView.GetTextPositionFromPoint(endPoint, true);
//we need to move the resulting rectangle at half space because
//the geometry calculating function does the same
extension = true;
}
if (textView != null && textView.IsValid && TextDocumentView.Contains(pointer, textView.TextSegments))
{
Rect rect = textView.GetRectangleFromTextPosition(pointer);
if (extension && rect != Rect.Empty)
{
rect.X += rect.Height / 2.0;
}
return rect;
}
return Rect.Empty;
}
///
/// Gets DocumentViewerBase and a page number for specified TextPointer
///
/// a TP from the container
/// the page number
/// DocumentViewerBase
public static IDocumentPaginatorSource GetPointerPage(ITextPointer pointer, out int pageNumber)
{
Invariant.Assert(pointer != null, "unknown pointer");
IDocumentPaginatorSource idp = pointer.TextContainer.Parent as IDocumentPaginatorSource;
FixedDocument fixedDoc = idp as FixedDocument;
if (fixedDoc != null)
{
FixedDocumentSequence sequence = fixedDoc.Parent as FixedDocumentSequence;
if (sequence != null)
idp = sequence;
}
Invariant.Assert(idp != null);
DynamicDocumentPaginator ddp = idp.DocumentPaginator as DynamicDocumentPaginator;
pageNumber = ddp != null ? ddp.GetPageNumber((ContentPosition)pointer) : -1;
return idp;
}
#endregion Public Methods
//------------------------------------------------------
//
// Internal Methods
//
//------------------------------------------------------
#region Internal Methods
///
/// Gets the start, end and text segments of the selection. Throws an exception if the
/// selection is of the wrong type.
///
internal static void CheckSelection(object selection, out ITextPointer start, out ITextPointer end, out IList segments)
{
ITextRange textRange = selection as ITextRange;
if (textRange != null)
{
start = textRange.Start;
end = textRange.End;
segments = textRange.TextSegments;
}
else
{
TextAnchor textAnchor = selection as TextAnchor;
if (textAnchor == null)
throw new ArgumentException(SR.Get(SRID.WrongSelectionType), "selection");
start = textAnchor.Start;
end = textAnchor.End;
segments = textAnchor.TextSegments;
}
}
///
/// Gets the TextView exposed by the page where this pointer lives
///
/// the pointer
/// the TextView
internal static ITextView GetDocumentPageTextView(ITextPointer pointer)
{
int pageNumber;
DependencyObject content = pointer.TextContainer.Parent as DependencyObject;
if (content != null)
{
FlowDocumentScrollViewer scrollViewer = PathNode.GetParent(content) as FlowDocumentScrollViewer;
if (scrollViewer != null)
{
IServiceProvider provider = scrollViewer.ScrollViewer.Content as IServiceProvider;
Invariant.Assert(provider != null, "FlowDocumentScrollViewer should be an IServiceProvider.");
return provider.GetService(typeof(ITextView)) as ITextView;
}
}
IDocumentPaginatorSource idp = GetPointerPage(pointer, out pageNumber);
if (idp != null && pageNumber >= 0)
{
DocumentPage docPage = idp.DocumentPaginator.GetPage(pageNumber);
IServiceProvider isp = docPage as IServiceProvider;
if (isp != null)
return isp.GetService(typeof(ITextView)) as ITextView;
}
return null;
}
///
/// Gets a list of ITextViews spanned by this text segment
///
/// the text segment
/// the TextViews list
internal static List GetDocumentPageTextViews(TextSegment segment)
{
List res = null;
int startPageNumber, endPageNumber;
//revert the logical direction of the pointers
ITextPointer start = segment.Start.CreatePointer(LogicalDirection.Forward);
ITextPointer end = segment.End.CreatePointer(LogicalDirection.Backward);
DependencyObject content = start.TextContainer.Parent as DependencyObject;
if (content != null)
{
FlowDocumentScrollViewer scrollViewer = PathNode.GetParent(content) as FlowDocumentScrollViewer;
if (scrollViewer != null)
{
IServiceProvider provider = scrollViewer.ScrollViewer.Content as IServiceProvider;
Invariant.Assert(provider != null, "FlowDocumentScrollViewer should be an IServiceProvider.");
res = new List(1);
res.Add(provider.GetService(typeof(ITextView)) as ITextView);
return res;
}
}
IDocumentPaginatorSource idp = GetPointerPage(start, out startPageNumber);
DynamicDocumentPaginator ddp = idp.DocumentPaginator as DynamicDocumentPaginator;
endPageNumber = ddp != null ? ddp.GetPageNumber((ContentPosition)end) : -1;
if (startPageNumber == -1 || endPageNumber == -1)
{
// If either page couldn't be found, we return an empty list. This
// could be caused by a failure in paginating the document.
res = new List(0);
}
else if (startPageNumber == endPageNumber)
{
res = ProcessSinglePage(idp, startPageNumber);
}
else
{
res = ProcessMultiplePages(idp, startPageNumber, endPageNumber);
}
return res;
}
#endregion Internal Methods
//-----------------------------------------------------
//
// Private Methods
//
//------------------------------------------------------
#region Private Methods
///
/// Gets a single page TextView throug the idp.GetPage. cALL this API only when
/// it is sure that the page is loaded
///
/// IDocumentPaginatorSource
/// page number
/// returns a list of one view
private static List ProcessSinglePage(IDocumentPaginatorSource idp, int pageNumber)
{
Invariant.Assert(idp != null, "IDocumentPaginatorSource is null");
DocumentPage docPage = idp.DocumentPaginator.GetPage(pageNumber);
IServiceProvider isp = docPage as IServiceProvider;
List res = null;
if (isp != null)
{
res = new List(1);
ITextView view = isp.GetService(typeof(ITextView)) as ITextView;
if (view != null)
res.Add(view);
}
return res;
}
///
/// Gets existing views for pages from start to end. Scans only existing view to
/// avoid loading of unloaded pages.
///
/// IDocumentPaginatorSource
/// start page number
/// end page number
/// returns a list of text views
private static List ProcessMultiplePages(IDocumentPaginatorSource idp, int startPageNumber, int endPageNumber)
{
Invariant.Assert(idp != null, "IDocumentPaginatorSource is null");
//now get available views
DocumentViewerBase viewer = PathNode.GetParent(idp as DependencyObject) as DocumentViewerBase;
Invariant.Assert(viewer != null, "DocumentViewer not found");
// If the pages for the text segment are reversed (possibly a floater where the floater
// reflow on to a page that comes after its anchor) we just swap them
if (endPageNumber < startPageNumber)
{
int temp = endPageNumber;
endPageNumber = startPageNumber;
startPageNumber = temp;
}
List res = null;
if (idp != null && startPageNumber >= 0 && endPageNumber >= startPageNumber)
{
res = new List(endPageNumber - startPageNumber + 1);
for (int pageNb = startPageNumber; pageNb <= endPageNumber; pageNb++)
{
DocumentPageView view = AnnotationHelper.FindView(viewer, pageNb);
if (view != null)
{
IServiceProvider serviceProvider = view.DocumentPage as IServiceProvider;
if (serviceProvider != null)
{
ITextView textView = serviceProvider.GetService(typeof(ITextView)) as ITextView;
if (textView != null)
res.Add(textView);
}
}
}
}
return res;
}
#endregion Private Methods
}
}
// 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
- ZoneIdentityPermission.cs
- ColorTranslator.cs
- Soap12FormatExtensions.cs
- LiteralSubsegment.cs
- BaseTypeViewSchema.cs
- ArrangedElement.cs
- ArraySortHelper.cs
- __Error.cs
- CompositeControl.cs
- XmlCharCheckingWriter.cs
- QueryPageSettingsEventArgs.cs
- Rules.cs
- HttpConfigurationContext.cs
- CssStyleCollection.cs
- COAUTHINFO.cs
- EventMappingSettingsCollection.cs
- ReceiveActivityDesignerTheme.cs
- GB18030Encoding.cs
- StrokeNodeOperations.cs
- StorageSetMapping.cs
- SqlDataReaderSmi.cs
- MergePropertyDescriptor.cs
- AlphaSortedEnumConverter.cs
- TextCollapsingProperties.cs
- SqlDataSourceFilteringEventArgs.cs
- PropVariant.cs
- WebPartConnection.cs
- LocalFileSettingsProvider.cs
- OwnerDrawPropertyBag.cs
- ByteStreamMessageUtility.cs
- SafeSystemMetrics.cs
- NonBatchDirectoryCompiler.cs
- SQLRoleProvider.cs
- ContentFilePart.cs
- PageAdapter.cs
- Duration.cs
- PropertyIDSet.cs
- COAUTHINFO.cs
- ButtonColumn.cs
- IsolatedStorage.cs
- ApplicationServiceManager.cs
- VisualBrush.cs
- BasicViewGenerator.cs
- QilExpression.cs
- PenLineJoinValidation.cs
- SkewTransform.cs
- DataPointer.cs
- FormsAuthenticationUserCollection.cs
- SupportsEventValidationAttribute.cs
- Attributes.cs
- InvalidOperationException.cs
- AmbientLight.cs
- ObjectStateFormatter.cs
- NavigatorInvalidBodyAccessException.cs
- FixedTextContainer.cs
- TypeInfo.cs
- XmlNamedNodeMap.cs
- PeerCollaborationPermission.cs
- DataRowCollection.cs
- DataGridViewIntLinkedList.cs
- DataDocumentXPathNavigator.cs
- AsymmetricKeyExchangeDeformatter.cs
- PassportAuthenticationModule.cs
- PolicyException.cs
- SocketPermission.cs
- SignatureDescription.cs
- AppDomainGrammarProxy.cs
- ErasingStroke.cs
- WindowsEditBox.cs
- FunctionParameter.cs
- ImageMetadata.cs
- RemotingConfiguration.cs
- Char.cs
- PointCollectionConverter.cs
- Console.cs
- PageTextBox.cs
- BinHexDecoder.cs
- SocketAddress.cs
- PrtCap_Reader.cs
- Base64Stream.cs
- HttpClientChannel.cs
- RangeValueProviderWrapper.cs
- ConfigurationManagerHelper.cs
- QueryServiceConfigHandle.cs
- GridViewCellAutomationPeer.cs
- D3DImage.cs
- CodeExporter.cs
- EventLog.cs
- DeviceFilterEditorDialog.cs
- RuleSettingsCollection.cs
- TreeViewItem.cs
- TagPrefixCollection.cs
- XPathParser.cs
- ServiceSecurityContext.cs
- Button.cs
- RegexStringValidator.cs
- DecimalConverter.cs
- CodeBlockBuilder.cs
- DocumentPageTextView.cs
- FileChangesMonitor.cs