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
- BeginEvent.cs
- CodeCommentStatement.cs
- PartialCachingAttribute.cs
- DBDataPermission.cs
- ObsoleteAttribute.cs
- CreateUserWizard.cs
- MediaPlayerState.cs
- TypeDescriptionProvider.cs
- DbDataSourceEnumerator.cs
- LineBreakRecord.cs
- OutOfProcStateClientManager.cs
- XamlSerializationHelper.cs
- IntegerCollectionEditor.cs
- BindingSource.cs
- Console.cs
- DataGridCell.cs
- ResourceKey.cs
- IIS7WorkerRequest.cs
- XmlAttributeOverrides.cs
- WebPartUserCapability.cs
- SqlProviderManifest.cs
- OciHandle.cs
- ChooseAction.cs
- ConfigErrorGlyph.cs
- DataStreamFromComStream.cs
- DataServiceContext.cs
- DataGridViewCellPaintingEventArgs.cs
- QilTernary.cs
- AjaxFrameworkAssemblyAttribute.cs
- SafeLocalMemHandle.cs
- ZoneMembershipCondition.cs
- XmlUTF8TextReader.cs
- Item.cs
- TabPanel.cs
- SocketAddress.cs
- MemberDomainMap.cs
- PointAnimationClockResource.cs
- ContentTextAutomationPeer.cs
- TemplateBindingExpressionConverter.cs
- SiteMap.cs
- XPathQilFactory.cs
- PointLight.cs
- UniformGrid.cs
- SelectedDatesCollection.cs
- X509ScopedServiceCertificateElement.cs
- IndexingContentUnit.cs
- SimplePropertyEntry.cs
- ReferencedType.cs
- SqlFunctionAttribute.cs
- CompoundFileDeflateTransform.cs
- EncoderReplacementFallback.cs
- Convert.cs
- SamlEvidence.cs
- UriParserTemplates.cs
- RouteParameter.cs
- _CommandStream.cs
- SqlDataSourceConfigureSortForm.cs
- ASCIIEncoding.cs
- BufferAllocator.cs
- TimersDescriptionAttribute.cs
- _AutoWebProxyScriptHelper.cs
- FamilyMap.cs
- ServiceNameElementCollection.cs
- DataGridHeaderBorder.cs
- ToolStripDropDownMenu.cs
- XmlNodeReader.cs
- SimpleWorkerRequest.cs
- WindowsListViewGroupHelper.cs
- CacheAxisQuery.cs
- Effect.cs
- OutputCacheSection.cs
- MetafileHeaderEmf.cs
- BaseValidator.cs
- PageParser.cs
- ActivityIdHeader.cs
- HTTPNotFoundHandler.cs
- WindowProviderWrapper.cs
- ProfileSettings.cs
- WSSecurityPolicy11.cs
- MdImport.cs
- StandardBindingElementCollection.cs
- Style.cs
- ProfileEventArgs.cs
- ResourceReferenceKeyNotFoundException.cs
- BooleanProjectedSlot.cs
- PropertyEmitterBase.cs
- listviewsubitemcollectioneditor.cs
- DivideByZeroException.cs
- SiteMapNode.cs
- FontNamesConverter.cs
- ChildrenQuery.cs
- DesignerDataConnection.cs
- SrgsRulesCollection.cs
- QueryOpeningEnumerator.cs
- WebPartTransformerAttribute.cs
- ApplicationFileCodeDomTreeGenerator.cs
- SmtpReplyReader.cs
- TextOptionsInternal.cs
- ServiceEndpointCollection.cs
- ProbeDuplexCD1AsyncResult.cs