FixedPage.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Framework / System / Windows / Documents / FixedPage.cs / 1 / FixedPage.cs

                            //---------------------------------------------------------------------------- 
// 
//      Copyright (C) 2003 by Microsoft Corporation.  All rights reserved.
// 
// 
// Description:
//      Implements the FixedPage element 
// 
// History:
//      06/03/2003 - [....] ([....]) - Created. 
//
// [....]/payloads/Payloads%20Features/FixedPanelPage.mht
//
//--------------------------------------------------------------------------- 
namespace System.Windows.Documents
{ 
    using MS.Internal; 
    using MS.Internal.Documents;
    using MS.Internal.AppModel; 
    using System.IO.Packaging;
    using System.Windows;                // DependencyID etc.
    using System.Windows.Controls;       // Canvas
    using System.Windows.Media; 
    using System.Windows.Shapes;        // Glyphs
    using System.Windows.Markup; 
    using System.Windows.Threading; 
    using System;
    using System.Text; 
    using System.ComponentModel;
    using System.Collections;
    using System.Collections.Generic;
    using System.Diagnostics; 
    using System.Windows.Input;
    using System.Windows.Navigation ; 
    using System.Windows.Documents.DocumentStructures; 
    using MS.Internal.Utility;
    using System.Security; 
    using System.Security.Permissions;
    using System.Globalization;
    using MS.Internal.PresentationFramework;      // SecurityHelper
 

    //===================================================================== 
    ///  
    /// 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
    {
        //-------------------------------------------------------------------
        // 
        // Connstructors
        // 
        //---------------------------------------------------------------------- 

        #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.
        [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.
        public static void SetNavigateUri(UIElement element, Uri uri) 
        { 
            if (element == null) { throw new ArgumentNullException("element"); }
            element.SetValue(NavigateUriProperty, uri); 
        }

        /// 
        /// Reads the attached property IsHyperlinkPressed from the given element. 
        /// 
        [AttachedPropertyBrowsableForChildren()] 
        internal static bool GetIsHyperlinkPressed(UIElement element) 
        {
            if (element == null) { throw new ArgumentNullException("element"); } 
            return (bool)element.GetValue(IsHyperlinkPressedProperty);
        }

        ///  
        /// Writes the attached property IsHyperlinkPressed to the given element.
        ///  
        internal static void SetIsHyperlinkPressed(UIElement element, bool isPressed) 
        {
            if (element == null) { throw new ArgumentNullException("element"); } 
            element.SetValue(IsHyperlinkPressedProperty, isPressed);
        }

        #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  property.
        /// 
        public static readonly DependencyProperty BackgroundProperty = 
                Panel.BackgroundProperty.AddOwner(
                        typeof(FixedPage), 
                        new FrameworkPropertyMetadata((Brush)Brushes.White, FrameworkPropertyMetadataOptions.AffectsRender)); 

        ///  
        /// 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(OnNavigateUriChanged))); 

        static void OnNavigateUriChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Uri navigateUri = e.NewValue as Uri; 
            FrameworkElement element = d as FrameworkElement;
            if (element != null && navigateUri != null && 
                ((element is Path) || (element is Canvas) || (element is Glyphs) || (element is FixedPage))) 
            {
                if (CanNavigateToUri(navigateUri)) 
                {
                    //
                    // We only support FixedPage.NavigateUri to attached to those four element:
                    // Path(Overlay purpose), Canvas, Glyph, FixedPage. 
                    //
                    element.AddHandler(Keyboard.KeyDownEvent, new KeyEventHandler(FixedPage.OnKeyDown_Hyperlink)); 
                    element.AddHandler(Mouse.MouseDownEvent, new MouseButtonEventHandler(FixedPage.OnMouseDown_Hyperlink)); 
                    element.AddHandler(Mouse.MouseUpEvent, new MouseButtonEventHandler(FixedPage.OnMouseUp_Hyperlink));
                    element.AddHandler(Mouse.MouseEnterEvent, new MouseEventHandler(FixedPage.OnMouseEnter_Hyperlink)); 
                    element.AddHandler(Mouse.MouseLeaveEvent, new MouseEventHandler(FixedPage.OnMouseLeave_Hyperlink));

                    element.Cursor = Cursors.Hand;
#if DEBUG 
                    element.ToolTip = navigateUri.ToString();
#endif 
                } 
                else
                { 
                    element.Cursor = Cursors.No;
                }
            }
 
        }
 
        ///  
        /// Record the IsPressed property attached to Hyperlink element
        ///  
        internal static readonly DependencyProperty IsHyperlinkPressedProperty =
                DependencyProperty.RegisterAttached(
                        "IsHyperlinkPressed",
                        typeof(bool), 
                        typeof(FixedPage),
                        new FrameworkPropertyMetadata(false)); 
 
        #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;
        } 
 
