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 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(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
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ConnectionInterfaceCollection.cs
- Mappings.cs
- ListViewAutomationPeer.cs
- TraceListeners.cs
- HiddenField.cs
- PointCollectionConverter.cs
- GC.cs
- WindowsTooltip.cs
- Ray3DHitTestResult.cs
- HtmlControl.cs
- EncodingInfo.cs
- FileDialog_Vista.cs
- MediaContextNotificationWindow.cs
- TextEditorDragDrop.cs
- DataServiceProviderWrapper.cs
- ReferencedAssemblyResolver.cs
- XmlLinkedNode.cs
- MasterPage.cs
- MemberExpressionHelper.cs
- TraceHandlerErrorFormatter.cs
- CommentEmitter.cs
- TraceLog.cs
- SQLSingle.cs
- Query.cs
- InfoCardSymmetricCrypto.cs
- FontSource.cs
- MatrixTransform3D.cs
- XamlDesignerSerializationManager.cs
- TextBox.cs
- VectorCollection.cs
- ConnectionPoolManager.cs
- WebPartConnectionsConnectVerb.cs
- SkinBuilder.cs
- ContextDataSourceView.cs
- CodeSnippetExpression.cs
- ValueTypeFixupInfo.cs
- DocumentPageHost.cs
- TypeBuilderInstantiation.cs
- TreeViewItemAutomationPeer.cs
- IntSecurity.cs
- UIAgentInitializationException.cs
- Oid.cs
- PageAdapter.cs
- BrushProxy.cs
- ToolStripItemRenderEventArgs.cs
- RangeBase.cs
- IntPtr.cs
- LongValidatorAttribute.cs
- TextParaClient.cs
- MdiWindowListItemConverter.cs
- DrawingGroupDrawingContext.cs
- IChannel.cs
- LayoutSettings.cs
- KeyboardNavigation.cs
- SingleKeyFrameCollection.cs
- _FtpControlStream.cs
- ScrollEventArgs.cs
- MobileUITypeEditor.cs
- XmlAnyElementAttribute.cs
- CollectionBase.cs
- BitmapSizeOptions.cs
- TextClipboardData.cs
- CodeAttributeArgument.cs
- CustomPopupPlacement.cs
- PolicyStatement.cs
- DependencyPropertyAttribute.cs
- LinkUtilities.cs
- ContractTypeNameElement.cs
- XmlSignificantWhitespace.cs
- BrowserDefinitionCollection.cs
- HtmlInputButton.cs
- MemoryPressure.cs
- TableItemProviderWrapper.cs
- ItemCollection.cs
- FilterQuery.cs
- XPathDescendantIterator.cs
- AssociationType.cs
- FieldMetadata.cs
- SHA512CryptoServiceProvider.cs
- TypeExtensionConverter.cs
- BindingMAnagerBase.cs
- FixedSOMLineCollection.cs
- VirtualPathExtension.cs
- IBuiltInEvidence.cs
- Normalization.cs
- AnnotationObservableCollection.cs
- SoapSchemaMember.cs
- SqlMetaData.cs
- DataGridViewColumnEventArgs.cs
- UIElement3DAutomationPeer.cs
- NTAccount.cs
- TraceEventCache.cs
- RegexCompiler.cs
- SystemDropShadowChrome.cs
- PackageRelationshipSelector.cs
- NonParentingControl.cs
- Int32Rect.cs
- safePerfProviderHandle.cs
- SystemResourceHost.cs
- AutoGeneratedField.cs