Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Documents / FixedPage.cs / 1305600 / FixedPage.cs
//---------------------------------------------------------------------------- //// Copyright (C) 2003 by Microsoft Corporation. All rights reserved. // // // Description: // Implements the FixedPage element // // History: // 06/03/2003 - Zhenbin Xu (ZhenbinX) - Created. // // http://edocs/payloads/Payloads%20Features/FixedPanelPage.mht // //--------------------------------------------------------------------------- namespace System.Windows.Documents { using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO.Packaging; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Documents.DocumentStructures; using System.Windows.Input; using System.Windows.Markup; using System.Windows.Media; using System.Windows.Navigation; using System.Windows.Shapes; using MS.Internal; using MS.Internal.Documents; using MS.Internal.Utility; //===================================================================== ////// FixedPage is the container element for a metafile that represents /// a single page of portable, high-fidelity content. /// /// As an object that represents a static page of content, the primary /// usage scenario for a FixedPage is inside a FixedDocument, a control /// that is specialized to represent FixedPages to the pagination architecture. /// The secondary scenario is to place a FixedPage inside a generic paginating /// control such as the FlowDocument; for this scenario, the FixedPage is configured /// to automatically set page breaks at the beginning and end of its content. /// [ContentProperty("Children")] public sealed class FixedPage : FrameworkElement, IAddChildInternal, IFixedNavigate, IUriContext { //------------------------------------------------------------------- // // Constructors // //---------------------------------------------------------------------- #region Constructors static FixedPage() { FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata(FlowDirection.LeftToRight, FrameworkPropertyMetadataOptions.AffectsParentArrange); metadata.CoerceValueCallback = new CoerceValueCallback(CoerceFlowDirection); FlowDirectionProperty.OverrideMetadata(typeof(FixedPage), metadata); // This puts the origin always at the top left of the page and prevents mirroring unless this is overridden. } ////// Default FixedPage constructor /// ////// Automatic determination of current Dispatcher. Use alternative constructor /// that accepts a Dispatcher for best performance. /// public FixedPage() : base() { Init(); } #endregion Constructors //------------------------------------------------------------------- // // Public Methods // //---------------------------------------------------------------------- #region Public Methods ////// Creates AutomationPeer ( protected override System.Windows.Automation.Peers.AutomationPeer OnCreateAutomationPeer() { return new System.Windows.Automation.Peers.FixedPageAutomationPeer(this); } ///) /// /// Responds to mouse wheel event, used to update debug visuals. /// MouseWheelEvent handler, initializes the context menu. /// protected override void OnPreviewMouseWheel(MouseWheelEventArgs e) { #if DEBUG if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift)) { int delta = e.Delta; e.Handled = true; if (delta > 0) { _drawDebugVisual--; } else { _drawDebugVisual++; } _drawDebugVisual = _drawDebugVisual % (int)DrawDebugVisual.LastOne; if (_drawDebugVisual < 0) { _drawDebugVisual += (int)DrawDebugVisual.LastOne; } InvalidateVisual(); // // For container, the first child of element is always a Path with Fill. // if (_uiElementCollection.Count != 0) { Path path = _uiElementCollection[0] as Path; if (path != null) { if (_drawDebugVisual == 0) { path.Visibility = Visibility.Visible; } else { path.Visibility = Visibility.Hidden; } } } } #endif } ////// Override from UIElement /// protected override void OnRender(DrawingContext dc) { // Draw background in rectangle inside border. Brush background = this.Background; if (background != null) { dc.DrawRectangle(background, null, new Rect(0, 0, RenderSize.Width, RenderSize.Height)); } #if DEBUG AdornerLayer al = AdornerLayer.GetAdornerLayer(this); if (al != null) { Adorner[] adorners = al.GetAdorners(this); if (adorners != null && adorners.Length > 0) { al.Update(this); } } #endif } ////// This method is called to Add the object as a child of the Panel. This method is used primarily /// by the parser. /// ///value is NULL. ///value is not of type UIElement. /// /// The object to add as a child; it must be a UIElement. /// ///void IAddChild.AddChild (Object value) { if (value == null) { throw new ArgumentNullException("value"); } UIElement uie = value as UIElement; if (uie == null) { throw new ArgumentException(SR.Get(SRID.UnexpectedParameterType, value.GetType(), typeof(UIElement)), "value"); } Children.Add(uie); } /// /// This method is called by the parser when text appears under the tag in markup. /// As default Panels do not support text, calling this method has no effect if the /// text is all whitespace. Passing non-whitespace text throws an exception. /// ///text contains non-whitespace text. /// /// Text to add as a child. /// void IAddChild.AddText (string text) { XamlSerializerUtil.ThrowIfNonWhiteSpaceInAddText(text, this); } ////// Reads the attached property Left from the given element. /// ///element is NULL. /// The element from which to read the Left attached property. ///The property's Length value. ///[TypeConverter("System.Windows.LengthConverter, PresentationFramework, Version=" + Microsoft.Internal.BuildInfo.WCP_VERSION + ", Culture=neutral, PublicKeyToken=" + Microsoft.Internal.BuildInfo.WCP_PUBLIC_KEY_TOKEN + ", Custom=null")] [AttachedPropertyBrowsableForChildren()] public static double GetLeft(UIElement element) { if (element == null) { throw new ArgumentNullException("element"); } return (double)element.GetValue(LeftProperty); } /// /// Writes the attached property Left to the given element. /// ///element is NULL. /// The element to which to write the Left attached property. /// The Length to set ///public static void SetLeft(UIElement element, double length) { if (element == null) { throw new ArgumentNullException("element"); } element.SetValue(LeftProperty, length); } /// /// Reads the attached property Top from the given element. /// ///element is NULL. /// The element from which to read the Top attached property. ///The property's Length value. ///[TypeConverter("System.Windows.LengthConverter, PresentationFramework, Version=" + Microsoft.Internal.BuildInfo.WCP_VERSION + ", Culture=neutral, PublicKeyToken=" + Microsoft.Internal.BuildInfo.WCP_PUBLIC_KEY_TOKEN + ", Custom=null")] [AttachedPropertyBrowsableForChildren()] public static double GetTop(UIElement element) { if (element == null) { throw new ArgumentNullException("element"); } return (double)element.GetValue(TopProperty); } /// /// Writes the attached property Top to the given element. /// ///element is NULL. /// The element to which to write the Top attached property. /// The Length to set ///public static void SetTop(UIElement element, double length) { if (element == null) { throw new ArgumentNullException("element"); } element.SetValue(TopProperty, length); } /// /// Reads the attached property Right from the given element. /// ///element is NULL. /// The element from which to read the Right attached property. ///The property's Length value. ///[TypeConverter("System.Windows.LengthConverter, PresentationFramework, Version=" + Microsoft.Internal.BuildInfo.WCP_VERSION + ", Culture=neutral, PublicKeyToken=" + Microsoft.Internal.BuildInfo.WCP_PUBLIC_KEY_TOKEN + ", Custom=null")] [AttachedPropertyBrowsableForChildren()] public static double GetRight(UIElement element) { if (element == null) { throw new ArgumentNullException("element"); } return (double)element.GetValue(RightProperty); } /// /// Writes the attached property Right to the given element. /// ///element is NULL. /// The element to which to write the Right attached property. /// The Length to set ///public static void SetRight(UIElement element, double length) { if (element == null) { throw new ArgumentNullException("element"); } element.SetValue(RightProperty, length); } /// /// Reads the attached property Bottom from the given element. /// ///element is NULL. /// The element from which to read the Bottom attached property. ///The property's Length value. ///[TypeConverter("System.Windows.LengthConverter, PresentationFramework, Version=" + Microsoft.Internal.BuildInfo.WCP_VERSION + ", Culture=neutral, PublicKeyToken=" + Microsoft.Internal.BuildInfo.WCP_PUBLIC_KEY_TOKEN + ", Custom=null")] [AttachedPropertyBrowsableForChildren()] public static double GetBottom(UIElement element) { if (element == null) { throw new ArgumentNullException("element"); } return (double)element.GetValue(BottomProperty); } /// /// Writes the attached property Bottom to the given element. /// ///element is NULL. /// The element to which to write the Bottom attached property. /// The Length to set ///public static void SetBottom(UIElement element, double length) { if (element == null) { throw new ArgumentNullException("element"); } element.SetValue(BottomProperty, length); } /// /// Reads the attached property NavigateUri from the given element. /// ///element is NULL. ///Should be kept here for compatibility since the attached property has moved from FixedPage to Hyperlink. [AttachedPropertyBrowsableForChildren()] public static Uri GetNavigateUri(UIElement element) { if (element == null) { throw new ArgumentNullException("element"); } return (Uri)element.GetValue(NavigateUriProperty); } ////// Writes the attached property NavigateUri to the given element. /// ///element is NULL. ///Should be kept here for compatibility since the attached property has moved from FixedPage to Hyperlink. public static void SetNavigateUri(UIElement element, Uri uri) { if (element == null) { throw new ArgumentNullException("element"); } element.SetValue(NavigateUriProperty, uri); } #endregion #region IUriContext ////// Uri IUriContext.BaseUri { get { return (Uri) GetValue(BaseUriHelper.BaseUriProperty); } set { SetValue(BaseUriHelper.BaseUriProperty, value); } } ////// /// Returns enumerator to logical children. /// protected internal override IEnumerator LogicalChildren { get { return this.Children.GetEnumerator(); } } #endregion IUriContext //-------------------------------------------------------------------- // // Public Properties // //--------------------------------------------------------------------- #region Public Properties ////// Returns a UIElementCollection of children for user to add/remove children manually /// Returns null if Panel is data-bound (no manual control of children is possible, /// the associated ItemsControl completely overrides children) /// Note: the derived Panel classes should never use this collection for any /// internal purposes! They should use Children instead, because Children /// is always present and either is a mirror of public Children collection (in case of Direct Panel) /// or is generated from data binding. /// [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public UIElementCollection Children { get { if(_uiElementCollection == null) //nobody used it yet { _uiElementCollection = CreateUIElementCollection(this); } return _uiElementCollection; } } ////// /// public static readonly DependencyProperty PrintTicketProperty = DependencyProperty.RegisterAttached( "PrintTicket", typeof(object), typeof(FixedPage), new FrameworkPropertyMetadata((object)null)); ////// Get/Set PrintTicket Property /// public object PrintTicket { get { return GetValue(PrintTicketProperty); } set { SetValue(PrintTicketProperty,value); } } ////// The Background property defines the brush used to fill the area between borders. /// public Brush Background { get { return (Brush) GetValue(BackgroundProperty); } set { SetValue(BackgroundProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty BackgroundProperty = Panel.BackgroundProperty.AddOwner( typeof(FixedPage), new FrameworkPropertyMetadata((Brush)Brushes.White, FrameworkPropertyMetadataOptions.AffectsRender)); ///property. /// /// This is the dependency property registered for the Canvas' Left attached property. /// /// The Left property is read by a Canvas on its children to determine where to position them. /// The child's offset from this property does not have an effect on the Canvas' own size. /// If you want offset to affect size, set the child's Margin property instead. /// Conflict between the Left and Right properties is resolved in favor of Left. /// Percentages are with respect to the Canvas' size. /// ///public static readonly DependencyProperty LeftProperty = DependencyProperty.RegisterAttached( "Left", typeof(double), typeof(FixedPage), new FrameworkPropertyMetadata(Double.NaN, FrameworkPropertyMetadataOptions.AffectsParentArrange)); /// /// This is the dependency property registered for the Canvas' Top attached property. /// /// The Top property is read by a Canvas on its children to determine where to position them. /// The child's offset from this property does not have an effect on the Canvas' own size. /// If you want offset to affect size, set the child's Margin property instead. /// Conflict between the Top and Bottom properties is resolved in favor of Top. /// Percentages are with respect to the Canvas' size. /// ///public static readonly DependencyProperty TopProperty = DependencyProperty.RegisterAttached( "Top", typeof(double), typeof(FixedPage), new FrameworkPropertyMetadata(Double.NaN, FrameworkPropertyMetadataOptions.AffectsParentArrange)); /// /// This is the dependency property registered for the Canvas' Right attached property. /// /// The Right property is read by a Canvas on its children to determine where to position them. /// The child's offset from this property does not have an effect on the Canvas' own size. /// If you want offset to affect size, set the child's Margin property instead. /// Conflict between the Left and Right properties is resolved in favor of Right. /// Percentages are with respect to the Canvas' size. /// ///public static readonly DependencyProperty RightProperty = DependencyProperty.RegisterAttached( "Right", typeof(double), typeof(FixedPage), new FrameworkPropertyMetadata(Double.NaN, FrameworkPropertyMetadataOptions.AffectsParentArrange)); /// /// This is the dependency property registered for the Canvas' Bottom attached property. /// /// The Bottom property is read by a Canvas on its children to determine where to position them. /// The child's offset from this property does not have an effect on the Canvas' own size. /// If you want offset to affect size, set the child's Margin property instead. /// Conflict between the Top and Bottom properties is resolved in favor of Bottom. /// Percentages are with respect to the Canvas' size. /// ///public static readonly DependencyProperty BottomProperty = DependencyProperty.RegisterAttached( "Bottom", typeof(double), typeof(FixedPage), new FrameworkPropertyMetadata(Double.NaN, FrameworkPropertyMetadataOptions.AffectsParentArrange)); /// /// The DependencyProperty for the ContentBox property. /// public Rect ContentBox { get { return (Rect) GetValue(ContentBoxProperty); } set { SetValue(ContentBoxProperty, value); } } ////// The DependencyProperty for the ContentBox property. /// public static readonly DependencyProperty ContentBoxProperty = DependencyProperty.Register( "ContentBox", typeof(Rect), typeof(FixedPage), new FrameworkPropertyMetadata(Rect.Empty)); ////// The DependencyProperty for the BleedBox property. /// public Rect BleedBox { get { return (Rect) GetValue(BleedBoxProperty); } set { SetValue(BleedBoxProperty, value); } } ////// The DependencyProperty for the BleedBox property. /// public static readonly DependencyProperty BleedBoxProperty = DependencyProperty.Register( "BleedBox", typeof(Rect), typeof(FixedPage), new FrameworkPropertyMetadata(Rect.Empty)); ////// Contains the target URI to navigate when a hyperlink is clicked /// public static readonly DependencyProperty NavigateUriProperty = DependencyProperty.RegisterAttached( "NavigateUri", typeof(Uri), typeof(FixedPage), new FrameworkPropertyMetadata( (Uri) null, new PropertyChangedCallback(Hyperlink.OnNavigateUriChanged), new CoerceValueCallback(Hyperlink.CoerceNavigateUri))); #endregion protected internal override void OnVisualParentChanged(DependencyObject oldParent) { base.OnVisualParentChanged(oldParent); if (oldParent == null) { HighlightVisual highlightVisual = HighlightVisual.GetHighlightVisual(this); AdornerLayer al = AdornerLayer.GetAdornerLayer(this); if (highlightVisual == null && al != null) { //Get Page Content PageContent pc = LogicalTreeHelper.GetParent(this) as PageContent; if (pc != null) { //Get FixedDocument FixedDocument doc = LogicalTreeHelper.GetParent(pc) as FixedDocument; if (doc != null) { if (al != null) { //The Text Selection adorner must have predefined ZOrder MaxInt/2, //we assign the ZOrder to annotation adorners respectively int zOrder = System.Int32.MaxValue / 2; al.Add(new HighlightVisual(doc, this),zOrder); } } } } #if DEBUG DebugVisualAdorner debugVisualAd = DebugVisualAdorner.GetDebugVisual(this); if (debugVisualAd == null && al != null) { al.Add(new DebugVisualAdorner(this), System.Int32.MaxValue / 4); } #endif } } private static object CoerceFlowDirection(DependencyObject page, Object flowDirection) { return FlowDirection.LeftToRight; } internal static bool CanNavigateToUri(Uri uri) { // Is http:, https:, mailto:, or file:? if (!uri.IsAbsoluteUri || uri.IsUnc || uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps || uri.Scheme == Uri.UriSchemeMailto || // Automation will request navigation to pack Uris when automating links withing a document (uri.Scheme == PackUriHelper.UriSchemePack && !String.IsNullOrEmpty(uri.Fragment))) { return true; } else { return SecurityHelper.CallerHasWebPermission(uri); } } internal static Uri GetLinkUri(IInputElement element, Uri inputUri) { DependencyObject dpo = element as DependencyObject; Debug.Assert(dpo != null, "GetLinkUri shouldn't be called for non-DependencyObjects."); if (inputUri != null && (CanNavigateToUri(inputUri) || (inputUri.Scheme == PackUriHelper.UriSchemePack && !String.IsNullOrEmpty(inputUri.Fragment)))) // We want to allow navigation to pack:// Uris as we may get these from automation, but we // wouldn't support this if an actual Uri were given as a pack:// Uri { // // First remove the fragment, this is to prevent escape in file URI case, for example, // if the inputUri = "..\..\myFile.xaml#fragment", without removing the fragment first, // the absoluteUri would be "file:///...../myFile.xaml%23fragment", note # is escaped to // %23. // If indeed the file contains # such as "This#File.xaml", it should set // FixedPage.NavigateUri="This%23File.xaml" // // // Copy from BindUriHelper.GetFragment STARTS. // It should have a version return #, otherwise, you can // not tell betweeen myFile.xaml and myFile.xaml# // Uri workuri = inputUri; if (inputUri.IsAbsoluteUri == false) { // this is a relative uri, and Fragement() doesn't work with relative uris. The base uri is completley irrelevant // here and will never affect the returned fragment, but the method requires something to be there. Therefore, // we will use "http://microsoft.com" as a convenient substitute. workuri = new Uri(new Uri("http://microsoft.com/"), inputUri); } // Copy from BindUriHelper.GetFragment ENDS. // the fragmene will include # sign String fragment = workuri.Fragment; int fragmentLength = (fragment == null) ? 0 : fragment.Length; if (fragmentLength != 0) { String inputUriString = inputUri.ToString(); String inputUriStringWithoutFragment = inputUriString.Substring(0, inputUriString.IndexOf('#')); inputUri = new Uri(inputUriStringWithoutFragment, UriKind.RelativeOrAbsolute); //Only Check for the startpart uri if the hyperlink is relative, else it's not part of the package if (inputUri.IsAbsoluteUri == false) { String startPartUriString = GetStartPartUriString(dpo); if (startPartUriString != null) { inputUri = new Uri(startPartUriString, UriKind.RelativeOrAbsolute); } } } // // Resolve to absolute URI // Uri baseUri = BaseUriHelper.GetBaseUri(dpo); Uri absoluteUri = BindUriHelper.GetUriToNavigate(dpo, baseUri, inputUri); if (fragmentLength != 0) { StringBuilder absoluteUriString = new StringBuilder(absoluteUri.ToString()); absoluteUriString.Append(fragment); absoluteUri = new Uri(absoluteUriString.ToString(), UriKind.RelativeOrAbsolute); } return absoluteUri; } return null; } //-------------------------------------------------------------------- // // Public Events // //--------------------------------------------------------------------- //------------------------------------------------------------------- // // Protected Methods // //--------------------------------------------------------------------- #region Protected Methods ////// Gets the Visual children count. /// protected override int VisualChildrenCount { get { if (_uiElementCollection == null) { return 0; } else { return _uiElementCollection.Count; } } } ////// Gets the Visual child at the specified index. /// protected override Visual GetVisualChild(int index) { if (_uiElementCollection == null) { throw new ArgumentOutOfRangeException("index", index, SR.Get(SRID.Visual_ArgumentOutOfRange)); } return _uiElementCollection[index]; } ////// Creates a new UIElementCollection. Panel-derived class can create its own version of /// UIElementCollection -derived class to add cached information to every child or to /// intercept any Add/Remove actions (for example, for incremental layout update) /// private UIElementCollection CreateUIElementCollection(FrameworkElement logicalParent) { return new UIElementCollection(this, logicalParent); } ////// Updates DesiredSize of the Canvas. Called by parent UIElement. This is the first pass of layout. /// ////// Canvas measures each of its children accounting for any of their FrameworkElement properties. /// Children will be passed either the parent's constraint less any margin on the child or their /// explicitly specified (Min/Max)Width/Height properties. /// /// If it has enough space, Canvas will return a size large enough to accommodate all children's /// desired sizes and margins. Children's Top/Left/Bottom/Right properties are not considered in /// this method. If it does not have enough space to accommodate its children in a dimension, this /// will simply return the full constraint in that dimension. /// /// Constraint size is an "upper limit" that Canvas should not exceed. ///Canvas' desired size. protected override Size MeasureOverride(Size constraint) { Size childConstraint = new Size(Double.PositiveInfinity, Double.PositiveInfinity); foreach (UIElement child in Children) { child.Measure(childConstraint); } return new Size(); } ////// Canvas computes a position for each of its children taking into account their margin and /// attached Canvas properties: Top, Left, Bottom, and Right. If specified, Top or Left take /// priority over Bottom or Right. /// /// Canvas will also arrange each of its children. /// /// Size that Canvas will assume to position children. protected override Size ArrangeOverride(Size arrangeSize) { //Canvas arranges children at their DesiredSize. //This means that Margin on children is actually respected and added //to the size of layout partition for a child. //Therefore, is Margin is 10 and Left is 20, the child's ink will start at 30. foreach (UIElement child in Children) { double x = 0; double y = 0; //Compute offset of the child: //If Left is specified, then Right is ignored //If Left is not specified, then Right is used //If both are not there, then 0 double left = GetLeft(child); if(!DoubleUtil.IsNaN(left)) { x = left; } else { double right = GetRight(child); if(!DoubleUtil.IsNaN(right)) { x = arrangeSize.Width - child.DesiredSize.Width - right; } } double top = GetTop(child); if(!DoubleUtil.IsNaN(top)) { y = top; } else { double bottom = GetBottom(child); if(!DoubleUtil.IsNaN(bottom)) { y = arrangeSize.Height - child.DesiredSize.Height - bottom; } } child.Arrange(new Rect(new Point(x, y), child.DesiredSize)); } return arrangeSize; } #endregion //-------------------------------------------------------------------- // // Internal Methods // //--------------------------------------------------------------------- #region Internal methods void IFixedNavigate.NavigateAsync(string elementID) { FixedHyperLink.NavigateToElement(this, elementID); } UIElement IFixedNavigate.FindElementByID(string elementID, out FixedPage rootFixedPage) { UIElement uiElementRet = null; rootFixedPage = this; // We need iterate through the PageContentCollect first. UIElementCollection elementCollection = this.Children; UIElement uiElement; DependencyObject node ; for (int i = 0, n = elementCollection.Count; i < n; i++) { uiElement = elementCollection[i]; node = LogicalTreeHelper.FindLogicalNode(uiElement, elementID); if (node != null) { uiElementRet = node as UIElement; break; } } return uiElementRet; } // Create a FixedNode representing this glyphs or image internal FixedNode CreateFixedNode(int pageIndex, UIElement e) { // Should we check here to make sure this is a selectable element? Debug.Assert(e != null); return _CreateFixedNode(pageIndex, e); } internal Glyphs GetGlyphsElement(FixedNode node) { return GetElement(node) as Glyphs; } // FixedNode represents a leaf node. It contains a path // from root to the leaf in the form of child index. // [Level1 ChildIndex] [Level2 ChildIndex] [Level3 ChildIndex]... internal DependencyObject GetElement(FixedNode node) { int currentLevelIndex = node[1]; if (!(currentLevelIndex >= 0 && currentLevelIndex <= this.Children.Count)) { return null; } #if DEBUG if (node.ChildLevels > 1) { DocumentsTrace.FixedFormat.FixedDocument.Trace(string.Format("FixedPage.GetUIElement {0} is nested element", node)); } #endif DependencyObject element = this.Children[currentLevelIndex]; for (int level = 2; level <= node.ChildLevels; level++) { // Follow the path if necessary currentLevelIndex = node[level]; if (element is Canvas) { // Canvas is a known S0 grouping element. // Boundary Node only would appear in first level! Debug.Assert(currentLevelIndex >= 0 && currentLevelIndex <= ((Canvas)element).Children.Count); element = ((Canvas)element).Children[currentLevelIndex]; } else { DocumentsTrace.FixedFormat.FixedDocument.Trace(string.Format("FixedPage.GeElement {0} is non S0 grouping element in L[{1}]!", node, level)); IEnumerable currentChildrens = LogicalTreeHelper.GetChildren((DependencyObject)element); if (currentChildrens == null) { DocumentsTrace.FixedFormat.FixedDocument.Trace(string.Format("FixedPage.GetElement {0} is NOT a grouping element in L[{1}]!!!", node, level)); return null; } // We have no uniform way to do random access for this element. // This should never happen for S0 conforming document. int childIndex = -1; IEnumerator itor = currentChildrens.GetEnumerator(); while (itor.MoveNext()) { childIndex++; if (childIndex == currentLevelIndex) { element = (DependencyObject)itor.Current; break; } } } } #if DEBUG if (!(element is Glyphs)) { DocumentsTrace.FixedFormat.FixedDocument.Trace(string.Format("FixedPage.GetElement{0} is non-Glyphs", node)); } #endif return element; } #endregion Internal Methods #region Internal Properties internal String StartPartUriString { get { return _startPartUriString; } set { _startPartUriString = value; } } private String _startPartUriString; #if DEBUG internal FixedPageStructure FixedPageStructure { get { return _fixedPageStructure; } set { _fixedPageStructure = value; } } internal int DrawDebugVisualSelection { get { return _drawDebugVisual; } } #endif #endregion Internal Properties //-------------------------------------------------------------------- // // private Properties // //---------------------------------------------------------------------- private UIElementCollection _uiElementCollection; //------------------------------------------------------------------- // // Private Methods // //---------------------------------------------------------------------- #region Private Methods private void Init() { if (XpsValidatingLoader.DocumentMode) { this.InheritanceBehavior = InheritanceBehavior.SkipAllNext; } } ////// internal StoryFragments GetPageStructure() { StoryFragments sf; sf = FixedDocument.GetStoryFragments(this); return sf; } internal int[] _CreateChildIndex(DependencyObject e) { ArrayList childPath = new ArrayList(); while (e != this) { DependencyObject parent = LogicalTreeHelper.GetParent(e); int childIndex = -1; if (parent is FixedPage) { childIndex = ((FixedPage)parent).Children.IndexOf((UIElement)e); } else if (parent is Canvas) { childIndex = ((Canvas)parent).Children.IndexOf((UIElement)e); } else { IEnumerable currentChildrens = LogicalTreeHelper.GetChildren(parent); Debug.Assert(currentChildrens != null); // We have no uniform way to do random access for this element. // This should never happen for S0 conforming document. IEnumerator itor = currentChildrens.GetEnumerator(); while (itor.MoveNext()) { childIndex++; if (itor.Current == e) { break; } } } childPath.Insert(0, childIndex); e = parent; } while (e != this) ; return (int[])childPath.ToArray(typeof(int)); } // Making this function private and only expose the versions // that take S0 elements as parameter. private FixedNode _CreateFixedNode(int pageIndex, UIElement e) { return FixedNode.Create(pageIndex, _CreateChildIndex(e)); } ////// /// This function walks the logical tree for the FixedDocumentSequence and then /// retrieves its URI. We use this Uri for fragment navigation during a FixedPage.OnClick /// event. /// /// ///private static String GetStartPartUriString(DependencyObject current) { //1) Get FixedPage from DependcyObject's InheritanceObject property DependencyObject obj = current; FixedPage fixedPage = current as FixedPage; while (fixedPage == null && obj != null) { obj = obj.InheritanceParent; fixedPage = obj as FixedPage; } if (fixedPage == null) { return null; } //2) Check if fixedPage StartPartUri is null if (fixedPage.StartPartUriString == null) { //3) Walk Logical Tree to the FixedDocumentSequence DependencyObject parent = LogicalTreeHelper.GetParent(current); while (parent != null) { FixedDocumentSequence docSequence = parent as FixedDocumentSequence; if (docSequence != null) { //4) Retrieve DocumentSequence Uri Uri startPartUri = ((IUriContext)docSequence).BaseUri; if (startPartUri != null) { String startPartUriString = startPartUri.ToString(); // If there is a fragment we need to strip it off String fragment = startPartUri.Fragment; int fragmentLength = (fragment == null) ? 0 : fragment.Length; if (fragmentLength != 0) { fixedPage.StartPartUriString = startPartUriString.Substring(0, startPartUriString.IndexOf('#')); } else { fixedPage.StartPartUriString = startPartUri.ToString(); } } break; } parent = LogicalTreeHelper.GetParent(parent); } //If we don't have a starting part Uri, assign fixedPage.StartPartUriString to Empty so //we don't try to look it up again. if (fixedPage.StartPartUriString == null) { fixedPage.StartPartUriString = String.Empty; } } if (fixedPage.StartPartUriString == String.Empty) { return null; } else { return fixedPage.StartPartUriString; } } #endregion //------------------------------------------------------------------- // // Private Fields // //--------------------------------------------------------------------- #if DEBUG private FixedPageStructure _fixedPageStructure; // // The debugging features: set to true will draw the bounding box for each // line from the analyzed layout results. // private int _drawDebugVisual = 0; #endif } #if DEBUG internal sealed class DebugVisualAdorner: Adorner { internal DebugVisualAdorner(FixedPage page) : base(page) { _fixedPage = page; } override protected void OnRender(DrawingContext dc) { if (_fixedPage.DrawDebugVisualSelection == (int) DrawDebugVisual.None) { return; } FixedPageStructure pageStructure = _fixedPage.FixedPageStructure; Debug.Assert(pageStructure != null); if (_fixedPage.DrawDebugVisualSelection == (int) DrawDebugVisual.Glyphs) { if (pageStructure.FixedNodes != null) { _RenderMarkupOrder(dc, pageStructure.FixedNodes); } } else if (_fixedPage.DrawDebugVisualSelection == (int) DrawDebugVisual.Lines) { pageStructure.RenderLines(dc); } else { if (pageStructure.FixedSOMPage != null) { pageStructure.FixedSOMPage.Render(dc, null, (DrawDebugVisual) _fixedPage.DrawDebugVisualSelection); } else { //Explicit document structure FlowNode[] pageNodes = _fixedPage.FixedPageStructure.FlowNodes; int flowOrder = 0; foreach (FlowNode node in pageNodes) { if (node != null && node.FixedSOMElements != null) { foreach (FixedSOMElement somElement in node.FixedSOMElements) { somElement.Render(dc, flowOrder.ToString(), (DrawDebugVisual) _fixedPage.DrawDebugVisualSelection); flowOrder++; } } } } } } internal static DebugVisualAdorner GetDebugVisual(FixedPage page) { AdornerLayer al = AdornerLayer.GetAdornerLayer(page); DebugVisualAdorner debugVisualAd; if (al == null) { return null; } Adorner[] adorners = al.GetAdorners(page); if (adorners != null) { foreach (Adorner ad in adorners) { debugVisualAd = ad as DebugVisualAdorner; if (debugVisualAd != null) { return debugVisualAd; } } } return null; } private void _RenderMarkupOrder(DrawingContext dc, List markupOrder) { int order = 0; foreach (FixedNode node in markupOrder) { DependencyObject ob = _fixedPage.GetElement(node); Glyphs glyphs = ob as Glyphs; Path path = ob as Path; if (glyphs != null) { GlyphRun glyphRun = glyphs.ToGlyphRun(); Rect alignmentBox = glyphRun.ComputeAlignmentBox(); alignmentBox.Offset(glyphs.OriginX, glyphs.OriginY); GeneralTransform transform = glyphs.TransformToAncestor(_fixedPage); alignmentBox = transform.TransformBounds(alignmentBox); Pen pen = new Pen(Brushes.Green, 1); dc.DrawRectangle(null, pen , alignmentBox); _RenderLabel(dc, order.ToString(), alignmentBox); ++order; } else if (path != null) { Geometry renderGeom = path.RenderedGeometry; Pen backgroundPen = new Pen(Brushes.Black,1); dc.DrawGeometry(null, backgroundPen, renderGeom); _RenderLabel(dc, order.ToString(), renderGeom.Bounds); ++order; } } } private void _RenderLabel(DrawingContext dc, string label, Rect boundingRect) { FormattedText ft = new FormattedText(label, System.Windows.Markup.TypeConverterHelper.InvariantEnglishUS, FlowDirection.LeftToRight, new Typeface("Arial"), 10, Brushes.White); Point labelLocation = new Point(boundingRect.Left-25, (boundingRect.Bottom + boundingRect.Top)/2 - 10); Geometry geom = ft.BuildHighlightGeometry(labelLocation); Pen backgroundPen = new Pen(Brushes.Black,1); dc.DrawGeometry(Brushes.Black, backgroundPen, geom); dc.DrawText(ft, labelLocation); } private FixedPage _fixedPage; } internal enum DrawDebugVisual { None = 0, Glyphs = 1, Lines = 2, TextRuns = 3, Paragraphs = 4, Groups = 5, LastOne = 6 } #endif } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------------------- // // Copyright (C) 2003 by Microsoft Corporation. All rights reserved. // // // Description: // Implements the FixedPage element // // History: // 06/03/2003 - Zhenbin Xu (ZhenbinX) - Created. // // http://edocs/payloads/Payloads%20Features/FixedPanelPage.mht // //--------------------------------------------------------------------------- namespace System.Windows.Documents { using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO.Packaging; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Documents.DocumentStructures; using System.Windows.Input; using System.Windows.Markup; using System.Windows.Media; using System.Windows.Navigation; using System.Windows.Shapes; using MS.Internal; using MS.Internal.Documents; using MS.Internal.Utility; //===================================================================== ////// FixedPage is the container element for a metafile that represents /// a single page of portable, high-fidelity content. /// /// As an object that represents a static page of content, the primary /// usage scenario for a FixedPage is inside a FixedDocument, a control /// that is specialized to represent FixedPages to the pagination architecture. /// The secondary scenario is to place a FixedPage inside a generic paginating /// control such as the FlowDocument; for this scenario, the FixedPage is configured /// to automatically set page breaks at the beginning and end of its content. /// [ContentProperty("Children")] public sealed class FixedPage : FrameworkElement, IAddChildInternal, IFixedNavigate, IUriContext { //------------------------------------------------------------------- // // Constructors // //---------------------------------------------------------------------- #region Constructors static FixedPage() { FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata(FlowDirection.LeftToRight, FrameworkPropertyMetadataOptions.AffectsParentArrange); metadata.CoerceValueCallback = new CoerceValueCallback(CoerceFlowDirection); FlowDirectionProperty.OverrideMetadata(typeof(FixedPage), metadata); // This puts the origin always at the top left of the page and prevents mirroring unless this is overridden. } ////// Default FixedPage constructor /// ////// Automatic determination of current Dispatcher. Use alternative constructor /// that accepts a Dispatcher for best performance. /// public FixedPage() : base() { Init(); } #endregion Constructors //------------------------------------------------------------------- // // Public Methods // //---------------------------------------------------------------------- #region Public Methods ////// Creates AutomationPeer ( protected override System.Windows.Automation.Peers.AutomationPeer OnCreateAutomationPeer() { return new System.Windows.Automation.Peers.FixedPageAutomationPeer(this); } ///) /// /// Responds to mouse wheel event, used to update debug visuals. /// MouseWheelEvent handler, initializes the context menu. /// protected override void OnPreviewMouseWheel(MouseWheelEventArgs e) { #if DEBUG if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift)) { int delta = e.Delta; e.Handled = true; if (delta > 0) { _drawDebugVisual--; } else { _drawDebugVisual++; } _drawDebugVisual = _drawDebugVisual % (int)DrawDebugVisual.LastOne; if (_drawDebugVisual < 0) { _drawDebugVisual += (int)DrawDebugVisual.LastOne; } InvalidateVisual(); // // For container, the first child of element is always a Path with Fill. // if (_uiElementCollection.Count != 0) { Path path = _uiElementCollection[0] as Path; if (path != null) { if (_drawDebugVisual == 0) { path.Visibility = Visibility.Visible; } else { path.Visibility = Visibility.Hidden; } } } } #endif } ////// Override from UIElement /// protected override void OnRender(DrawingContext dc) { // Draw background in rectangle inside border. Brush background = this.Background; if (background != null) { dc.DrawRectangle(background, null, new Rect(0, 0, RenderSize.Width, RenderSize.Height)); } #if DEBUG AdornerLayer al = AdornerLayer.GetAdornerLayer(this); if (al != null) { Adorner[] adorners = al.GetAdorners(this); if (adorners != null && adorners.Length > 0) { al.Update(this); } } #endif } ////// This method is called to Add the object as a child of the Panel. This method is used primarily /// by the parser. /// ///value is NULL. ///value is not of type UIElement. /// /// The object to add as a child; it must be a UIElement. /// ///void IAddChild.AddChild (Object value) { if (value == null) { throw new ArgumentNullException("value"); } UIElement uie = value as UIElement; if (uie == null) { throw new ArgumentException(SR.Get(SRID.UnexpectedParameterType, value.GetType(), typeof(UIElement)), "value"); } Children.Add(uie); } /// /// This method is called by the parser when text appears under the tag in markup. /// As default Panels do not support text, calling this method has no effect if the /// text is all whitespace. Passing non-whitespace text throws an exception. /// ///text contains non-whitespace text. /// /// Text to add as a child. /// void IAddChild.AddText (string text) { XamlSerializerUtil.ThrowIfNonWhiteSpaceInAddText(text, this); } ////// Reads the attached property Left from the given element. /// ///element is NULL. /// The element from which to read the Left attached property. ///The property's Length value. ///[TypeConverter("System.Windows.LengthConverter, PresentationFramework, Version=" + Microsoft.Internal.BuildInfo.WCP_VERSION + ", Culture=neutral, PublicKeyToken=" + Microsoft.Internal.BuildInfo.WCP_PUBLIC_KEY_TOKEN + ", Custom=null")] [AttachedPropertyBrowsableForChildren()] public static double GetLeft(UIElement element) { if (element == null) { throw new ArgumentNullException("element"); } return (double)element.GetValue(LeftProperty); } /// /// Writes the attached property Left to the given element. /// ///element is NULL. /// The element to which to write the Left attached property. /// The Length to set ///public static void SetLeft(UIElement element, double length) { if (element == null) { throw new ArgumentNullException("element"); } element.SetValue(LeftProperty, length); } /// /// Reads the attached property Top from the given element. /// ///element is NULL. /// The element from which to read the Top attached property. ///The property's Length value. ///[TypeConverter("System.Windows.LengthConverter, PresentationFramework, Version=" + Microsoft.Internal.BuildInfo.WCP_VERSION + ", Culture=neutral, PublicKeyToken=" + Microsoft.Internal.BuildInfo.WCP_PUBLIC_KEY_TOKEN + ", Custom=null")] [AttachedPropertyBrowsableForChildren()] public static double GetTop(UIElement element) { if (element == null) { throw new ArgumentNullException("element"); } return (double)element.GetValue(TopProperty); } /// /// Writes the attached property Top to the given element. /// ///element is NULL. /// The element to which to write the Top attached property. /// The Length to set ///public static void SetTop(UIElement element, double length) { if (element == null) { throw new ArgumentNullException("element"); } element.SetValue(TopProperty, length); } /// /// Reads the attached property Right from the given element. /// ///element is NULL. /// The element from which to read the Right attached property. ///The property's Length value. ///[TypeConverter("System.Windows.LengthConverter, PresentationFramework, Version=" + Microsoft.Internal.BuildInfo.WCP_VERSION + ", Culture=neutral, PublicKeyToken=" + Microsoft.Internal.BuildInfo.WCP_PUBLIC_KEY_TOKEN + ", Custom=null")] [AttachedPropertyBrowsableForChildren()] public static double GetRight(UIElement element) { if (element == null) { throw new ArgumentNullException("element"); } return (double)element.GetValue(RightProperty); } /// /// Writes the attached property Right to the given element. /// ///element is NULL. /// The element to which to write the Right attached property. /// The Length to set ///public static void SetRight(UIElement element, double length) { if (element == null) { throw new ArgumentNullException("element"); } element.SetValue(RightProperty, length); } /// /// Reads the attached property Bottom from the given element. /// ///element is NULL. /// The element from which to read the Bottom attached property. ///The property's Length value. ///[TypeConverter("System.Windows.LengthConverter, PresentationFramework, Version=" + Microsoft.Internal.BuildInfo.WCP_VERSION + ", Culture=neutral, PublicKeyToken=" + Microsoft.Internal.BuildInfo.WCP_PUBLIC_KEY_TOKEN + ", Custom=null")] [AttachedPropertyBrowsableForChildren()] public static double GetBottom(UIElement element) { if (element == null) { throw new ArgumentNullException("element"); } return (double)element.GetValue(BottomProperty); } /// /// Writes the attached property Bottom to the given element. /// ///element is NULL. /// The element to which to write the Bottom attached property. /// The Length to set ///public static void SetBottom(UIElement element, double length) { if (element == null) { throw new ArgumentNullException("element"); } element.SetValue(BottomProperty, length); } /// /// Reads the attached property NavigateUri from the given element. /// ///element is NULL. ///Should be kept here for compatibility since the attached property has moved from FixedPage to Hyperlink. [AttachedPropertyBrowsableForChildren()] public static Uri GetNavigateUri(UIElement element) { if (element == null) { throw new ArgumentNullException("element"); } return (Uri)element.GetValue(NavigateUriProperty); } ////// Writes the attached property NavigateUri to the given element. /// ///element is NULL. ///Should be kept here for compatibility since the attached property has moved from FixedPage to Hyperlink. public static void SetNavigateUri(UIElement element, Uri uri) { if (element == null) { throw new ArgumentNullException("element"); } element.SetValue(NavigateUriProperty, uri); } #endregion #region IUriContext ////// Uri IUriContext.BaseUri { get { return (Uri) GetValue(BaseUriHelper.BaseUriProperty); } set { SetValue(BaseUriHelper.BaseUriProperty, value); } } ////// /// Returns enumerator to logical children. /// protected internal override IEnumerator LogicalChildren { get { return this.Children.GetEnumerator(); } } #endregion IUriContext //-------------------------------------------------------------------- // // Public Properties // //--------------------------------------------------------------------- #region Public Properties ////// Returns a UIElementCollection of children for user to add/remove children manually /// Returns null if Panel is data-bound (no manual control of children is possible, /// the associated ItemsControl completely overrides children) /// Note: the derived Panel classes should never use this collection for any /// internal purposes! They should use Children instead, because Children /// is always present and either is a mirror of public Children collection (in case of Direct Panel) /// or is generated from data binding. /// [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public UIElementCollection Children { get { if(_uiElementCollection == null) //nobody used it yet { _uiElementCollection = CreateUIElementCollection(this); } return _uiElementCollection; } } ////// /// public static readonly DependencyProperty PrintTicketProperty = DependencyProperty.RegisterAttached( "PrintTicket", typeof(object), typeof(FixedPage), new FrameworkPropertyMetadata((object)null)); ////// Get/Set PrintTicket Property /// public object PrintTicket { get { return GetValue(PrintTicketProperty); } set { SetValue(PrintTicketProperty,value); } } ////// The Background property defines the brush used to fill the area between borders. /// public Brush Background { get { return (Brush) GetValue(BackgroundProperty); } set { SetValue(BackgroundProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty BackgroundProperty = Panel.BackgroundProperty.AddOwner( typeof(FixedPage), new FrameworkPropertyMetadata((Brush)Brushes.White, FrameworkPropertyMetadataOptions.AffectsRender)); ///property. /// /// This is the dependency property registered for the Canvas' Left attached property. /// /// The Left property is read by a Canvas on its children to determine where to position them. /// The child's offset from this property does not have an effect on the Canvas' own size. /// If you want offset to affect size, set the child's Margin property instead. /// Conflict between the Left and Right properties is resolved in favor of Left. /// Percentages are with respect to the Canvas' size. /// ///public static readonly DependencyProperty LeftProperty = DependencyProperty.RegisterAttached( "Left", typeof(double), typeof(FixedPage), new FrameworkPropertyMetadata(Double.NaN, FrameworkPropertyMetadataOptions.AffectsParentArrange)); /// /// This is the dependency property registered for the Canvas' Top attached property. /// /// The Top property is read by a Canvas on its children to determine where to position them. /// The child's offset from this property does not have an effect on the Canvas' own size. /// If you want offset to affect size, set the child's Margin property instead. /// Conflict between the Top and Bottom properties is resolved in favor of Top. /// Percentages are with respect to the Canvas' size. /// ///public static readonly DependencyProperty TopProperty = DependencyProperty.RegisterAttached( "Top", typeof(double), typeof(FixedPage), new FrameworkPropertyMetadata(Double.NaN, FrameworkPropertyMetadataOptions.AffectsParentArrange)); /// /// This is the dependency property registered for the Canvas' Right attached property. /// /// The Right property is read by a Canvas on its children to determine where to position them. /// The child's offset from this property does not have an effect on the Canvas' own size. /// If you want offset to affect size, set the child's Margin property instead. /// Conflict between the Left and Right properties is resolved in favor of Right. /// Percentages are with respect to the Canvas' size. /// ///public static readonly DependencyProperty RightProperty = DependencyProperty.RegisterAttached( "Right", typeof(double), typeof(FixedPage), new FrameworkPropertyMetadata(Double.NaN, FrameworkPropertyMetadataOptions.AffectsParentArrange)); /// /// This is the dependency property registered for the Canvas' Bottom attached property. /// /// The Bottom property is read by a Canvas on its children to determine where to position them. /// The child's offset from this property does not have an effect on the Canvas' own size. /// If you want offset to affect size, set the child's Margin property instead. /// Conflict between the Top and Bottom properties is resolved in favor of Bottom. /// Percentages are with respect to the Canvas' size. /// ///public static readonly DependencyProperty BottomProperty = DependencyProperty.RegisterAttached( "Bottom", typeof(double), typeof(FixedPage), new FrameworkPropertyMetadata(Double.NaN, FrameworkPropertyMetadataOptions.AffectsParentArrange)); /// /// The DependencyProperty for the ContentBox property. /// public Rect ContentBox { get { return (Rect) GetValue(ContentBoxProperty); } set { SetValue(ContentBoxProperty, value); } } ////// The DependencyProperty for the ContentBox property. /// public static readonly DependencyProperty ContentBoxProperty = DependencyProperty.Register( "ContentBox", typeof(Rect), typeof(FixedPage), new FrameworkPropertyMetadata(Rect.Empty)); ////// The DependencyProperty for the BleedBox property. /// public Rect BleedBox { get { return (Rect) GetValue(BleedBoxProperty); } set { SetValue(BleedBoxProperty, value); } } ////// The DependencyProperty for the BleedBox property. /// public static readonly DependencyProperty BleedBoxProperty = DependencyProperty.Register( "BleedBox", typeof(Rect), typeof(FixedPage), new FrameworkPropertyMetadata(Rect.Empty)); ////// Contains the target URI to navigate when a hyperlink is clicked /// public static readonly DependencyProperty NavigateUriProperty = DependencyProperty.RegisterAttached( "NavigateUri", typeof(Uri), typeof(FixedPage), new FrameworkPropertyMetadata( (Uri) null, new PropertyChangedCallback(Hyperlink.OnNavigateUriChanged), new CoerceValueCallback(Hyperlink.CoerceNavigateUri))); #endregion protected internal override void OnVisualParentChanged(DependencyObject oldParent) { base.OnVisualParentChanged(oldParent); if (oldParent == null) { HighlightVisual highlightVisual = HighlightVisual.GetHighlightVisual(this); AdornerLayer al = AdornerLayer.GetAdornerLayer(this); if (highlightVisual == null && al != null) { //Get Page Content PageContent pc = LogicalTreeHelper.GetParent(this) as PageContent; if (pc != null) { //Get FixedDocument FixedDocument doc = LogicalTreeHelper.GetParent(pc) as FixedDocument; if (doc != null) { if (al != null) { //The Text Selection adorner must have predefined ZOrder MaxInt/2, //we assign the ZOrder to annotation adorners respectively int zOrder = System.Int32.MaxValue / 2; al.Add(new HighlightVisual(doc, this),zOrder); } } } } #if DEBUG DebugVisualAdorner debugVisualAd = DebugVisualAdorner.GetDebugVisual(this); if (debugVisualAd == null && al != null) { al.Add(new DebugVisualAdorner(this), System.Int32.MaxValue / 4); } #endif } } private static object CoerceFlowDirection(DependencyObject page, Object flowDirection) { return FlowDirection.LeftToRight; } internal static bool CanNavigateToUri(Uri uri) { // Is http:, https:, mailto:, or file:? if (!uri.IsAbsoluteUri || uri.IsUnc || uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps || uri.Scheme == Uri.UriSchemeMailto || // Automation will request navigation to pack Uris when automating links withing a document (uri.Scheme == PackUriHelper.UriSchemePack && !String.IsNullOrEmpty(uri.Fragment))) { return true; } else { return SecurityHelper.CallerHasWebPermission(uri); } } internal static Uri GetLinkUri(IInputElement element, Uri inputUri) { DependencyObject dpo = element as DependencyObject; Debug.Assert(dpo != null, "GetLinkUri shouldn't be called for non-DependencyObjects."); if (inputUri != null && (CanNavigateToUri(inputUri) || (inputUri.Scheme == PackUriHelper.UriSchemePack && !String.IsNullOrEmpty(inputUri.Fragment)))) // We want to allow navigation to pack:// Uris as we may get these from automation, but we // wouldn't support this if an actual Uri were given as a pack:// Uri { // // First remove the fragment, this is to prevent escape in file URI case, for example, // if the inputUri = "..\..\myFile.xaml#fragment", without removing the fragment first, // the absoluteUri would be "file:///...../myFile.xaml%23fragment", note # is escaped to // %23. // If indeed the file contains # such as "This#File.xaml", it should set // FixedPage.NavigateUri="This%23File.xaml" // // // Copy from BindUriHelper.GetFragment STARTS. // It should have a version return #, otherwise, you can // not tell betweeen myFile.xaml and myFile.xaml# // Uri workuri = inputUri; if (inputUri.IsAbsoluteUri == false) { // this is a relative uri, and Fragement() doesn't work with relative uris. The base uri is completley irrelevant // here and will never affect the returned fragment, but the method requires something to be there. Therefore, // we will use "http://microsoft.com" as a convenient substitute. workuri = new Uri(new Uri("http://microsoft.com/"), inputUri); } // Copy from BindUriHelper.GetFragment ENDS. // the fragmene will include # sign String fragment = workuri.Fragment; int fragmentLength = (fragment == null) ? 0 : fragment.Length; if (fragmentLength != 0) { String inputUriString = inputUri.ToString(); String inputUriStringWithoutFragment = inputUriString.Substring(0, inputUriString.IndexOf('#')); inputUri = new Uri(inputUriStringWithoutFragment, UriKind.RelativeOrAbsolute); //Only Check for the startpart uri if the hyperlink is relative, else it's not part of the package if (inputUri.IsAbsoluteUri == false) { String startPartUriString = GetStartPartUriString(dpo); if (startPartUriString != null) { inputUri = new Uri(startPartUriString, UriKind.RelativeOrAbsolute); } } } // // Resolve to absolute URI // Uri baseUri = BaseUriHelper.GetBaseUri(dpo); Uri absoluteUri = BindUriHelper.GetUriToNavigate(dpo, baseUri, inputUri); if (fragmentLength != 0) { StringBuilder absoluteUriString = new StringBuilder(absoluteUri.ToString()); absoluteUriString.Append(fragment); absoluteUri = new Uri(absoluteUriString.ToString(), UriKind.RelativeOrAbsolute); } return absoluteUri; } return null; } //-------------------------------------------------------------------- // // Public Events // //--------------------------------------------------------------------- //------------------------------------------------------------------- // // Protected Methods // //--------------------------------------------------------------------- #region Protected Methods ////// Gets the Visual children count. /// protected override int VisualChildrenCount { get { if (_uiElementCollection == null) { return 0; } else { return _uiElementCollection.Count; } } } ////// Gets the Visual child at the specified index. /// protected override Visual GetVisualChild(int index) { if (_uiElementCollection == null) { throw new ArgumentOutOfRangeException("index", index, SR.Get(SRID.Visual_ArgumentOutOfRange)); } return _uiElementCollection[index]; } ////// Creates a new UIElementCollection. Panel-derived class can create its own version of /// UIElementCollection -derived class to add cached information to every child or to /// intercept any Add/Remove actions (for example, for incremental layout update) /// private UIElementCollection CreateUIElementCollection(FrameworkElement logicalParent) { return new UIElementCollection(this, logicalParent); } ////// Updates DesiredSize of the Canvas. Called by parent UIElement. This is the first pass of layout. /// ////// Canvas measures each of its children accounting for any of their FrameworkElement properties. /// Children will be passed either the parent's constraint less any margin on the child or their /// explicitly specified (Min/Max)Width/Height properties. /// /// If it has enough space, Canvas will return a size large enough to accommodate all children's /// desired sizes and margins. Children's Top/Left/Bottom/Right properties are not considered in /// this method. If it does not have enough space to accommodate its children in a dimension, this /// will simply return the full constraint in that dimension. /// /// Constraint size is an "upper limit" that Canvas should not exceed. ///Canvas' desired size. protected override Size MeasureOverride(Size constraint) { Size childConstraint = new Size(Double.PositiveInfinity, Double.PositiveInfinity); foreach (UIElement child in Children) { child.Measure(childConstraint); } return new Size(); } ////// Canvas computes a position for each of its children taking into account their margin and /// attached Canvas properties: Top, Left, Bottom, and Right. If specified, Top or Left take /// priority over Bottom or Right. /// /// Canvas will also arrange each of its children. /// /// Size that Canvas will assume to position children. protected override Size ArrangeOverride(Size arrangeSize) { //Canvas arranges children at their DesiredSize. //This means that Margin on children is actually respected and added //to the size of layout partition for a child. //Therefore, is Margin is 10 and Left is 20, the child's ink will start at 30. foreach (UIElement child in Children) { double x = 0; double y = 0; //Compute offset of the child: //If Left is specified, then Right is ignored //If Left is not specified, then Right is used //If both are not there, then 0 double left = GetLeft(child); if(!DoubleUtil.IsNaN(left)) { x = left; } else { double right = GetRight(child); if(!DoubleUtil.IsNaN(right)) { x = arrangeSize.Width - child.DesiredSize.Width - right; } } double top = GetTop(child); if(!DoubleUtil.IsNaN(top)) { y = top; } else { double bottom = GetBottom(child); if(!DoubleUtil.IsNaN(bottom)) { y = arrangeSize.Height - child.DesiredSize.Height - bottom; } } child.Arrange(new Rect(new Point(x, y), child.DesiredSize)); } return arrangeSize; } #endregion //-------------------------------------------------------------------- // // Internal Methods // //--------------------------------------------------------------------- #region Internal methods void IFixedNavigate.NavigateAsync(string elementID) { FixedHyperLink.NavigateToElement(this, elementID); } UIElement IFixedNavigate.FindElementByID(string elementID, out FixedPage rootFixedPage) { UIElement uiElementRet = null; rootFixedPage = this; // We need iterate through the PageContentCollect first. UIElementCollection elementCollection = this.Children; UIElement uiElement; DependencyObject node ; for (int i = 0, n = elementCollection.Count; i < n; i++) { uiElement = elementCollection[i]; node = LogicalTreeHelper.FindLogicalNode(uiElement, elementID); if (node != null) { uiElementRet = node as UIElement; break; } } return uiElementRet; } // Create a FixedNode representing this glyphs or image internal FixedNode CreateFixedNode(int pageIndex, UIElement e) { // Should we check here to make sure this is a selectable element? Debug.Assert(e != null); return _CreateFixedNode(pageIndex, e); } internal Glyphs GetGlyphsElement(FixedNode node) { return GetElement(node) as Glyphs; } // FixedNode represents a leaf node. It contains a path // from root to the leaf in the form of child index. // [Level1 ChildIndex] [Level2 ChildIndex] [Level3 ChildIndex]... internal DependencyObject GetElement(FixedNode node) { int currentLevelIndex = node[1]; if (!(currentLevelIndex >= 0 && currentLevelIndex <= this.Children.Count)) { return null; } #if DEBUG if (node.ChildLevels > 1) { DocumentsTrace.FixedFormat.FixedDocument.Trace(string.Format("FixedPage.GetUIElement {0} is nested element", node)); } #endif DependencyObject element = this.Children[currentLevelIndex]; for (int level = 2; level <= node.ChildLevels; level++) { // Follow the path if necessary currentLevelIndex = node[level]; if (element is Canvas) { // Canvas is a known S0 grouping element. // Boundary Node only would appear in first level! Debug.Assert(currentLevelIndex >= 0 && currentLevelIndex <= ((Canvas)element).Children.Count); element = ((Canvas)element).Children[currentLevelIndex]; } else { DocumentsTrace.FixedFormat.FixedDocument.Trace(string.Format("FixedPage.GeElement {0} is non S0 grouping element in L[{1}]!", node, level)); IEnumerable currentChildrens = LogicalTreeHelper.GetChildren((DependencyObject)element); if (currentChildrens == null) { DocumentsTrace.FixedFormat.FixedDocument.Trace(string.Format("FixedPage.GetElement {0} is NOT a grouping element in L[{1}]!!!", node, level)); return null; } // We have no uniform way to do random access for this element. // This should never happen for S0 conforming document. int childIndex = -1; IEnumerator itor = currentChildrens.GetEnumerator(); while (itor.MoveNext()) { childIndex++; if (childIndex == currentLevelIndex) { element = (DependencyObject)itor.Current; break; } } } } #if DEBUG if (!(element is Glyphs)) { DocumentsTrace.FixedFormat.FixedDocument.Trace(string.Format("FixedPage.GetElement{0} is non-Glyphs", node)); } #endif return element; } #endregion Internal Methods #region Internal Properties internal String StartPartUriString { get { return _startPartUriString; } set { _startPartUriString = value; } } private String _startPartUriString; #if DEBUG internal FixedPageStructure FixedPageStructure { get { return _fixedPageStructure; } set { _fixedPageStructure = value; } } internal int DrawDebugVisualSelection { get { return _drawDebugVisual; } } #endif #endregion Internal Properties //-------------------------------------------------------------------- // // private Properties // //---------------------------------------------------------------------- private UIElementCollection _uiElementCollection; //------------------------------------------------------------------- // // Private Methods // //---------------------------------------------------------------------- #region Private Methods private void Init() { if (XpsValidatingLoader.DocumentMode) { this.InheritanceBehavior = InheritanceBehavior.SkipAllNext; } } ////// internal StoryFragments GetPageStructure() { StoryFragments sf; sf = FixedDocument.GetStoryFragments(this); return sf; } internal int[] _CreateChildIndex(DependencyObject e) { ArrayList childPath = new ArrayList(); while (e != this) { DependencyObject parent = LogicalTreeHelper.GetParent(e); int childIndex = -1; if (parent is FixedPage) { childIndex = ((FixedPage)parent).Children.IndexOf((UIElement)e); } else if (parent is Canvas) { childIndex = ((Canvas)parent).Children.IndexOf((UIElement)e); } else { IEnumerable currentChildrens = LogicalTreeHelper.GetChildren(parent); Debug.Assert(currentChildrens != null); // We have no uniform way to do random access for this element. // This should never happen for S0 conforming document. IEnumerator itor = currentChildrens.GetEnumerator(); while (itor.MoveNext()) { childIndex++; if (itor.Current == e) { break; } } } childPath.Insert(0, childIndex); e = parent; } while (e != this) ; return (int[])childPath.ToArray(typeof(int)); } // Making this function private and only expose the versions // that take S0 elements as parameter. private FixedNode _CreateFixedNode(int pageIndex, UIElement e) { return FixedNode.Create(pageIndex, _CreateChildIndex(e)); } ////// /// This function walks the logical tree for the FixedDocumentSequence and then /// retrieves its URI. We use this Uri for fragment navigation during a FixedPage.OnClick /// event. /// /// ///private static String GetStartPartUriString(DependencyObject current) { //1) Get FixedPage from DependcyObject's InheritanceObject property DependencyObject obj = current; FixedPage fixedPage = current as FixedPage; while (fixedPage == null && obj != null) { obj = obj.InheritanceParent; fixedPage = obj as FixedPage; } if (fixedPage == null) { return null; } //2) Check if fixedPage StartPartUri is null if (fixedPage.StartPartUriString == null) { //3) Walk Logical Tree to the FixedDocumentSequence DependencyObject parent = LogicalTreeHelper.GetParent(current); while (parent != null) { FixedDocumentSequence docSequence = parent as FixedDocumentSequence; if (docSequence != null) { //4) Retrieve DocumentSequence Uri Uri startPartUri = ((IUriContext)docSequence).BaseUri; if (startPartUri != null) { String startPartUriString = startPartUri.ToString(); // If there is a fragment we need to strip it off String fragment = startPartUri.Fragment; int fragmentLength = (fragment == null) ? 0 : fragment.Length; if (fragmentLength != 0) { fixedPage.StartPartUriString = startPartUriString.Substring(0, startPartUriString.IndexOf('#')); } else { fixedPage.StartPartUriString = startPartUri.ToString(); } } break; } parent = LogicalTreeHelper.GetParent(parent); } //If we don't have a starting part Uri, assign fixedPage.StartPartUriString to Empty so //we don't try to look it up again. if (fixedPage.StartPartUriString == null) { fixedPage.StartPartUriString = String.Empty; } } if (fixedPage.StartPartUriString == String.Empty) { return null; } else { return fixedPage.StartPartUriString; } } #endregion //------------------------------------------------------------------- // // Private Fields // //--------------------------------------------------------------------- #if DEBUG private FixedPageStructure _fixedPageStructure; // // The debugging features: set to true will draw the bounding box for each // line from the analyzed layout results. // private int _drawDebugVisual = 0; #endif } #if DEBUG internal sealed class DebugVisualAdorner: Adorner { internal DebugVisualAdorner(FixedPage page) : base(page) { _fixedPage = page; } override protected void OnRender(DrawingContext dc) { if (_fixedPage.DrawDebugVisualSelection == (int) DrawDebugVisual.None) { return; } FixedPageStructure pageStructure = _fixedPage.FixedPageStructure; Debug.Assert(pageStructure != null); if (_fixedPage.DrawDebugVisualSelection == (int) DrawDebugVisual.Glyphs) { if (pageStructure.FixedNodes != null) { _RenderMarkupOrder(dc, pageStructure.FixedNodes); } } else if (_fixedPage.DrawDebugVisualSelection == (int) DrawDebugVisual.Lines) { pageStructure.RenderLines(dc); } else { if (pageStructure.FixedSOMPage != null) { pageStructure.FixedSOMPage.Render(dc, null, (DrawDebugVisual) _fixedPage.DrawDebugVisualSelection); } else { //Explicit document structure FlowNode[] pageNodes = _fixedPage.FixedPageStructure.FlowNodes; int flowOrder = 0; foreach (FlowNode node in pageNodes) { if (node != null && node.FixedSOMElements != null) { foreach (FixedSOMElement somElement in node.FixedSOMElements) { somElement.Render(dc, flowOrder.ToString(), (DrawDebugVisual) _fixedPage.DrawDebugVisualSelection); flowOrder++; } } } } } } internal static DebugVisualAdorner GetDebugVisual(FixedPage page) { AdornerLayer al = AdornerLayer.GetAdornerLayer(page); DebugVisualAdorner debugVisualAd; if (al == null) { return null; } Adorner[] adorners = al.GetAdorners(page); if (adorners != null) { foreach (Adorner ad in adorners) { debugVisualAd = ad as DebugVisualAdorner; if (debugVisualAd != null) { return debugVisualAd; } } } return null; } private void _RenderMarkupOrder(DrawingContext dc, List markupOrder) { int order = 0; foreach (FixedNode node in markupOrder) { DependencyObject ob = _fixedPage.GetElement(node); Glyphs glyphs = ob as Glyphs; Path path = ob as Path; if (glyphs != null) { GlyphRun glyphRun = glyphs.ToGlyphRun(); Rect alignmentBox = glyphRun.ComputeAlignmentBox(); alignmentBox.Offset(glyphs.OriginX, glyphs.OriginY); GeneralTransform transform = glyphs.TransformToAncestor(_fixedPage); alignmentBox = transform.TransformBounds(alignmentBox); Pen pen = new Pen(Brushes.Green, 1); dc.DrawRectangle(null, pen , alignmentBox); _RenderLabel(dc, order.ToString(), alignmentBox); ++order; } else if (path != null) { Geometry renderGeom = path.RenderedGeometry; Pen backgroundPen = new Pen(Brushes.Black,1); dc.DrawGeometry(null, backgroundPen, renderGeom); _RenderLabel(dc, order.ToString(), renderGeom.Bounds); ++order; } } } private void _RenderLabel(DrawingContext dc, string label, Rect boundingRect) { FormattedText ft = new FormattedText(label, System.Windows.Markup.TypeConverterHelper.InvariantEnglishUS, FlowDirection.LeftToRight, new Typeface("Arial"), 10, Brushes.White); Point labelLocation = new Point(boundingRect.Left-25, (boundingRect.Bottom + boundingRect.Top)/2 - 10); Geometry geom = ft.BuildHighlightGeometry(labelLocation); Pen backgroundPen = new Pen(Brushes.Black,1); dc.DrawGeometry(Brushes.Black, backgroundPen, geom); dc.DrawText(ft, labelLocation); } private FixedPage _fixedPage; } internal enum DrawDebugVisual { None = 0, Glyphs = 1, Lines = 2, TextRuns = 3, Paragraphs = 4, Groups = 5, LastOne = 6 } #endif } // 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
- EmptyReadOnlyDictionaryInternal.cs
- SortDescriptionCollection.cs
- FileUpload.cs
- MarginsConverter.cs
- XmlObjectSerializer.cs
- DbDataReader.cs
- RectValueSerializer.cs
- CustomValidator.cs
- TreeNodeClickEventArgs.cs
- LinearGradientBrush.cs
- QEncodedStream.cs
- DefaultBindingPropertyAttribute.cs
- TransformDescriptor.cs
- AssemblyCollection.cs
- ExtendedPropertyDescriptor.cs
- DocumentViewerConstants.cs
- ValidatedControlConverter.cs
- MethodRental.cs
- TypeDescriptor.cs
- Substitution.cs
- MenuItemStyle.cs
- WsrmMessageInfo.cs
- ObjectStorage.cs
- DataTemplateSelector.cs
- FormattedTextSymbols.cs
- BufferAllocator.cs
- SQLInt32Storage.cs
- SqlUtils.cs
- LoggedException.cs
- ContentValidator.cs
- AuthorizationRuleCollection.cs
- NestPullup.cs
- EdgeProfileValidation.cs
- ProviderBase.cs
- _emptywebproxy.cs
- ComPlusDiagnosticTraceSchemas.cs
- ObjectContext.cs
- DependencyProperty.cs
- PageSettings.cs
- LogArchiveSnapshot.cs
- XmlC14NWriter.cs
- BitHelper.cs
- DefaultExpressionVisitor.cs
- URLEditor.cs
- ToolStripMenuItemDesigner.cs
- RequiredAttributeAttribute.cs
- XPathAxisIterator.cs
- OAVariantLib.cs
- BinaryObjectReader.cs
- TypedElement.cs
- ImageKeyConverter.cs
- AdornedElementPlaceholder.cs
- Pkcs7Signer.cs
- XmlDeclaration.cs
- ParseChildrenAsPropertiesAttribute.cs
- BaseCodeDomTreeGenerator.cs
- String.cs
- CodeExporter.cs
- ManipulationDevice.cs
- ReadOnlyState.cs
- XPathArrayIterator.cs
- RtfControlWordInfo.cs
- ContentElement.cs
- Control.cs
- CachedFontFace.cs
- Int64AnimationBase.cs
- DbProviderServices.cs
- DocumentSequence.cs
- EdmFunction.cs
- ObjectDisposedException.cs
- CngProperty.cs
- DragDrop.cs
- IIS7WorkerRequest.cs
- IdentityNotMappedException.cs
- HttpHandlersSection.cs
- ObsoleteAttribute.cs
- CompleteWizardStep.cs
- HierarchicalDataSourceControl.cs
- __Filters.cs
- HttpCachePolicyElement.cs
- UnsafeNativeMethods.cs
- SmtpTransport.cs
- SchemaElementLookUpTable.cs
- MemoryResponseElement.cs
- SafeNativeMethods.cs
- DefaultTraceListener.cs
- SerializationInfoEnumerator.cs
- ToolbarAUtomationPeer.cs
- TypeSystemProvider.cs
- RegisteredDisposeScript.cs
- IisTraceWebEventProvider.cs
- SourceFileBuildProvider.cs
- Int32Animation.cs
- DecoderExceptionFallback.cs
- SerializationException.cs
- TargetControlTypeCache.cs
- InheritablePropertyChangeInfo.cs
- XmlElement.cs
- QilSortKey.cs
- SerializableAttribute.cs