| File: MS\Internal\Documents\UIElementIsland.cs | Web Access |
| Project: src\wpf\src\Microsoft.DotNet.Wpf\src\PresentationFramework\PresentationFramework.csproj (PresentationFramework) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // Description: UIElement layout island. // using System.Collections.ObjectModel; // ReadOnlyCollection<T> using System.Windows; // UIElement using System.Windows.Media; // Visual namespace MS.Internal.Documents { /// <summary> /// UIElement layout island. /// </summary> internal class UIElementIsland : ContainerVisual, IContentHost, IDisposable { //------------------------------------------------------------------- // // Constructors // //------------------------------------------------------------------- #region Constructors /// <summary> /// Create an instance of a UIElementIsland. /// </summary> internal UIElementIsland(UIElement child) { SetFlags(true, VisualFlags.IsLayoutIslandRoot); _child = child; if (_child != null) { // Disconnect visual from its old parent, if necessary. Visual currentParent = VisualTreeHelper.GetParent(_child) as Visual; if (currentParent != null) { Invariant.Assert(currentParent is UIElementIsland, "Parent should always be a UIElementIsland."); ((UIElementIsland)currentParent).Dispose(); } // Notify the Visual layer that a new child appeared. Children.Add(_child); } } #endregion Constructors //------------------------------------------------------------------- // // Internal Methods // //------------------------------------------------------------------- #region Internal Methods /// <summary> /// Do layout of entire UIElement Island. /// </summary> /// <param name="availableSize">Avalilable slot size of the UIElement Island.</param> /// <param name="horizontalAutoSize">Whether horizontal autosizing is enabled.</param> /// <param name="verticalAutoSize">Whether vertical autosizing is enabled.</param> /// <returns>The size of the UIElement Island.</returns> internal Size DoLayout(Size availableSize, bool horizontalAutoSize, bool verticalAutoSize) { Size islandSize = new Size(); if (_child != null) { // Get FlowDirection from logical parent and set it on UIElemntIsland // to get layout mirroring provided by the layout system. if (_child is FrameworkElement && ((FrameworkElement)_child).Parent != null) { SetValue(FrameworkElement.FlowDirectionProperty, ((FrameworkElement)_child).Parent.GetValue(FrameworkElement.FlowDirectionProperty)); } try { _layoutInProgress = true; // Measure UIElement _child.Measure(availableSize); // Arrange UIElement islandSize.Width = horizontalAutoSize ? _child.DesiredSize.Width : availableSize.Width; islandSize.Height = verticalAutoSize ? _child.DesiredSize.Height : availableSize.Height; _child.Arrange(new Rect(islandSize)); } finally { _layoutInProgress = false; } } return islandSize; } #endregion Internal Methods //------------------------------------------------------------------- // // Internal Properties // //------------------------------------------------------------------- #region Internal Properties /// <summary> /// Root of UIElement island. /// </summary> internal UIElement Root { get { return _child; } } #endregion Internal Properties //------------------------------------------------------------------- // // Internal Events // //------------------------------------------------------------------- #region Internal Events /// <summary> /// Fired after DesiredSize for child UIElement has been changed. /// </summary> internal event DesiredSizeChangedEventHandler DesiredSizeChanged; #endregion Internal Events //------------------------------------------------------------------- // // Private Fields // //------------------------------------------------------------------- #region Private Fields private UIElement _child; // Hosted UIElement root. private bool _layoutInProgress; // Whether layout is in progress. #endregion Private Fields //------------------------------------------------------------------- // // IDisposable Members // //------------------------------------------------------------------- #region IDisposable Members /// <summary> /// <see cref="IDisposable.Dispose"/> /// </summary> public void Dispose() { if (_child != null) { Children.Clear(); _child = null; } GC.SuppressFinalize(this); } #endregion IDisposable Members //------------------------------------------------------------------- // // IContentHost Members // //------------------------------------------------------------------- #region IContentHost Members /// <summary> /// <see cref="IContentHost.InputHitTest"/> /// </summary> IInputElement IContentHost.InputHitTest(Point point) { // UIElementIsland only hosts UIElements, which can be found by the // normal hit-testing logic, so we don't need to provide our own // hit-testing implementation. return null; } /// <summary> /// <see cref="IContentHost.GetRectangles"/> /// </summary> ReadOnlyCollection<Rect> IContentHost.GetRectangles(ContentElement child) { return ReadOnlyCollection<Rect>.Empty; } /// <summary> /// <see cref="IContentHost.HostedElements"/> /// </summary> IEnumerator<IInputElement> IContentHost.HostedElements { get { List<IInputElement> hostedElements = new List<IInputElement>(); if (_child != null) { hostedElements.Add(_child); } return hostedElements.GetEnumerator(); } } /// <summary> /// <see cref="IContentHost.OnChildDesiredSizeChanged"/> /// </summary> void IContentHost.OnChildDesiredSizeChanged(UIElement child) { Invariant.Assert(child == _child); if (!_layoutInProgress && DesiredSizeChanged != null) { DesiredSizeChanged(this, new DesiredSizeChangedEventArgs(child)); } } #endregion IContentHost Members } /// <summary> /// DesiredSizeChanged event handler. /// </summary> internal delegate void DesiredSizeChangedEventHandler(object sender, DesiredSizeChangedEventArgs e); /// <summary> /// Event arguments for the DesiredSizeChanged event. /// </summary> internal class DesiredSizeChangedEventArgs : EventArgs { /// <summary> /// Constructor. /// </summary> /// <param name="child">UIElement for which DesiredSize has been changed.</param> internal DesiredSizeChangedEventArgs(UIElement child) { _child = child; } /// <summary> /// UIElement for which DesiredSize has been changed. /// </summary> internal UIElement Child { get { return _child; } } /// <summary> /// UIElement for which DesiredSize has been changed. /// </summary> private readonly UIElement _child; } }