        /// 
        /// This is the method that responds to the KeyDown event. 
        /// 
        /// ///
        ///     Critical - asserts UserInitatedNavigationPermisison.
        /// 
        ///     TreatAsSafe - assert is used to enable "safe" navigation only.
        ///                   we consider this safe as we only assert if this is a userInitiated action. 
        ///                   The UserInitiated bit is set inside of the InputManager - and tracked via critical. 
        ///
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        [UIPermissionAttribute(SecurityAction.InheritanceDemand, Unrestricted = true)]
        private static void  OnKeyDown_Hyperlink(object sender, KeyEventArgs e)
        { 
            if (e.RoutedEvent == Keyboard.KeyDownEvent && e.Key == Key.Enter)
            { 
                if (e.UserInitiated) 
                {
                    CodeAccessPermission perm = SecurityHelper.CreateUserInitiatedNavigationPermission(); 
                    perm.Assert();  //BlessedAssert:
                }

                try 
                {
                    e.Handled = true; 
                    OnClick(sender); 
                }
                finally 
                {
                    if (e.UserInitiated)
                    {
                        CodeAccessPermission.RevertAssert(); 
                    }
                } 
            } 
        }
 
        /// 
        /// Fire the event to change the status bar.
        /// 
        private static void OnMouseEnter_Hyperlink(object sender, MouseEventArgs e) 
        {
            FrameworkElement element = sender as FrameworkElement; 
            if (element != null) 
            {
                Uri NavigateUri = element.GetValue(NavigateUriProperty) as Uri; 

                if (NavigateUri != null)
                {
                    RequestSetStatusBarEventArgs args = new RequestSetStatusBarEventArgs(NavigateUri.ToString()); 
                    element.RaiseEvent(args);
                } 
            } 
        }
 

        /// 
        /// Set the status bar text back to empty
        ///  
        private static void OnMouseLeave_Hyperlink(object sender, MouseEventArgs e)
        { 
            FrameworkElement element = sender as FrameworkElement; 
            if (element != null)
            { 
                RequestSetStatusBarEventArgs args = new RequestSetStatusBarEventArgs(String.Empty);
                element.RaiseEvent(args);
            }
        } 

        ///  
        /// This is the method that responds to the MouseButtonEvent event. 
        /// 
        private static void OnMouseDown_Hyperlink(object sender, MouseButtonEventArgs e) 
        {
            if (!e.Handled)
            {
                switch (e.ChangedButton) 
                {
                    case MouseButton.Left: 
                        OnMouseLeftButtonDown_Hyperlink(sender, e); 
                        break;
                    default: 
                        // No wrappers exposed for the other buttons.
                        break;
                }
            } 
        }
 
        private static void OnMouseLeftButtonDown_Hyperlink(object sender, MouseButtonEventArgs e) 
        {
            UIElement element = sender as UIElement; 
            // It is possible that the mouse state could have changed during all of
            // the call-outs that have happened so far.
            if (e.ButtonState == MouseButtonState.Pressed)
            { 
                // Capture the mouse, and make sure we got it.
                Mouse.Capture(element); 
                if (element.IsMouseCaptured) 
                {
                    // Though we have already checked this state, our call to CaptureMouse 
                    // could also end up changing the state, so we check it again.
                    if (e.ButtonState == MouseButtonState.Pressed)
                    {
                        element.SetValue(IsHyperlinkPressedProperty, true); 
                    }
                    else 
                    { 
                        // Release capture since we decided not to press the button.
                        Mouse.Capture(null); 
                    }
                }
            }
 
            e.Handled = true;
        } 
 
