Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Framework / System / Windows / Controls / DefinitionBase.cs / 1 / DefinitionBase.cs
//---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // Specs // Grid : http://avalon/layout/Specs/Grid.mht // Size Sharing: http://avalon/layout/Specs/Size%20Information%20Sharing.doc // // Misc // Grid Tutorial: http://avalon/layout/Documentation%20and%20Tutorials/Grid%20Tutorial.mht // // Description: Implementation of base abstract class for ColumnDefinition // and RowDefinition. // // History: // 11/17/2003 : olego - Created // //--------------------------------------------------------------------------- using MS.Internal; using MS.Internal.KnownBoxes; using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Security.Permissions; using System.Windows; using System.Windows.Threading; namespace System.Windows.Controls { ////// DefinitionBase provides core functionality used internally by Grid /// and ColumnDefinitionCollection / RowDefinitionCollection /// [Localizability(LocalizationCategory.Ignore)] public abstract class DefinitionBase : FrameworkContentElement { //----------------------------------------------------- // // Constructors // //----------------------------------------------------- #region Constructors internal DefinitionBase(bool isColumnDefinition) { _isColumnDefinition = isColumnDefinition; _parentIndex = -1; } #endregion Constructors //------------------------------------------------------ // // Public Properties // //----------------------------------------------------- #region Public Properties ////// SharedSizeGroup property. /// public string SharedSizeGroup { get { return (string) GetValue(SharedSizeGroupProperty); } set { SetValue(SharedSizeGroupProperty, value); } } #endregion Public Properties //------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ #region Internal Methods ////// Callback to notify about entering model tree. /// internal void OnEnterParentTree() { if (_sharedState == null) { // start with getting SharedSizeGroup value. // this property is NOT inhereted which should result in better overall perf. string sharedSizeGroupId = SharedSizeGroup; if (sharedSizeGroupId != null) { SharedSizeScope privateSharedSizeScope = PrivateSharedSizeScope; if (privateSharedSizeScope != null) { _sharedState = privateSharedSizeScope.EnsureSharedState(sharedSizeGroupId); _sharedState.AddMember(this); } } } } ////// Callback to notify about exitting model tree. /// internal void OnExitParentTree() { _offset = 0; if (_sharedState != null) { _sharedState.RemoveMember(this); _sharedState = null; } } ////// Performs action preparing definition to enter layout calculation mode. /// internal void OnBeforeLayout(Grid grid) { // reset layout state. _minSize = 0; LayoutWasUpdated = true; // defer verification for shared definitions if (_sharedState != null) { _sharedState.EnsureDeferredValidation(grid); } } ////// Updates min size. /// /// New size. internal void UpdateMinSize(double minSize) { _minSize = Math.Max(_minSize, minSize); } ////// ////// /// This method needs to be internal to be accessable from derived classes. /// internal static void OnUserSizePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { DefinitionBase definition = (DefinitionBase) d; if (definition.InParentLogicalTree) { if (definition._sharedState != null) { definition._sharedState.Invalidate(); } else { Grid parentGrid = (Grid) definition.Parent; if (((GridLength) e.OldValue).GridUnitType != ((GridLength) e.NewValue).GridUnitType) { parentGrid.Invalidate(); } else { parentGrid.InvalidateMeasure(); } } } } ////// ////// /// This method needs to be internal to be accessable from derived classes. /// internal static bool IsUserSizePropertyValueValid(object value) { return (((GridLength)value).Value >= 0); } ////// ////// /// This method needs to be internal to be accessable from derived classes. /// internal static void OnUserMinSizePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { DefinitionBase definition = (DefinitionBase) d; if (definition.InParentLogicalTree) { Grid parentGrid = (Grid) definition.Parent; parentGrid.InvalidateMeasure(); } } ////// ////// /// This method needs to be internal to be accessable from derived classes. /// internal static bool IsUserMinSizePropertyValueValid(object value) { double v = (double)value; return (!DoubleUtil.IsNaN(v) && v >= 0.0d && !Double.IsPositiveInfinity(v)); } ////// ////// /// This method needs to be internal to be accessable from derived classes. /// internal static void OnUserMaxSizePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { DefinitionBase definition = (DefinitionBase) d; if (definition.InParentLogicalTree) { Grid parentGrid = (Grid) definition.Parent; parentGrid.InvalidateMeasure(); } } ////// ////// /// This method needs to be internal to be accessable from derived classes. /// internal static bool IsUserMaxSizePropertyValueValid(object value) { double v = (double)value; return (!DoubleUtil.IsNaN(v) && v >= 0.0d); } ////// ////// /// This method reflects Grid.SharedScopeProperty state by setting / clearing /// dynamic property PrivateSharedSizeScopeProperty. Value of PrivateSharedSizeScopeProperty /// is a collection of SharedSizeState objects for the scope. /// Also PrivateSharedSizeScopeProperty is FrameworkPropertyMetadataOptions.Inherits property. So that all children /// elements belonging to a certain scope can easily access SharedSizeState collection. As well /// as been norified about enter / exit a scope. /// internal static void OnIsSharedSizeScopePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { // if ((bool) e.NewValue) { SharedSizeScope sharedStatesCollection = new SharedSizeScope(); d.SetValue(PrivateSharedSizeScopeProperty, sharedStatesCollection); } else { d.ClearValue(PrivateSharedSizeScopeProperty); } } #endregion Internal Methods //----------------------------------------------------- // // Internal Properties // //------------------------------------------------------ #region Internal Properties ////// Returns internal bool IsShared { get { return (_sharedState != null); } } ///true if this definition is a part of shared group. ////// Internal accessor to user size field. /// internal GridLength UserSize { get { return (_sharedState != null ? _sharedState.UserSize : UserSizeValueCache); } } ////// Internal accessor to user min size field. /// internal double UserMinSize { get { return (UserMinSizeValueCache); } } ////// Internal accessor to user max size field. /// internal double UserMaxSize { get { return (UserMaxSizeValueCache); } } ////// DefinitionBase's index in the parents collection. /// internal int Index { get { return (_parentIndex); } set { Debug.Assert(value >= -1 && _parentIndex != value); _parentIndex = value; } } ////// Layout-time user size type. /// internal Grid.LayoutTimeSizeType SizeType { get { return (_sizeType); } set { _sizeType = value; } } ////// Returns or sets measure size for the definition. /// internal double MeasureSize { get { return (_measureSize); } set { _measureSize = value; } } ////// Returns definition's layout time type sensitive preferred size. /// ////// Returned value is guaranteed to be true preferred size. /// internal double PreferredSize { get { double preferredSize = MinSize; if ( _sizeType != Grid.LayoutTimeSizeType.Auto && preferredSize < _measureSize ) { preferredSize = _measureSize; } return (preferredSize); } } ////// Returns or sets size cache for the definition. /// internal double SizeCache { get { return (_sizeCache); } set { _sizeCache = value; } } ////// Returns min size. /// internal double MinSize { get { double minSize = _minSize; if ( UseSharedMinimum && _sharedState != null && minSize < _sharedState.MinSize ) { minSize = _sharedState.MinSize; } return (minSize); } } ////// Returns min size, always taking into account shared state. /// internal double MinSizeForArrange { get { double minSize = _minSize; if ( _sharedState != null && (UseSharedMinimum || !LayoutWasUpdated) && minSize < _sharedState.MinSize ) { minSize = _sharedState.MinSize; } return (minSize); } } ////// Offset. /// internal double FinalOffset { get { return _offset; } set { _offset = value; } } ////// Internal helper to access up-to-date UserSize property value. /// internal GridLength UserSizeValueCache { get { return (GridLength) GetValue( _isColumnDefinition ? ColumnDefinition.WidthProperty : RowDefinition.HeightProperty); } } ////// Internal helper to access up-to-date UserMinSize property value. /// internal double UserMinSizeValueCache { get { return (double) GetValue( _isColumnDefinition ? ColumnDefinition.MinWidthProperty : RowDefinition.MinHeightProperty); } } ////// Internal helper to access up-to-date UserMaxSize property value. /// internal double UserMaxSizeValueCache { get { return (double) GetValue( _isColumnDefinition ? ColumnDefinition.MaxWidthProperty : RowDefinition.MaxHeightProperty); } } ////// Protected. Returns internal bool InParentLogicalTree { get { return (_parentIndex != -1); } } #endregion Internal Properties //----------------------------------------------------- // // Private Methods // //----------------------------------------------------- #region Private Methods ///true if this DefinitionBase instance is in parent's logical tree. ////// SetFlags is used to set or unset one or multiple /// flags on the object. /// private void SetFlags(bool value, Flags flags) { _flags = value ? (_flags | flags) : (_flags & (~flags)); } ////// CheckFlagsAnd returns private bool CheckFlagsAnd(Flags flags) { return ((_flags & flags) == flags); } ///true if all the flags in the /// given bitmask are set on the object. ////// private static void OnSharedSizeGroupPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { DefinitionBase definition = (DefinitionBase) d; if (definition.InParentLogicalTree) { string sharedSizeGroupId = (string) e.NewValue; if (definition._sharedState != null) { // if definition is already registered AND shared size group id is changing, // then un-register the definition from the current shared size state object. definition._sharedState.RemoveMember(definition); definition._sharedState = null; } if ((definition._sharedState == null) && (sharedSizeGroupId != null)) { SharedSizeScope privateSharedSizeScope = definition.PrivateSharedSizeScope; if (privateSharedSizeScope != null) { // if definition is not registered and both: shared size group id AND private shared scope // are available, then register definition. definition._sharedState = privateSharedSizeScope.EnsureSharedState(sharedSizeGroupId); definition._sharedState.AddMember(definition); } } } } ////// /// ////// /// Verifies that Shared Size Group Property string /// a) not empty. /// b) contains only letters, digits and underscore ('_'). /// c) does not start with a digit. /// private static bool SharedSizeGroupPropertyValueValid(object value) { // null is default value if (value == null) { return (true); } string id = (string)value; if (id != string.Empty) { int i = -1; while (++i < id.Length) { bool isDigit = Char.IsDigit(id[i]); if ( (i == 0 && isDigit) || !( isDigit || Char.IsLetter(id[i]) || '_' == id[i] ) ) { break; } } if (i == id.Length) { return (true); } } return (false); } ////// ////// /// OnPrivateSharedSizeScopePropertyChanged is called when new scope enters or /// existing scope just left. In both cases if the DefinitionBase object is already registered /// in SharedSizeState, it should un-register and register itself in a new one. /// private static void OnPrivateSharedSizeScopePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { DefinitionBase definition = (DefinitionBase)d; if (definition.InParentLogicalTree) { SharedSizeScope privateSharedSizeScope = (SharedSizeScope) e.NewValue; if (definition._sharedState != null) { // if definition is already registered And shared size scope is changing, // then un-register the definition from the current shared size state object. definition._sharedState.RemoveMember(definition); definition._sharedState = null; } if ((definition._sharedState == null) && (privateSharedSizeScope != null)) { string sharedSizeGroup = definition.SharedSizeGroup; if (sharedSizeGroup != null) { // if definition is not registered and both: shared size group id AND private shared scope // are available, then register definition. definition._sharedState = privateSharedSizeScope.EnsureSharedState(definition.SharedSizeGroup); definition._sharedState.AddMember(definition); } } } } #endregion Private Methods //----------------------------------------------------- // // Private Properties // //------------------------------------------------------ #region Private Properties ////// Private getter of shared state collection dynamic property. /// private SharedSizeScope PrivateSharedSizeScope { get { return (SharedSizeScope) GetValue(PrivateSharedSizeScopeProperty); } } ////// Convenience accessor to UseSharedMinimum flag /// private bool UseSharedMinimum { get { return (CheckFlagsAnd(Flags.UseSharedMinimum)); } set { SetFlags(value, Flags.UseSharedMinimum); } } ////// Convenience accessor to LayoutWasUpdated flag /// private bool LayoutWasUpdated { get { return (CheckFlagsAnd(Flags.LayoutWasUpdated)); } set { SetFlags(value, Flags.LayoutWasUpdated); } } #endregion Private Properties //----------------------------------------------------- // // Private Fields // //------------------------------------------------------ #region Private Fields private readonly bool _isColumnDefinition; // when "true", this is a ColumnDefinition; when "false" this is a RowDefinition (faster than a type check) private Flags _flags; // flags reflecting various aspects of internal state private int _parentIndex; // this instance's index in parent's children collection private Grid.LayoutTimeSizeType _sizeType; // layout-time user size type. it may differ from _userSizeValueCache.UnitType when calculating "to-content" private double _minSize; // used during measure to accumulate size for "Auto" and "Star" DefinitionBase's private double _measureSize; // size, calculated to be the input contstraint size for Child.Measure private double _sizeCache; // cache used for various purposes (sorting, caching, etc) during calculations private double _offset; // offset of the DefinitionBase from left / top corner (assuming LTR case) private SharedSizeState _sharedState; // reference to shared state object this instance is registered with internal const bool ThisIsColumnDefinition = true; internal const bool ThisIsRowDefinition = false; #endregion Private Fields //------------------------------------------------------ // // Private Structures / Classes // //----------------------------------------------------- #region Private Structures Classes [System.Flags] private enum Flags : byte { // // bool flags // UseSharedMinimum = 0x00000020, // when "1", definition will take into account shared state's minimum LayoutWasUpdated = 0x00000040, // set to "1" every time the parent grid is measured } ////// Collection of shared states objects for a single scope /// private class SharedSizeScope { ////// Returns SharedSizeState object for a given group. /// Creates a new StatedState object if necessary. /// internal SharedSizeState EnsureSharedState(string sharedSizeGroup) { // check that sharedSizeGroup is not default Debug.Assert(sharedSizeGroup != null); SharedSizeState sharedState = _registry[sharedSizeGroup] as SharedSizeState; if (sharedState == null) { sharedState = new SharedSizeState(this, sharedSizeGroup); _registry[sharedSizeGroup] = sharedState; } return (sharedState); } ////// Removes an entry in the registry by the given key. /// internal void Remove(object key) { Debug.Assert(_registry.Contains(key)); _registry.Remove(key); } private Hashtable _registry = new Hashtable(); // storage for shared state objects } ////// Implementation of per shared group state object /// private class SharedSizeState { ////// Default ctor. /// internal SharedSizeState(SharedSizeScope sharedSizeScope, string sharedSizeGroupId) { Debug.Assert(sharedSizeScope != null && sharedSizeGroupId != null); _sharedSizeScope = sharedSizeScope; _sharedSizeGroupId = sharedSizeGroupId; _registry = new List(); _layoutUpdated = new EventHandler(OnLayoutUpdated); _broadcastInvalidation = true; } /// /// Adds / registers a definition instance. /// internal void AddMember(DefinitionBase member) { Debug.Assert(!_registry.Contains(member)); _registry.Add(member); Invalidate(); } ////// Removes / un-registers a definition instance. /// ////// If the collection of registered definitions becomes empty /// instantiates self removal from owner's collection. /// internal void RemoveMember(DefinitionBase member) { Invalidate(); _registry.Remove(member); if (_registry.Count == 0) { _sharedSizeScope.Remove(_sharedSizeGroupId); } } ////// Propogates invalidations for all registered definitions. /// Resets its own state. /// internal void Invalidate() { _userSizeValid = false; if (_broadcastInvalidation) { for (int i = 0, count = _registry.Count; i < count; ++i) { Grid parentGrid = (Grid)(_registry[i].Parent); parentGrid.Invalidate(); } _broadcastInvalidation = false; } } ////// Makes sure that one and only one layout updated handler is registered for this shared state. /// internal void EnsureDeferredValidation(UIElement layoutUpdatedHost) { if (_layoutUpdatedHost == null) { _layoutUpdatedHost = layoutUpdatedHost; _layoutUpdatedHost.LayoutUpdated += _layoutUpdated; } } ////// DefinitionBase's specific code. /// internal double MinSize { get { if (!_userSizeValid) { EnsureUserSizeValid(); } return (_minSize); } } ////// DefinitionBase's specific code. /// internal GridLength UserSize { get { if (!_userSizeValid) { EnsureUserSizeValid(); } return (_userSize); } } private void EnsureUserSizeValid() { _userSize = new GridLength(1, GridUnitType.Auto); for (int i = 0, count = _registry.Count; i < count; ++i) { Debug.Assert( _userSize.GridUnitType == GridUnitType.Auto || _userSize.GridUnitType == GridUnitType.Pixel ); GridLength currentGridLength = _registry[i].UserSizeValueCache; if (currentGridLength.GridUnitType == GridUnitType.Pixel) { if (_userSize.GridUnitType == GridUnitType.Auto) { _userSize = currentGridLength; } else if (_userSize.Value < currentGridLength.Value) { _userSize = currentGridLength; } } } // taking maximum with user size effectively prevents squishy-ness. // this is a "solution" to avoid shared definitions from been sized to // different final size at arrange time, if / when different grids receive // different final sizes. _minSize = _userSize.IsAbsolute ? _userSize.Value : 0.0; _userSizeValid = true; } ////// OnLayoutUpdated handler. Validates that all participating definitions /// have updated min size value. Forces another layout update cycle if needed. /// private void OnLayoutUpdated(object sender, EventArgs e) { double sharedMinSize = 0; // accumulate min size of all participating definitions for (int i = 0, count = _registry.Count; i < count; ++i) { sharedMinSize = Math.Max(sharedMinSize, _registry[i].MinSize); } bool sharedMinSizeChanged = !DoubleUtil.AreClose(_minSize, sharedMinSize); // compare accumulated min size with min sizes of the individual definitions for (int i = 0, count = _registry.Count; i < count; ++i) { DefinitionBase definitionBase = _registry[i]; if (sharedMinSizeChanged || definitionBase.LayoutWasUpdated) { // if definition's min size is different, then need to re-measure if (!DoubleUtil.AreClose(sharedMinSize, definitionBase.MinSize)) { Grid parentGrid = (Grid)definitionBase.Parent; parentGrid.InvalidateMeasure(); definitionBase.UseSharedMinimum = true; } else { definitionBase.UseSharedMinimum = false; // if measure is valid then also need to check arrange. // Note: definitionBase.SizeCache is volatile but at this point // it contains up-to-date final size if (!DoubleUtil.AreClose(sharedMinSize, definitionBase.SizeCache)) { Grid parentGrid = (Grid)definitionBase.Parent; parentGrid.InvalidateArrange(); } } definitionBase.LayoutWasUpdated = false; } } _minSize = sharedMinSize; _layoutUpdatedHost.LayoutUpdated -= _layoutUpdated; _layoutUpdatedHost = null; _broadcastInvalidation = true; } private readonly SharedSizeScope _sharedSizeScope; // the scope this state belongs to private readonly string _sharedSizeGroupId; // Id of the shared size group this object is servicing private readonly List_registry; // registry of participating definitions private readonly EventHandler _layoutUpdated; // instance event handler for layout updated event private UIElement _layoutUpdatedHost; // UIElement for which layout updated event handler is registered private bool _broadcastInvalidation; // "true" when broadcasting of invalidation is needed private bool _userSizeValid; // "true" when _userSize is up to date private GridLength _userSize; // shared state private double _minSize; // shared state } #endregion Private Structures Classes //------------------------------------------------------ // // Properties // //----------------------------------------------------- #region Properties /// /// Private shared size scope property holds a collection of shared state objects for the a given shared size scope. /// internal static readonly DependencyProperty PrivateSharedSizeScopeProperty = DependencyProperty.RegisterAttached( "PrivateSharedSizeScope", typeof(SharedSizeScope), typeof(DefinitionBase), new FrameworkPropertyMetadata( null, FrameworkPropertyMetadataOptions.Inherits)); ////// /// Shared size group property marks column / row definition as belonging to a group "Foo" or "Bar". /// ////// Value of the Shared Size Group Property must satisfy the following rules: /// public static readonly DependencyProperty SharedSizeGroupProperty = DependencyProperty.Register( "SharedSizeGroup", typeof(string), typeof(DefinitionBase), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnSharedSizeGroupPropertyChanged)), new ValidateValueCallback(SharedSizeGroupPropertyValueValid)); //////
///- ///
/// String must not be empty. /// - ///
/// String must consist of letters, digits and underscore ('_') only. /// - ///
/// String must not start with a digit. /// /// Static ctor. Used for static registration of properties. /// static DefinitionBase() { PrivateSharedSizeScopeProperty.OverrideMetadata( typeof(DefinitionBase), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnPrivateSharedSizeScopePropertyChanged))); } #endregion Properties } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // Specs // Grid : http://avalon/layout/Specs/Grid.mht // Size Sharing: http://avalon/layout/Specs/Size%20Information%20Sharing.doc // // Misc // Grid Tutorial: http://avalon/layout/Documentation%20and%20Tutorials/Grid%20Tutorial.mht // // Description: Implementation of base abstract class for ColumnDefinition // and RowDefinition. // // History: // 11/17/2003 : olego - Created // //--------------------------------------------------------------------------- using MS.Internal; using MS.Internal.KnownBoxes; using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Security.Permissions; using System.Windows; using System.Windows.Threading; namespace System.Windows.Controls { ////// DefinitionBase provides core functionality used internally by Grid /// and ColumnDefinitionCollection / RowDefinitionCollection /// [Localizability(LocalizationCategory.Ignore)] public abstract class DefinitionBase : FrameworkContentElement { //----------------------------------------------------- // // Constructors // //----------------------------------------------------- #region Constructors internal DefinitionBase(bool isColumnDefinition) { _isColumnDefinition = isColumnDefinition; _parentIndex = -1; } #endregion Constructors //------------------------------------------------------ // // Public Properties // //----------------------------------------------------- #region Public Properties ////// SharedSizeGroup property. /// public string SharedSizeGroup { get { return (string) GetValue(SharedSizeGroupProperty); } set { SetValue(SharedSizeGroupProperty, value); } } #endregion Public Properties //------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ #region Internal Methods ////// Callback to notify about entering model tree. /// internal void OnEnterParentTree() { if (_sharedState == null) { // start with getting SharedSizeGroup value. // this property is NOT inhereted which should result in better overall perf. string sharedSizeGroupId = SharedSizeGroup; if (sharedSizeGroupId != null) { SharedSizeScope privateSharedSizeScope = PrivateSharedSizeScope; if (privateSharedSizeScope != null) { _sharedState = privateSharedSizeScope.EnsureSharedState(sharedSizeGroupId); _sharedState.AddMember(this); } } } } ////// Callback to notify about exitting model tree. /// internal void OnExitParentTree() { _offset = 0; if (_sharedState != null) { _sharedState.RemoveMember(this); _sharedState = null; } } ////// Performs action preparing definition to enter layout calculation mode. /// internal void OnBeforeLayout(Grid grid) { // reset layout state. _minSize = 0; LayoutWasUpdated = true; // defer verification for shared definitions if (_sharedState != null) { _sharedState.EnsureDeferredValidation(grid); } } ////// Updates min size. /// /// New size. internal void UpdateMinSize(double minSize) { _minSize = Math.Max(_minSize, minSize); } ////// ////// /// This method needs to be internal to be accessable from derived classes. /// internal static void OnUserSizePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { DefinitionBase definition = (DefinitionBase) d; if (definition.InParentLogicalTree) { if (definition._sharedState != null) { definition._sharedState.Invalidate(); } else { Grid parentGrid = (Grid) definition.Parent; if (((GridLength) e.OldValue).GridUnitType != ((GridLength) e.NewValue).GridUnitType) { parentGrid.Invalidate(); } else { parentGrid.InvalidateMeasure(); } } } } ////// ////// /// This method needs to be internal to be accessable from derived classes. /// internal static bool IsUserSizePropertyValueValid(object value) { return (((GridLength)value).Value >= 0); } ////// ////// /// This method needs to be internal to be accessable from derived classes. /// internal static void OnUserMinSizePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { DefinitionBase definition = (DefinitionBase) d; if (definition.InParentLogicalTree) { Grid parentGrid = (Grid) definition.Parent; parentGrid.InvalidateMeasure(); } } ////// ////// /// This method needs to be internal to be accessable from derived classes. /// internal static bool IsUserMinSizePropertyValueValid(object value) { double v = (double)value; return (!DoubleUtil.IsNaN(v) && v >= 0.0d && !Double.IsPositiveInfinity(v)); } ////// ////// /// This method needs to be internal to be accessable from derived classes. /// internal static void OnUserMaxSizePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { DefinitionBase definition = (DefinitionBase) d; if (definition.InParentLogicalTree) { Grid parentGrid = (Grid) definition.Parent; parentGrid.InvalidateMeasure(); } } ////// ////// /// This method needs to be internal to be accessable from derived classes. /// internal static bool IsUserMaxSizePropertyValueValid(object value) { double v = (double)value; return (!DoubleUtil.IsNaN(v) && v >= 0.0d); } ////// ////// /// This method reflects Grid.SharedScopeProperty state by setting / clearing /// dynamic property PrivateSharedSizeScopeProperty. Value of PrivateSharedSizeScopeProperty /// is a collection of SharedSizeState objects for the scope. /// Also PrivateSharedSizeScopeProperty is FrameworkPropertyMetadataOptions.Inherits property. So that all children /// elements belonging to a certain scope can easily access SharedSizeState collection. As well /// as been norified about enter / exit a scope. /// internal static void OnIsSharedSizeScopePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { // if ((bool) e.NewValue) { SharedSizeScope sharedStatesCollection = new SharedSizeScope(); d.SetValue(PrivateSharedSizeScopeProperty, sharedStatesCollection); } else { d.ClearValue(PrivateSharedSizeScopeProperty); } } #endregion Internal Methods //----------------------------------------------------- // // Internal Properties // //------------------------------------------------------ #region Internal Properties ////// Returns internal bool IsShared { get { return (_sharedState != null); } } ///true if this definition is a part of shared group. ////// Internal accessor to user size field. /// internal GridLength UserSize { get { return (_sharedState != null ? _sharedState.UserSize : UserSizeValueCache); } } ////// Internal accessor to user min size field. /// internal double UserMinSize { get { return (UserMinSizeValueCache); } } ////// Internal accessor to user max size field. /// internal double UserMaxSize { get { return (UserMaxSizeValueCache); } } ////// DefinitionBase's index in the parents collection. /// internal int Index { get { return (_parentIndex); } set { Debug.Assert(value >= -1 && _parentIndex != value); _parentIndex = value; } } ////// Layout-time user size type. /// internal Grid.LayoutTimeSizeType SizeType { get { return (_sizeType); } set { _sizeType = value; } } ////// Returns or sets measure size for the definition. /// internal double MeasureSize { get { return (_measureSize); } set { _measureSize = value; } } ////// Returns definition's layout time type sensitive preferred size. /// ////// Returned value is guaranteed to be true preferred size. /// internal double PreferredSize { get { double preferredSize = MinSize; if ( _sizeType != Grid.LayoutTimeSizeType.Auto && preferredSize < _measureSize ) { preferredSize = _measureSize; } return (preferredSize); } } ////// Returns or sets size cache for the definition. /// internal double SizeCache { get { return (_sizeCache); } set { _sizeCache = value; } } ////// Returns min size. /// internal double MinSize { get { double minSize = _minSize; if ( UseSharedMinimum && _sharedState != null && minSize < _sharedState.MinSize ) { minSize = _sharedState.MinSize; } return (minSize); } } ////// Returns min size, always taking into account shared state. /// internal double MinSizeForArrange { get { double minSize = _minSize; if ( _sharedState != null && (UseSharedMinimum || !LayoutWasUpdated) && minSize < _sharedState.MinSize ) { minSize = _sharedState.MinSize; } return (minSize); } } ////// Offset. /// internal double FinalOffset { get { return _offset; } set { _offset = value; } } ////// Internal helper to access up-to-date UserSize property value. /// internal GridLength UserSizeValueCache { get { return (GridLength) GetValue( _isColumnDefinition ? ColumnDefinition.WidthProperty : RowDefinition.HeightProperty); } } ////// Internal helper to access up-to-date UserMinSize property value. /// internal double UserMinSizeValueCache { get { return (double) GetValue( _isColumnDefinition ? ColumnDefinition.MinWidthProperty : RowDefinition.MinHeightProperty); } } ////// Internal helper to access up-to-date UserMaxSize property value. /// internal double UserMaxSizeValueCache { get { return (double) GetValue( _isColumnDefinition ? ColumnDefinition.MaxWidthProperty : RowDefinition.MaxHeightProperty); } } ////// Protected. Returns internal bool InParentLogicalTree { get { return (_parentIndex != -1); } } #endregion Internal Properties //----------------------------------------------------- // // Private Methods // //----------------------------------------------------- #region Private Methods ///true if this DefinitionBase instance is in parent's logical tree. ////// SetFlags is used to set or unset one or multiple /// flags on the object. /// private void SetFlags(bool value, Flags flags) { _flags = value ? (_flags | flags) : (_flags & (~flags)); } ////// CheckFlagsAnd returns private bool CheckFlagsAnd(Flags flags) { return ((_flags & flags) == flags); } ///true if all the flags in the /// given bitmask are set on the object. ////// private static void OnSharedSizeGroupPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { DefinitionBase definition = (DefinitionBase) d; if (definition.InParentLogicalTree) { string sharedSizeGroupId = (string) e.NewValue; if (definition._sharedState != null) { // if definition is already registered AND shared size group id is changing, // then un-register the definition from the current shared size state object. definition._sharedState.RemoveMember(definition); definition._sharedState = null; } if ((definition._sharedState == null) && (sharedSizeGroupId != null)) { SharedSizeScope privateSharedSizeScope = definition.PrivateSharedSizeScope; if (privateSharedSizeScope != null) { // if definition is not registered and both: shared size group id AND private shared scope // are available, then register definition. definition._sharedState = privateSharedSizeScope.EnsureSharedState(sharedSizeGroupId); definition._sharedState.AddMember(definition); } } } } ////// /// ////// /// Verifies that Shared Size Group Property string /// a) not empty. /// b) contains only letters, digits and underscore ('_'). /// c) does not start with a digit. /// private static bool SharedSizeGroupPropertyValueValid(object value) { // null is default value if (value == null) { return (true); } string id = (string)value; if (id != string.Empty) { int i = -1; while (++i < id.Length) { bool isDigit = Char.IsDigit(id[i]); if ( (i == 0 && isDigit) || !( isDigit || Char.IsLetter(id[i]) || '_' == id[i] ) ) { break; } } if (i == id.Length) { return (true); } } return (false); } ////// ////// /// OnPrivateSharedSizeScopePropertyChanged is called when new scope enters or /// existing scope just left. In both cases if the DefinitionBase object is already registered /// in SharedSizeState, it should un-register and register itself in a new one. /// private static void OnPrivateSharedSizeScopePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { DefinitionBase definition = (DefinitionBase)d; if (definition.InParentLogicalTree) { SharedSizeScope privateSharedSizeScope = (SharedSizeScope) e.NewValue; if (definition._sharedState != null) { // if definition is already registered And shared size scope is changing, // then un-register the definition from the current shared size state object. definition._sharedState.RemoveMember(definition); definition._sharedState = null; } if ((definition._sharedState == null) && (privateSharedSizeScope != null)) { string sharedSizeGroup = definition.SharedSizeGroup; if (sharedSizeGroup != null) { // if definition is not registered and both: shared size group id AND private shared scope // are available, then register definition. definition._sharedState = privateSharedSizeScope.EnsureSharedState(definition.SharedSizeGroup); definition._sharedState.AddMember(definition); } } } } #endregion Private Methods //----------------------------------------------------- // // Private Properties // //------------------------------------------------------ #region Private Properties ////// Private getter of shared state collection dynamic property. /// private SharedSizeScope PrivateSharedSizeScope { get { return (SharedSizeScope) GetValue(PrivateSharedSizeScopeProperty); } } ////// Convenience accessor to UseSharedMinimum flag /// private bool UseSharedMinimum { get { return (CheckFlagsAnd(Flags.UseSharedMinimum)); } set { SetFlags(value, Flags.UseSharedMinimum); } } ////// Convenience accessor to LayoutWasUpdated flag /// private bool LayoutWasUpdated { get { return (CheckFlagsAnd(Flags.LayoutWasUpdated)); } set { SetFlags(value, Flags.LayoutWasUpdated); } } #endregion Private Properties //----------------------------------------------------- // // Private Fields // //------------------------------------------------------ #region Private Fields private readonly bool _isColumnDefinition; // when "true", this is a ColumnDefinition; when "false" this is a RowDefinition (faster than a type check) private Flags _flags; // flags reflecting various aspects of internal state private int _parentIndex; // this instance's index in parent's children collection private Grid.LayoutTimeSizeType _sizeType; // layout-time user size type. it may differ from _userSizeValueCache.UnitType when calculating "to-content" private double _minSize; // used during measure to accumulate size for "Auto" and "Star" DefinitionBase's private double _measureSize; // size, calculated to be the input contstraint size for Child.Measure private double _sizeCache; // cache used for various purposes (sorting, caching, etc) during calculations private double _offset; // offset of the DefinitionBase from left / top corner (assuming LTR case) private SharedSizeState _sharedState; // reference to shared state object this instance is registered with internal const bool ThisIsColumnDefinition = true; internal const bool ThisIsRowDefinition = false; #endregion Private Fields //------------------------------------------------------ // // Private Structures / Classes // //----------------------------------------------------- #region Private Structures Classes [System.Flags] private enum Flags : byte { // // bool flags // UseSharedMinimum = 0x00000020, // when "1", definition will take into account shared state's minimum LayoutWasUpdated = 0x00000040, // set to "1" every time the parent grid is measured } ////// Collection of shared states objects for a single scope /// private class SharedSizeScope { ////// Returns SharedSizeState object for a given group. /// Creates a new StatedState object if necessary. /// internal SharedSizeState EnsureSharedState(string sharedSizeGroup) { // check that sharedSizeGroup is not default Debug.Assert(sharedSizeGroup != null); SharedSizeState sharedState = _registry[sharedSizeGroup] as SharedSizeState; if (sharedState == null) { sharedState = new SharedSizeState(this, sharedSizeGroup); _registry[sharedSizeGroup] = sharedState; } return (sharedState); } ////// Removes an entry in the registry by the given key. /// internal void Remove(object key) { Debug.Assert(_registry.Contains(key)); _registry.Remove(key); } private Hashtable _registry = new Hashtable(); // storage for shared state objects } ////// Implementation of per shared group state object /// private class SharedSizeState { ////// Default ctor. /// internal SharedSizeState(SharedSizeScope sharedSizeScope, string sharedSizeGroupId) { Debug.Assert(sharedSizeScope != null && sharedSizeGroupId != null); _sharedSizeScope = sharedSizeScope; _sharedSizeGroupId = sharedSizeGroupId; _registry = new List(); _layoutUpdated = new EventHandler(OnLayoutUpdated); _broadcastInvalidation = true; } /// /// Adds / registers a definition instance. /// internal void AddMember(DefinitionBase member) { Debug.Assert(!_registry.Contains(member)); _registry.Add(member); Invalidate(); } ////// Removes / un-registers a definition instance. /// ////// If the collection of registered definitions becomes empty /// instantiates self removal from owner's collection. /// internal void RemoveMember(DefinitionBase member) { Invalidate(); _registry.Remove(member); if (_registry.Count == 0) { _sharedSizeScope.Remove(_sharedSizeGroupId); } } ////// Propogates invalidations for all registered definitions. /// Resets its own state. /// internal void Invalidate() { _userSizeValid = false; if (_broadcastInvalidation) { for (int i = 0, count = _registry.Count; i < count; ++i) { Grid parentGrid = (Grid)(_registry[i].Parent); parentGrid.Invalidate(); } _broadcastInvalidation = false; } } ////// Makes sure that one and only one layout updated handler is registered for this shared state. /// internal void EnsureDeferredValidation(UIElement layoutUpdatedHost) { if (_layoutUpdatedHost == null) { _layoutUpdatedHost = layoutUpdatedHost; _layoutUpdatedHost.LayoutUpdated += _layoutUpdated; } } ////// DefinitionBase's specific code. /// internal double MinSize { get { if (!_userSizeValid) { EnsureUserSizeValid(); } return (_minSize); } } ////// DefinitionBase's specific code. /// internal GridLength UserSize { get { if (!_userSizeValid) { EnsureUserSizeValid(); } return (_userSize); } } private void EnsureUserSizeValid() { _userSize = new GridLength(1, GridUnitType.Auto); for (int i = 0, count = _registry.Count; i < count; ++i) { Debug.Assert( _userSize.GridUnitType == GridUnitType.Auto || _userSize.GridUnitType == GridUnitType.Pixel ); GridLength currentGridLength = _registry[i].UserSizeValueCache; if (currentGridLength.GridUnitType == GridUnitType.Pixel) { if (_userSize.GridUnitType == GridUnitType.Auto) { _userSize = currentGridLength; } else if (_userSize.Value < currentGridLength.Value) { _userSize = currentGridLength; } } } // taking maximum with user size effectively prevents squishy-ness. // this is a "solution" to avoid shared definitions from been sized to // different final size at arrange time, if / when different grids receive // different final sizes. _minSize = _userSize.IsAbsolute ? _userSize.Value : 0.0; _userSizeValid = true; } ////// OnLayoutUpdated handler. Validates that all participating definitions /// have updated min size value. Forces another layout update cycle if needed. /// private void OnLayoutUpdated(object sender, EventArgs e) { double sharedMinSize = 0; // accumulate min size of all participating definitions for (int i = 0, count = _registry.Count; i < count; ++i) { sharedMinSize = Math.Max(sharedMinSize, _registry[i].MinSize); } bool sharedMinSizeChanged = !DoubleUtil.AreClose(_minSize, sharedMinSize); // compare accumulated min size with min sizes of the individual definitions for (int i = 0, count = _registry.Count; i < count; ++i) { DefinitionBase definitionBase = _registry[i]; if (sharedMinSizeChanged || definitionBase.LayoutWasUpdated) { // if definition's min size is different, then need to re-measure if (!DoubleUtil.AreClose(sharedMinSize, definitionBase.MinSize)) { Grid parentGrid = (Grid)definitionBase.Parent; parentGrid.InvalidateMeasure(); definitionBase.UseSharedMinimum = true; } else { definitionBase.UseSharedMinimum = false; // if measure is valid then also need to check arrange. // Note: definitionBase.SizeCache is volatile but at this point // it contains up-to-date final size if (!DoubleUtil.AreClose(sharedMinSize, definitionBase.SizeCache)) { Grid parentGrid = (Grid)definitionBase.Parent; parentGrid.InvalidateArrange(); } } definitionBase.LayoutWasUpdated = false; } } _minSize = sharedMinSize; _layoutUpdatedHost.LayoutUpdated -= _layoutUpdated; _layoutUpdatedHost = null; _broadcastInvalidation = true; } private readonly SharedSizeScope _sharedSizeScope; // the scope this state belongs to private readonly string _sharedSizeGroupId; // Id of the shared size group this object is servicing private readonly List_registry; // registry of participating definitions private readonly EventHandler _layoutUpdated; // instance event handler for layout updated event private UIElement _layoutUpdatedHost; // UIElement for which layout updated event handler is registered private bool _broadcastInvalidation; // "true" when broadcasting of invalidation is needed private bool _userSizeValid; // "true" when _userSize is up to date private GridLength _userSize; // shared state private double _minSize; // shared state } #endregion Private Structures Classes //------------------------------------------------------ // // Properties // //----------------------------------------------------- #region Properties /// /// Private shared size scope property holds a collection of shared state objects for the a given shared size scope. /// internal static readonly DependencyProperty PrivateSharedSizeScopeProperty = DependencyProperty.RegisterAttached( "PrivateSharedSizeScope", typeof(SharedSizeScope), typeof(DefinitionBase), new FrameworkPropertyMetadata( null, FrameworkPropertyMetadataOptions.Inherits)); ////// /// Shared size group property marks column / row definition as belonging to a group "Foo" or "Bar". /// ////// Value of the Shared Size Group Property must satisfy the following rules: /// public static readonly DependencyProperty SharedSizeGroupProperty = DependencyProperty.Register( "SharedSizeGroup", typeof(string), typeof(DefinitionBase), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnSharedSizeGroupPropertyChanged)), new ValidateValueCallback(SharedSizeGroupPropertyValueValid)); //////
///- ///
/// String must not be empty. /// - ///
/// String must consist of letters, digits and underscore ('_') only. /// - ///
/// String must not start with a digit. /// /// Static ctor. Used for static registration of properties. /// static DefinitionBase() { PrivateSharedSizeScopeProperty.OverrideMetadata( typeof(DefinitionBase), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnPrivateSharedSizeScopePropertyChanged))); } #endregion Properties } } // 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
- WebControl.cs
- HttpChannelHelpers.cs
- ResourcePermissionBase.cs
- EntityCommand.cs
- PermissionToken.cs
- SessionPageStatePersister.cs
- EditorPart.cs
- DataGridViewRowConverter.cs
- SqlCachedBuffer.cs
- XmlBufferReader.cs
- HeaderCollection.cs
- XmlSchemaFacet.cs
- ConfigUtil.cs
- XmlObjectSerializerReadContextComplex.cs
- InfoCardAsymmetricCrypto.cs
- HtmlMobileTextWriter.cs
- GuidTagList.cs
- PolyLineSegmentFigureLogic.cs
- XPathBinder.cs
- WsatTransactionHeader.cs
- ObjectDataProvider.cs
- MenuItemBindingCollection.cs
- RadioButtonRenderer.cs
- EndpointAddress.cs
- SecurityUniqueId.cs
- CurrencyManager.cs
- TextUtf8RawTextWriter.cs
- HyperLink.cs
- ComplexBindingPropertiesAttribute.cs
- AsymmetricKeyExchangeFormatter.cs
- BaseTransportHeaders.cs
- NotImplementedException.cs
- ListViewInsertedEventArgs.cs
- SQLString.cs
- Hash.cs
- UserControlFileEditor.cs
- ParentQuery.cs
- AuthenticatingEventArgs.cs
- ReadOnlyHierarchicalDataSource.cs
- AutomationPatternInfo.cs
- AutoCompleteStringCollection.cs
- CalendarAutomationPeer.cs
- ClientCredentialsSecurityTokenManager.cs
- MetadataCacheItem.cs
- X509Chain.cs
- BooleanStorage.cs
- APCustomTypeDescriptor.cs
- AssemblyCollection.cs
- RouteData.cs
- x509utils.cs
- DataGridCheckBoxColumn.cs
- __ComObject.cs
- FontCacheUtil.cs
- ReadOnlyState.cs
- Aggregates.cs
- SqlTriggerAttribute.cs
- WindowsGraphics.cs
- SequenceDesigner.cs
- UnsafeNativeMethods.cs
- HMACMD5.cs
- SvcMapFileSerializer.cs
- GuidelineCollection.cs
- PolygonHotSpot.cs
- LocationInfo.cs
- XhtmlTextWriter.cs
- ContextMenuStrip.cs
- UnsafeNativeMethods.cs
- ExpiredSecurityTokenException.cs
- DoubleAnimationClockResource.cs
- XmlSchemaSequence.cs
- RenderCapability.cs
- HttpAsyncResult.cs
- WebServiceTypeData.cs
- HttpSysSettings.cs
- ToolStripControlHost.cs
- DisplayToken.cs
- Enum.cs
- invalidudtexception.cs
- EnumValAlphaComparer.cs
- WindowsFont.cs
- WorkflowValidationFailedException.cs
- NotifyInputEventArgs.cs
- GetIsBrowserClientRequest.cs
- PriorityBindingExpression.cs
- BinaryFormatterWriter.cs
- DynamicEndpointElement.cs
- ControlAdapter.cs
- CompositeCollection.cs
- ConstructorBuilder.cs
- EndEvent.cs
- XpsFixedDocumentReaderWriter.cs
- AssertSection.cs
- BackStopAuthenticationModule.cs
- TypeLoadException.cs
- WebPartDescription.cs
- NgenServicingAttributes.cs
- XmlTextAttribute.cs
- WebControlAdapter.cs
- Rect3DConverter.cs
- unitconverter.cs