/// <summary>
            /// Removes / un-registers a definition instance.
            /// </summary>
            /// <remarks>
            /// If the collection of registered definitions becomes empty
            /// instantiates self removal from owner's collection.
            /// </remarks>
            internal void RemoveMember(DefinitionBase member)
            {
                Invalidate();
                _registry.Remove(member);

                if (_registry.Count == 0)
                {
                    _sharedSizeScope.Remove(_sharedSizeGroupId);
                }
            }
Пример #2
0
 internal DistributionOrderIndexComparer(DefinitionBase[] definitions) 
 {
     Invariant.Assert(definitions != null); 
     this.definitions = definitions; 
 }
 /// <summary>
 /// Adds / registers a definition instance.
 /// </summary>
 internal void AddMember(DefinitionBase member)
 {
     Debug.Assert(!_registry.Contains(member));
     _registry.Add(member);
     Invalidate();
 }
Пример #4
0
        /// <summary>
        /// Calculates and sets final size for all definitions in the given array. 
        /// </summary> 
        /// <param name="definitions">Array of definitions to process.</param>
        /// <param name="finalSize">Final size to lay out to.</param> 
        /// <param name="rows">True if sizing row definitions, false for columns</param>
        private void SetFinalSize(
            DefinitionBase[] definitions,
            double finalSize, 
            bool columns)
        { 
            int starDefinitionsCount = 0;                       //  traverses form the first entry up 
            int nonStarIndex = definitions.Length;              //  traverses from the last entry down
            double allPreferredArrangeSize = 0; 
            bool useLayoutRounding = this.UseLayoutRounding;
            int[] definitionIndices = DefinitionIndices;
            double[] roundingErrors = null;
 
            // If using layout rounding, check whether rounding needs to compensate for high DPI
            double dpi = 1.0; 
 
            if (useLayoutRounding)
            { 
                dpi = columns ? FrameworkElement.DpiScaleX : FrameworkElement.DpiScaleY;
                roundingErrors = RoundingErrors;
            }
 
            for (int i = 0; i < definitions.Length; ++i)
            { 
                //  if definition is shared then is cannot be star 
                Debug.Assert(!definitions[i].IsShared || !definitions[i].UserSize.IsStar);
 
                if (definitions[i].UserSize.IsStar)
                {
                    double starValue = definitions[i].UserSize.Value;
 
                    if (_IsZero(starValue))
                    { 
                        //  cach normilized star value temporary into MeasureSize 
                        definitions[i].MeasureSize = 0;
                        definitions[i].SizeCache = 0; 
                    }
                    else
                    {
                        //  clipping by c_starClip guarantees that sum of even a very big number of max'ed out star values 
                        //  can be summed up without overflow
                        starValue = Math.Min(starValue, c_starClip); 
 
                        //  Note: normalized star value is temporary cached into MeasureSize
                        definitions[i].MeasureSize = starValue; 
                        double maxSize = Math.Max(definitions[i].MinSizeForArrange, definitions[i].UserMaxSize);
                        maxSize = Math.Min(maxSize, c_starClip);
                        definitions[i].SizeCache = maxSize / starValue;
                        if (useLayoutRounding) 
                        {
                            roundingErrors[i] = definitions[i].SizeCache; 
                            definitions[i].SizeCache = UIElement.RoundLayoutValue(definitions[i].SizeCache, dpi); 
                        }
                    } 
                    definitionIndices[starDefinitionsCount++] = i;
                }
                else
                { 
                    double userSize = 0;
 
                    switch (definitions[i].UserSize.GridUnitType) 
                    {
                        case (GridUnitType.Pixel): 
                            userSize = definitions[i].UserSize.Value;
                            break;

                        case (GridUnitType.Auto): 
                            userSize = definitions[i].MinSizeForArrange;
                            break; 
                    } 

                    double userMaxSize; 

                    if (definitions[i].IsShared)
                    {
                        //  overriding userMaxSize 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. 
                        userMaxSize = userSize;
                    } 
                    else
                    {
                        userMaxSize = definitions[i].UserMaxSize;
                    } 

                    definitions[i].SizeCache = Math.Max(definitions[i].MinSizeForArrange, Math.Min(userSize, userMaxSize)); 
                    if (useLayoutRounding) 
                    {
                        roundingErrors[i] = definitions[i].SizeCache; 
                        definitions[i].SizeCache = UIElement.RoundLayoutValue(definitions[i].SizeCache, dpi);
                    }

                    allPreferredArrangeSize += definitions[i].SizeCache; 
                    definitionIndices[--nonStarIndex] = i;
                } 
            } 

            //  indices should meet 
            Debug.Assert(nonStarIndex == starDefinitionsCount);

            if (starDefinitionsCount > 0)
            { 
                StarDistributionOrderIndexComparer starDistributionOrderIndexComparer = new StarDistributionOrderIndexComparer(definitions);
                Array.Sort(definitionIndices, 0, starDefinitionsCount, starDistributionOrderIndexComparer); 
 
                //  the 'do {} while' loop below calculates sum of star weights in order to avoid fp overflow...
                //  partial sum value is stored in each definition's SizeCache member. 
                //  this way the algorithm guarantees (starValue <= definition.SizeCache) and thus
                //  (starValue / definition.SizeCache) will never overflow due to sum of star weights becoming zero.
                //  this is an important change from previous implementation where the following was possible:
                //  ((BigValueStar + SmallValueStar) - BigValueStar) resulting in 0... 
                double allStarWeights = 0;
                int i = starDefinitionsCount - 1; 
                do 
                {
                    allStarWeights += definitions[definitionIndices[i]].MeasureSize; 
                    definitions[definitionIndices[i]].SizeCache = allStarWeights;
                } while (--i >= 0);

                i = 0; 
                do
                { 
                    double resolvedSize; 
                    double starValue = definitions[definitionIndices[i]].MeasureSize;
 
                    if (_IsZero(starValue))
                    {
                        resolvedSize = definitions[definitionIndices[i]].MinSizeForArrange;
                    } 
                    else
                    { 
                        double userSize = Math.Max(finalSize - allPreferredArrangeSize, 0.0) * (starValue / definitions[definitionIndices[i]].SizeCache); 
                        resolvedSize = Math.Min(userSize, definitions[definitionIndices[i]].UserMaxSize);
                        resolvedSize = Math.Max(definitions[definitionIndices[i]].MinSizeForArrange, resolvedSize); 
                    }

                    definitions[definitionIndices[i]].SizeCache = resolvedSize;
                    if (useLayoutRounding) 
                    {
                        roundingErrors[definitionIndices[i]] = definitions[definitionIndices[i]].SizeCache; 
                        definitions[definitionIndices[i]].SizeCache = UIElement.RoundLayoutValue(definitions[definitionIndices[i]].SizeCache, dpi); 
                    }
 
                    allPreferredArrangeSize += definitions[definitionIndices[i]].SizeCache;
                } while (++i < starDefinitionsCount);
            }
 
            if (    allPreferredArrangeSize > finalSize
                &&  !_AreClose(allPreferredArrangeSize, finalSize)  ) 
            { 
                DistributionOrderIndexComparer distributionOrderIndexComparer = new DistributionOrderIndexComparer(definitions);
                Array.Sort(definitionIndices, 0, definitions.Length, distributionOrderIndexComparer); 
                double sizeToDistribute = finalSize - allPreferredArrangeSize;

                for (int i = 0; i < definitions.Length; ++i)
                { 
                    int definitionIndex = definitionIndices[i];
                    double final = definitions[definitionIndex].SizeCache + (sizeToDistribute / (definitions.Length - i)); 
                    double finalOld = final; 
                    final = Math.Max(final, definitions[definitionIndex].MinSizeForArrange);
                    final = Math.Min(final, definitions[definitionIndex].SizeCache); 

                    if (useLayoutRounding)
                    {
                        roundingErrors[definitionIndex] = final; 
                        final = UIElement.RoundLayoutValue(finalOld, dpi);
                        final = Math.Max(final, definitions[definitionIndex].MinSizeForArrange); 
                        final = Math.Min(final, definitions[definitionIndex].SizeCache); 
                    }
 
                    sizeToDistribute -= (final - definitions[definitionIndex].SizeCache);
                    definitions[definitionIndex].SizeCache = final;
                }
 
                allPreferredArrangeSize = finalSize - sizeToDistribute;
            } 
 
            if (useLayoutRounding)
            { 
                if (!_AreClose(allPreferredArrangeSize, finalSize))
                {
                    // Compute deltas
                    for (int i = 0; i < definitions.Length; ++i) 
                    {
                        roundingErrors[i] = roundingErrors[i] - definitions[i].SizeCache; 
                        definitionIndices[i] = i; 
                    }
 
                    // Sort rounding errors
                    RoundingErrorIndexComparer roundingErrorIndexComparer = new RoundingErrorIndexComparer(roundingErrors);
                    Array.Sort(definitionIndices, 0, definitions.Length, roundingErrorIndexComparer);
                    double adjustedSize = allPreferredArrangeSize; 
                    double dpiIncrement = UIElement.RoundLayoutValue(1.0, dpi);
 
                    if (allPreferredArrangeSize > finalSize) 
                    {
                        int i = definitions.Length - 1; 
                        while ((adjustedSize > finalSize && !_AreClose(adjustedSize, finalSize)) && i >= 0)
                        {
                            DefinitionBase definition = definitions[definitionIndices[i]];
                            double final = definition.SizeCache - dpiIncrement; 
                            final = Math.Max(final, definition.MinSizeForArrange);
                            if (final < definition.SizeCache) 
                            { 
                                adjustedSize -= dpiIncrement;
                            } 
                            definition.SizeCache = final;
                            i--;
                        }
                    } 
                    else if (allPreferredArrangeSize < finalSize)
                    { 
                        int i = 0; 
                        while ((adjustedSize < finalSize && !_AreClose(adjustedSize, finalSize)) && i < definitions.Length)
                        { 
                            DefinitionBase definition = definitions[definitionIndices[i]];
                            double final = definition.SizeCache + dpiIncrement;
                            final = Math.Max(final, definition.MinSizeForArrange);
                            if (final > definition.SizeCache) 
                            {
                                adjustedSize += dpiIncrement; 
                            } 
                            definition.SizeCache = final;
                            i++; 
                        }
                    }
                }
            } 

            definitions[0].FinalOffset = 0.0; 
            for (int i = 0; i < definitions.Length; ++i) 
            {
                definitions[(i + 1) % definitions.Length].FinalOffset = definitions[i].FinalOffset + definitions[i].SizeCache; 
            }
        }
Пример #5
0
        /// <summary>
        /// Calculates final (aka arrange) size for given range. 
        /// </summary> 
        /// <param name="definitions">Array of definitions to process.</param>
        /// <param name="start">Start of the range.</param> 
        /// <param name="count">Number of items in the range.</param>
        /// <returns>Final size.</returns>
        private double GetFinalSizeForRange(
            DefinitionBase[] definitions, 
            int start,
            int count) 
        { 
            double size = 0;
            int i = start + count - 1; 

            do
            {
                size += definitions[i].SizeCache; 
            } while (--i >= start);
 
            return (size); 
        }
Пример #6
0
        /// <summary> 
        /// Resolves Star's for given array of definitions.
        /// </summary>
        /// <param name="definitions">Array of definitions to resolve stars.</param>
        /// <param name="availableSize">All available size.</param> 
        /// <remarks>
        /// Must initialize LayoutSize for all Star entries in given array of definitions. 
        /// </remarks> 
        private void ResolveStar(
            DefinitionBase[] definitions, 
            double availableSize)
        {
            DefinitionBase[] tempDefinitions = TempDefinitions;
            int starDefinitionsCount = 0; 
            double takenSize = 0;
 
            for (int i = 0; i < definitions.Length; ++i) 
            {
                switch (definitions[i].SizeType) 
                {
                    case (LayoutTimeSizeType.Auto):
                        takenSize += definitions[i].MinSize;
                        break; 
                    case (LayoutTimeSizeType.Pixel):
                        takenSize += definitions[i].MeasureSize; 
                        break; 
                    case (LayoutTimeSizeType.Star):
                        { 
                            tempDefinitions[starDefinitionsCount++] = definitions[i];

                            double starValue = definitions[i].UserSize.Value;
 
                            if (_IsZero(starValue))
                            { 
                                definitions[i].MeasureSize = 0; 
                                definitions[i].SizeCache = 0;
                            } 
                            else
                            {
                                //  clipping by c_starClip guarantees that sum of even a very big number of max'ed out star values
                                //  can be summed up without overflow 
                                starValue = Math.Min(starValue, c_starClip);
 
                                //  Note: normalized star value is temporary cached into MeasureSize 
                                definitions[i].MeasureSize = starValue;
                                double maxSize             = Math.Max(definitions[i].MinSize, definitions[i].UserMaxSize); 
                                maxSize                    = Math.Min(maxSize, c_starClip);
                                definitions[i].SizeCache   = maxSize / starValue;
                            }
                        } 
                        break;
                } 
            } 

            if (starDefinitionsCount > 0) 
            {
                Array.Sort(tempDefinitions, 0, starDefinitionsCount, s_starDistributionOrderComparer);

                //  the 'do {} while' loop below calculates sum of star weights in order to avoid fp overflow... 
                //  partial sum value is stored in each definition's SizeCache member.
                //  this way the algorithm guarantees (starValue <= definition.SizeCache) and thus 
                //  (starValue / definition.SizeCache) will never overflow due to sum of star weights becoming zero. 
                //  this is an important change from previous implementation where the following was possible:
                //  ((BigValueStar + SmallValueStar) - BigValueStar) resulting in 0... 
                double allStarWeights = 0;
                int i = starDefinitionsCount - 1;
                do
                { 
                    allStarWeights += tempDefinitions[i].MeasureSize;
                    tempDefinitions[i].SizeCache = allStarWeights; 
                } while (--i >= 0); 

                i = 0; 
                do
                {
                    double resolvedSize;
                    double starValue = tempDefinitions[i].MeasureSize; 

                    if (_IsZero(starValue)) 
                    { 
                        resolvedSize = tempDefinitions[i].MinSize;
                    } 
                    else
                    {
                        double userSize = Math.Max(availableSize - takenSize, 0.0) * (starValue / tempDefinitions[i].SizeCache);
                        resolvedSize    = Math.Min(userSize, tempDefinitions[i].UserMaxSize); 
                        resolvedSize    = Math.Max(tempDefinitions[i].MinSize, resolvedSize);
                    } 
 
                    tempDefinitions[i].MeasureSize = resolvedSize;
                    takenSize                     += resolvedSize; 
                } while (++i < starDefinitionsCount);
            }
        }
Пример #7
0
        /// <summary>
        /// Calculates desired size for given array of definitions. 
        /// </summary> 
        /// <param name="definitions">Array of definitions to use for calculations.</param>
        /// <returns>Desired size.</returns> 
        private double CalculateDesiredSize(
            DefinitionBase[] definitions)
        {
            double desiredSize = 0; 

            for (int i = 0; i < definitions.Length; ++i) 
            { 
                desiredSize += definitions[i].MinSize;
            } 

            return (desiredSize);
        }
Пример #8
0
        /// <summary>
        /// Accumulates length type information for given definition's range. 
        /// </summary> 
        /// <param name="definitions">Source array of definitions to read values from.</param>
        /// <param name="start">Starting index of the range.</param> 
        /// <param name="count">Number of definitions included in the range.</param>
        /// <returns>Length type for given range.</returns>
        private LayoutTimeSizeType GetLengthTypeForRange(
            DefinitionBase[] definitions, 
            int start,
            int count) 
        { 
            Debug.Assert(0 < count && 0 <= start && (start + count) <= definitions.Length);
 
            LayoutTimeSizeType lengthType = LayoutTimeSizeType.None;
            int i = start + count - 1;

            do 
            {
                lengthType |= definitions[i].SizeType; 
            } while (--i >= start); 

            return (lengthType); 
        }
Пример #9
0
        /// <summary>
        /// Distributes min size back to definition array's range. 
        /// </summary>
        /// <param name="start">Start of the range.</param> 
        /// <param name="count">Number of items in the range.</param> 
        /// <param name="requestedSize">Minimum size that should "fit" into the definitions range.</param>
        /// <param name="definitions">Definition array receiving distribution.</param> 
        /// <param name="percentReferenceSize">Size used to resolve percentages.</param>
        private void EnsureMinSizeInDefinitionRange(
            DefinitionBase[] definitions,
            int start, 
            int count,
            double requestedSize, 
            double percentReferenceSize) 
        {
            Debug.Assert(1 < count && 0 <= start && (start + count) <= definitions.Length); 

            //  avoid processing when asked to distribute "0"
            if (!_IsZero(requestedSize))
            { 
                DefinitionBase[] tempDefinitions = TempDefinitions; //  temp array used to remember definitions for sorting
                int end = start + count; 
                int autoDefinitionsCount = 0; 
                double rangeMinSize = 0;
                double rangePreferredSize = 0; 
                double rangeMaxSize = 0;
                double maxMaxSize = 0;                              //  maximum of maximum sizes

                //  first accumulate the necessary information: 
                //  a) sum up the sizes in the range;
                //  b) count the number of auto definitions in the range; 
                //  c) initialize temp array 
                //  d) cache the maximum size into SizeCache
                //  e) accumulate max of max sizes 
                for (int i = start; i < end; ++i)
                {
                    double minSize = definitions[i].MinSize;
                    double preferredSize = definitions[i].PreferredSize; 
                    double maxSize = Math.Max(definitions[i].UserMaxSize, minSize);
 
                    rangeMinSize += minSize; 
                    rangePreferredSize += preferredSize;
                    rangeMaxSize += maxSize; 

                    definitions[i].SizeCache = maxSize;

                    //  sanity check: no matter what, but min size must always be the smaller; 
                    //  max size must be the biggest; and preferred should be in between
                    Debug.Assert(   minSize <= preferredSize 
                                &&  preferredSize <= maxSize 
                                &&  rangeMinSize <= rangePreferredSize
                                &&  rangePreferredSize <= rangeMaxSize  ); 

                    if (maxMaxSize < maxSize)   maxMaxSize = maxSize;
                    if (definitions[i].UserSize.IsAuto) autoDefinitionsCount++;
                    tempDefinitions[i - start] = definitions[i]; 
                }
 
                //  avoid processing if the range already big enough 
                if (requestedSize > rangeMinSize)
                { 
                    if (requestedSize <= rangePreferredSize)
                    {
                        //
                        //  requestedSize fits into preferred size of the range. 
                        //  distribute according to the following logic:
                        //  * do not distribute into auto definitions - they should continue to stay "tight"; 
                        //  * for all non-auto definitions distribute to equi-size min sizes, without exceeding preferred size. 
                        //
                        //  in order to achieve that, definitions are sorted in a way that all auto definitions 
                        //  are first, then definitions follow ascending order with PreferredSize as the key of sorting.
                        //
                        double sizeToDistribute;
                        int i; 

                        Array.Sort(tempDefinitions, 0, count, s_spanPreferredDistributionOrderComparer); 
                        for (i = 0, sizeToDistribute = requestedSize; i < autoDefinitionsCount; ++i) 
                        {
                            //  sanity check: only auto definitions allowed in this loop 
                            Debug.Assert(tempDefinitions[i].UserSize.IsAuto);

                            //  adjust sizeToDistribute value by subtracting auto definition min size
                            sizeToDistribute -= (tempDefinitions[i].MinSize); 
                        }
 
                        for (; i < count; ++i) 
                        {
                            //  sanity check: no auto definitions allowed in this loop 
                            Debug.Assert(!tempDefinitions[i].UserSize.IsAuto);

                            double newMinSize = Math.Min(sizeToDistribute / (count - i), tempDefinitions[i].PreferredSize);
                            if (newMinSize > tempDefinitions[i].MinSize) { tempDefinitions[i].UpdateMinSize(newMinSize); } 
                            sizeToDistribute -= newMinSize;
                        } 
 
                        //  sanity check: requested size must all be distributed
                        Debug.Assert(_IsZero(sizeToDistribute)); 
                    }
                    else if (requestedSize <= rangeMaxSize)
                    {
                        // 
                        //  requestedSize bigger than preferred size, but fit into max size of the range.
                        //  distribute according to the following logic: 
                        //  * do not distribute into auto definitions, if possible - they should continue to stay "tight"; 
                        //  * for all non-auto definitions distribute to euqi-size min sizes, without exceeding max size.
                        // 
                        //  in order to achieve that, definitions are sorted in a way that all non-auto definitions
                        //  are last, then definitions follow ascending order with MaxSize as the key of sorting.
                        //
                        double sizeToDistribute; 
                        int i;
 
                        Array.Sort(tempDefinitions, 0, count, s_spanMaxDistributionOrderComparer); 
                        for (i = 0, sizeToDistribute = requestedSize - rangePreferredSize; i < count - autoDefinitionsCount; ++i)
                        { 
                            //  sanity check: no auto definitions allowed in this loop
                            Debug.Assert(!tempDefinitions[i].UserSize.IsAuto);

                            double preferredSize = tempDefinitions[i].PreferredSize; 
                            double newMinSize = preferredSize + sizeToDistribute / (count - autoDefinitionsCount - i);
                            tempDefinitions[i].UpdateMinSize(Math.Min(newMinSize, tempDefinitions[i].SizeCache)); 
                            sizeToDistribute -= (tempDefinitions[i].MinSize - preferredSize); 
                        }
 
                        for (; i < count; ++i)
                        {
                            //  sanity check: only auto definitions allowed in this loop
                            Debug.Assert(tempDefinitions[i].UserSize.IsAuto); 

                            double preferredSize = tempDefinitions[i].MinSize; 
                            double newMinSize = preferredSize + sizeToDistribute / (count - i); 
                            tempDefinitions[i].UpdateMinSize(Math.Min(newMinSize, tempDefinitions[i].SizeCache));
                            sizeToDistribute -= (tempDefinitions[i].MinSize - preferredSize); 
                        }

                        //  sanity check: requested size must all be distributed
                        Debug.Assert(_IsZero(sizeToDistribute)); 
                    }
                    else 
                    { 
                        //
                        //  requestedSize bigger than max size of the range. 
                        //  distribute according to the following logic:
                        //  * for all definitions distribute to equi-size min sizes.
                        //
                        double equalSize = requestedSize / count; 

                        if (    equalSize < maxMaxSize 
                            &&  !_AreClose(equalSize, maxMaxSize)   ) 
                        {
                            //  equi-size is less than maximum of maxSizes. 
                            //  in this case distribute so that smaller definitions grow faster than
                            //  bigger ones.
                            double totalRemainingSize = maxMaxSize * count - rangeMaxSize;
                            double sizeToDistribute = requestedSize - rangeMaxSize; 

                            //  sanity check: totalRemainingSize and sizeToDistribute must be real positive numbers 
                            Debug.Assert(   !double.IsInfinity(totalRemainingSize) 
                                        &&  !DoubleUtil.IsNaN(totalRemainingSize)
                                        &&  totalRemainingSize > 0 
                                        &&  !double.IsInfinity(sizeToDistribute)
                                        &&  !DoubleUtil.IsNaN(sizeToDistribute)
                                        &&  sizeToDistribute > 0    );
 
                            for (int i = 0; i < count; ++i)
                            { 
                                double deltaSize = (maxMaxSize - tempDefinitions[i].SizeCache) * sizeToDistribute / totalRemainingSize; 
                                tempDefinitions[i].UpdateMinSize(tempDefinitions[i].SizeCache + deltaSize);
                            } 
                        }
                        else
                        {
                            // 
                            //  equi-size is greater or equal to maximum of max sizes.
                            //  all definitions receive equalSize as their mim sizes. 
                            // 
                            for (int i = 0; i < count; ++i)
                            { 
                                tempDefinitions[i].UpdateMinSize(equalSize);
                            }
                        }
                    } 
                }
            } 
        } 
Пример #10
0
        /// <summary> 
        /// Validates layout time size type information on given array of definitions.
        /// Sets MinSize and MeasureSizes. 
        /// </summary> 
        /// <param name="definitions">Array of definitions to update.</param>
        /// <param name="treatStarAsAuto">if "true" then star definitions are treated as Auto.</param> 
        private void ValidateDefinitionsLayout(
            DefinitionBase[] definitions,
            bool treatStarAsAuto)
        { 
            for (int i = 0; i < definitions.Length; ++i)
            { 
                definitions[i].OnBeforeLayout(this); 

                double userMinSize = definitions[i].UserMinSize; 
                double userMaxSize = definitions[i].UserMaxSize;
                double userSize = 0;

                switch (definitions[i].UserSize.GridUnitType) 
                {
                    case (GridUnitType.Pixel): 
                        definitions[i].SizeType = LayoutTimeSizeType.Pixel; 
                        userSize = definitions[i].UserSize.Value;
                        // this was brought with NewLayout and defeats squishy behavior 
                        userMinSize = Math.Max(userMinSize, Math.Min(userSize, userMaxSize));
                        break;
                    case (GridUnitType.Auto):
                        definitions[i].SizeType = LayoutTimeSizeType.Auto; 
                        userSize = double.PositiveInfinity;
                        break; 
                    case (GridUnitType.Star): 
                        if (treatStarAsAuto)
                        { 
                            definitions[i].SizeType = LayoutTimeSizeType.Auto;
                            userSize = double.PositiveInfinity;
                        }
                        else 
                        {
                            definitions[i].SizeType = LayoutTimeSizeType.Star; 
                            userSize = double.PositiveInfinity; 
                        }
                        break; 
                    default:
                        Debug.Assert(false);
                        break;
                } 

                definitions[i].UpdateMinSize(userMinSize); 
                definitions[i].MeasureSize = Math.Max(userMinSize, Math.Min(userSize, userMaxSize)); 
            }
        } 
Пример #11
0
        /// <summary>
        /// Calculates one dimensional measure size for given definitions' range.
        /// </summary> 
        /// <param name="definitions">Source array of definitions to read values from.</param>
        /// <param name="start">Starting index of the range.</param> 
        /// <param name="count">Number of definitions included in the range.</param> 
        /// <returns>Calculated measure size.</returns>
        /// <remarks> 
        /// For "Auto" definitions MinWidth is used in place of PreferredSize.
        /// </remarks>
        private double GetMeasureSizeForRange(
            DefinitionBase[] definitions, 
            int start,
            int count) 
        { 
            Debug.Assert(0 < count && 0 <= start && (start + count) <= definitions.Length);
 
            double measureSize = 0;
            int i = start + count - 1;

            do 
            {
                measureSize += (definitions[i].SizeType == LayoutTimeSizeType.Auto) 
                    ? definitions[i].MinSize 
                    : definitions[i].MeasureSize;
            } while (--i >= start); 

            return (measureSize);
        }
Пример #12
0
 // Gets Column or Row definition at index from grid based on resize direction
 private static void SetDefinitionLength(DefinitionBase definition, GridLength length)
 {
     definition.SetValue(definition is ColumnDefinition ? ColumnDefinition.WidthProperty : RowDefinition.HeightProperty, length);
 }
Пример #13
0
        // Retrieves the ActualWidth or ActualHeight of the definition depending on its type Column or Row
        private double GetActualLength(DefinitionBase definition)
        {
            ColumnDefinition column = definition as ColumnDefinition;

            return column == null ? ((RowDefinition)definition).ActualHeight : column.ActualWidth;
        }
Пример #14
0
        // These methods are to help abstract dealing with rows and columns.  
        // DefinitionBase already has internal helpers for getting Width/Height, MinWidth/MinHeight, and MaxWidth/MaxHeight

        // Returns true if the row/column has a Star length
        private static bool IsStar(DefinitionBase definition)
        {
            return definition.UserSizeValueCache.IsStar;
        }
Пример #15
0
            /// <summary>
            /// OnLayoutUpdated handler. Validates that all participating definitions
            /// have updated min size value. Forces another layout update cycle if needed.
            /// </summary>
            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];

                    // we'll set d.UseSharedMinimum to maintain the invariant:
                    //      d.UseSharedMinimum iff d._minSize < this.MinSize
                    // i.e. iff d is not a "long-pole" definition.
                    //
                    // Measure/Arrange of d's Grid uses d._minSize for long-pole
                    // definitions, and max(d._minSize, shared size) for
                    // short-pole definitions.  This distinction allows us to react
                    // to changes in "long-pole-ness" more efficiently and correctly,
                    // by avoiding remeasures when a long-pole definition changes.
                    bool useSharedMinimum = !DoubleUtil.AreClose(definitionBase._minSize, sharedMinSize);

                    // before doing that, determine whether d's Grid needs to be remeasured.
                    // It's important _not_ to remeasure if the last measure is still
                    // valid, otherwise infinite loops are possible
                    bool measureIsValid;
                    if (!definitionBase.UseSharedMinimum)
                    {
                        // d was a long-pole.  measure is valid iff it's still a long-pole,
                        // since previous measure didn't use shared size.
                        measureIsValid = !useSharedMinimum;
                    }
                    else if (useSharedMinimum)
                    {
                        // d was a short-pole, and still is.  measure is valid
                        // iff the shared size didn't change
                        measureIsValid = !sharedMinSizeChanged;
                    }
                    else
                    {
                        // d was a short-pole, but is now a long-pole.  This can
                        // happen in several ways:
                        //  a. d's minSize increased to or past the old shared size
                        //  b. other long-pole definitions decreased, leaving
                        //      d as the new winner
                        // In the former case, the measure is valid - it used
                        // d's new larger minSize.  In the latter case, the
                        // measure is invalid - it used the old shared size,
                        // which is larger than d's (possibly changed) minSize
                        measureIsValid = (definitionBase.LayoutWasUpdated &&
                                          DoubleUtil.GreaterThanOrClose(definitionBase._minSize, this.MinSize));
                    }

                    if (!measureIsValid)
                    {
                        Grid parentGrid = (Grid)definitionBase.Parent;
                        parentGrid.InvalidateMeasure();
                    }
                    else if (!DoubleUtil.AreClose(sharedMinSize, definitionBase.SizeCache))
                    {
                        //  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
                        Grid parentGrid = (Grid)definitionBase.Parent;
                        parentGrid.InvalidateArrange();
                    }

                    // now we can restore the invariant, and clear the layout flag
                    definitionBase.UseSharedMinimum = useSharedMinimum;
                    definitionBase.LayoutWasUpdated = false;
                }

                _minSize = sharedMinSize;

                _layoutUpdatedHost.LayoutUpdated -= _layoutUpdated;
                _layoutUpdatedHost = null;

                _broadcastInvalidation = true;
            }
Пример #16
0
 /// <summary>
 /// Adds / registers a definition instance.
 /// </summary>
 internal void AddMember(DefinitionBase member)
 {
     Debug.Assert(!_registry.Contains(member));
     _registry.Add(member);
     Invalidate();
 }