        /// 
        /// This is the method that responds to the MouseButtonEvent event. 
        /// 
        private static void OnMouseUp_Hyperlink(object sender, MouseButtonEventArgs e)
        {
            switch (e.ChangedButton) 
            {
                case MouseButton.Left: 
                    OnMouseLeftButtonUp_Hyperlink(sender, e); 
                    break;
                case MouseButton.Right: 
                    break;
                default:
                    // No wrappers exposed for the other buttons.
                    break; 
            }
        } 
 
        /// 
        /// This is the method that responds to the left button up event 
        /// 
        ///
        ///     Critical - asserts UserInitatedNavigationPermisison.
        /// 
        ///     TreatAsSafe - assert is used to enable "safe" navigation only.
        ///                   we consider this safe as we only assert if this is a userInitiated action. 
        ///                   The UserInitiated bit is set inside of the InputManager - and tracked via critical. 
        ///
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        [UIPermissionAttribute(SecurityAction.InheritanceDemand, Unrestricted = true)]
        private static void OnMouseLeftButtonUp_Hyperlink(object sender, MouseButtonEventArgs e)
        { 
            UIElement element = sender as UIElement;
 
            if (element.IsMouseCaptured) 
            {
                Mouse.Capture(null); 
            }

            if ((bool)element.GetValue(IsHyperlinkPressedProperty))
            { 
                element.SetValue(IsHyperlinkPressedProperty, false);
 
                // Make sure we're mousing up over the hyperlink 
                if (element.IsMouseOver)
                { 
                    bool assertCodeAccessPermission = e.UserInitiated &&
                                        (e.RoutedEvent == Mouse.MouseUpEvent) &&
                                        (e.ChangedButton == MouseButton.Left);
 
                    if (assertCodeAccessPermission)
                    { 
                        CodeAccessPermission perm = SecurityHelper.CreateUserInitiatedNavigationPermission(); 
                        perm.Assert(); //BlessedAssert:
                    } 

                    try
                    {
                        OnClick(sender); 
                    }
                    finally 
                    { 
                        if (assertCodeAccessPermission)
                        { 
                            CodeAccessPermission.RevertAssert();
                        }
                    }
                } 
            }
 
            e.Handled = true; 
        }
 
        /// 
        /// Navigate to URI specified in NavigateUri property
        /// 
        private static void OnClick(object sender) 
        {
            FrameworkElement element = (FrameworkElement)sender; 
            Uri inputUri = element.GetValue(NavigateUriProperty) as Uri; 
            RaiseNavigateFromPage(element, inputUri);
        } 

        private 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 MS.Internal.PresentationFramework.SecurityHelper.CallerHasWebPermission(uri); 
            }
        } 

        /// 
        /// Navigate to URI.  Used by OnClick and by automation.
        ///  
        /// 
        ///  
        internal static void RaiseNavigateFromPage(FrameworkElement element, Uri inputUri) 
        {
            Uri absoluteUri = GetLinkUri(element, inputUri); 
            if (absoluteUri != null)
            {
                // finally we have a good absoluteUri to fire the event.
                RequestNavigateEventArgs navigateArgs; 
                navigateArgs = new RequestNavigateEventArgs(absoluteUri, null);
                navigateArgs.Source=element; 
                // 
                // Fire the navigate events.
                // 
                element.RaiseEvent(navigateArgs);
            }
        }
 
        internal static Uri GetLinkUri(FrameworkElement element, Uri inputUri)
        { 
            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(element);
                        if (startPartUriString != null) 
                        { 
                            inputUri = new Uri(startPartUriString, UriKind.RelativeOrAbsolute);
                        } 
                    }
                }
                //
                // Resolve to absolute URI 
                //
                Uri baseUri = BaseUriHelper.GetBaseUri(element); 
                Uri absoluteUri = BindUriHelper.GetUriToNavigate(element, 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
        // 
        //----------------------------------------------------------------------

        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; 
            }
        } 

        //-------------------------------------------------------------------
        //
        // 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) 
        {
            CultureInfo EnglishCulture = CultureInfo.GetCultureInfoByIetfLanguageTag("en-US"); 
            FormattedText ft = new FormattedText(label, 
                                        EnglishCulture,
                                        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

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK