Ejemplo n.º 1
0
        /// <summary> 
        /// Override for <seealso cref="UIElement.MeasureCore" />.
        /// </summary> 
        protected sealed override Size MeasureCore(Size availableSize)
        {
            Debug.Assert(MeasureData == null || availableSize == MeasureData.AvailableSize, "MeasureData needs to be passed down in [....] with size");
 
            // If using layout rounding, check whether rounding needs to compensate for high DPI
            bool useLayoutRounding = this.UseLayoutRounding; 
 
            if (useLayoutRounding)
            { 
                if (!CheckFlagsAnd(VisualFlags.UseLayoutRounding))
                {
                    this.SetFlags(true, VisualFlags.UseLayoutRounding);
                } 
            }
 
            //build the visual tree from styles first 
            ApplyTemplate();
 
            if (BypassLayoutPolicies)
            {
                return MeasureOverride(availableSize);
            } 
            else
            { 
                Thickness margin = Margin; 
                double marginWidth = margin.Left + margin.Right;
                double marginHeight = margin.Top + margin.Bottom; 
                MeasureData measureData = MeasureData;

                //  parent size is what parent want us to be
                Size frameworkAvailableSize = new Size( 
                Math.Max(availableSize.Width - marginWidth, 0),
                Math.Max(availableSize.Height - marginHeight, 0)); 
 
                MinMax mm = new MinMax(this);
 
                LayoutTransformData ltd = LayoutTransformDataField.GetValue(this);
                {
                    Transform layoutTransform = this.LayoutTransform;
                    //  check that LayoutTransform is non-trivial 
                    if (layoutTransform != null && !layoutTransform.IsIdentity)
                    { 
                        if (ltd == null) 
                        {
                            //  allocate and store ltd if needed 
                            ltd = new LayoutTransformData();
                            LayoutTransformDataField.SetValue(this, ltd);
                        }
 
                        ltd.CreateTransformSnapshot(layoutTransform);
                        ltd.UntransformedDS = new Size(); 
 
                        if (useLayoutRounding)
                        { 
                            ltd.TransformedUnroundedDS = new Size();
                        }
                    }
                    else if (ltd != null) 
                    {
                        //  clear ltd storage 
                        ltd = null; 
                        LayoutTransformDataField.ClearValue(this);
                    } 
                }

                if (ltd != null)
                { 
                    // Find the maximal area rectangle in local (child) space that we can fit, post-transform
                    // in the decorator's measure constraint. 
                    frameworkAvailableSize = FindMaximalAreaLocalSpaceRect(ltd.Transform, frameworkAvailableSize); 
                }
 
                frameworkAvailableSize.Width = Math.Max(mm.minWidth, Math.Min(frameworkAvailableSize.Width, mm.maxWidth));
                frameworkAvailableSize.Height = Math.Max(mm.minHeight, Math.Min(frameworkAvailableSize.Height, mm.maxHeight));

                // If layout rounding is enabled, round available size passed to MeasureOverride. 
                if (useLayoutRounding)
                { 
                    frameworkAvailableSize = UIElement.RoundLayoutSize(frameworkAvailableSize, FrameworkElement.DpiScaleX, FrameworkElement.DpiScaleY); 
                }
 
                //  call to specific layout to measure
                if (measureData != null)
                {
                    measureData.AvailableSize = frameworkAvailableSize; 
                }
                Size desiredSize = MeasureOverride(frameworkAvailableSize); 
 
                if (measureData != null)
                { 
                    // MeasureData should be treated like a parameter to Measure and thus not modified when returning from this call.
                    measureData.AvailableSize = availableSize;
                }
 
                //  maximize desiredSize with user provided min size
                desiredSize = new Size( 
                    Math.Max(desiredSize.Width, mm.minWidth), 
                    Math.Max(desiredSize.Height, mm.minHeight));
 
                //here is the "true minimum" desired size - the one that is
                //for sure enough for the control to render its content.
                Size unclippedDesiredSize = desiredSize;
 
                if (ltd != null)
                { 
                    //need to store unclipped, untransformed desired size to be able to arrange later 
                    ltd.UntransformedDS = unclippedDesiredSize;
 
                    //transform unclipped desired size
                    Rect unclippedBoundsTransformed = Rect.Transform(new Rect(0, 0, unclippedDesiredSize.Width, unclippedDesiredSize.Height), ltd.Transform.Value);
                    unclippedDesiredSize.Width = unclippedBoundsTransformed.Width;
                    unclippedDesiredSize.Height = unclippedBoundsTransformed.Height; 
                }
 
                bool clipped = false; 

                // User-specified max size starts to "clip" the control here. 
                //Starting from this point desiredSize could be smaller then actually
                //needed to render the whole control
                if (desiredSize.Width > mm.maxWidth)
                { 
                    desiredSize.Width = mm.maxWidth;
                    clipped = true; 
                } 

                if (desiredSize.Height > mm.maxHeight) 
                {
                    desiredSize.Height = mm.maxHeight;
                    clipped = true;
                } 

                //transform desired size to layout slot space 
                if (ltd != null) 
                {
                    Rect childBoundsTransformed = Rect.Transform(new Rect(0, 0, desiredSize.Width, desiredSize.Height), ltd.Transform.Value); 
                    desiredSize.Width = childBoundsTransformed.Width;
                    desiredSize.Height = childBoundsTransformed.Height;
                }
 
                //  because of negative margins, clipped desired size may be negative.
                //  need to keep it as doubles for that reason and maximize with 0 at the 
                //  very last point - before returning desired size to the parent. 
                double clippedDesiredWidth = desiredSize.Width + marginWidth;
                double clippedDesiredHeight = desiredSize.Height + marginHeight; 

                // In overconstrained scenario, parent wins and measured size of the child,
                // including any sizes set or computed, can not be larger then
                // available size. We will clip the guy later. 
                if (clippedDesiredWidth > availableSize.Width)
                { 
                    clippedDesiredWidth = availableSize.Width; 
                    clipped = true;
                } 

                if (clippedDesiredHeight > availableSize.Height)
                {
                    clippedDesiredHeight = availableSize.Height; 
                    clipped = true;
                } 
 
                // Set transformed, unrounded size on layout transform, if any.
                if (ltd != null) 
                {
                    ltd.TransformedUnroundedDS = new Size(Math.Max(0, clippedDesiredWidth), Math.Max(0, clippedDesiredHeight));
                }
 
                // If using layout rounding, round desired size.
                if (useLayoutRounding) 
                { 
                    clippedDesiredWidth = UIElement.RoundLayoutValue(clippedDesiredWidth, DpiScaleX);
                    clippedDesiredHeight = UIElement.RoundLayoutValue(clippedDesiredHeight, DpiScaleY); 
                }

                //  Note: unclippedDesiredSize is needed in ArrangeCore,
                //  because due to the layout protocol, arrange should be called 
                //  with constraints greater or equal to child's desired size
                //  returned from MeasureOverride. But in most circumstances 
                //  it is possible to reconstruct original unclipped desired size. 
                //  In such cases we want to optimize space and save 16 bytes by
                //  not storing it on each FrameworkElement. 
                //
                //  The if statement conditions below lists the cases when
                //  it is NOT possible to recalculate unclipped desired size later
                //  in ArrangeCore, thus we save it into Uncommon Fields... 
                //
                //  Note 2: use SizeBox to avoid CLR boxing of Size. 
                //  measurements show it is better to allocate an object once than 
                //  have spurious boxing allocations on every resize
                SizeBox sb = UnclippedDesiredSizeField.GetValue(this); 
                if (clipped
                    || clippedDesiredWidth < 0
                    || clippedDesiredHeight < 0)
                { 
                    if (sb == null) //not yet allocated, allocate the box
                    { 
                        sb = new SizeBox(unclippedDesiredSize); 
                        UnclippedDesiredSizeField.SetValue(this, sb);
                    } 
                    else //we already have allocated size box, simply change it
                    {
                        sb.Width = unclippedDesiredSize.Width;
                        sb.Height = unclippedDesiredSize.Height; 
                    }
                } 
                else 
                {
                    if (sb != null) 
                        UnclippedDesiredSizeField.ClearValue(this);
                }

                return new Size(Math.Max(0, clippedDesiredWidth), Math.Max(0, clippedDesiredHeight)); 
            }
        } 
Ejemplo n.º 2
0
 protected override sealed Size MeasureCore(Size availableSize)
 {
     bool useLayoutRounding = this.UseLayoutRounding;
       if (useLayoutRounding && !this.CheckFlagsAnd(VisualFlags.UseLayoutRounding))
     this.SetFlags(true, VisualFlags.UseLayoutRounding);
       this.ApplyTemplate();
       if (this.BypassLayoutPolicies)
     return this.MeasureOverride(availableSize);
       Thickness margin = this.Margin;
       double num1 = margin.Left + margin.Right;
       double num2 = margin.Top + margin.Bottom;
       if (useLayoutRounding && this is ScrollContentPresenter)
       {
     num1 = UIElement.RoundLayoutValue(num1, FrameworkElement.DpiScaleX);
     num2 = UIElement.RoundLayoutValue(num2, FrameworkElement.DpiScaleY);
       }
       Size size1 = new Size(Math.Max(availableSize.Width - num1, 0.0), Math.Max(availableSize.Height - num2, 0.0));
       FrameworkElement.MinMax minMax = new FrameworkElement.MinMax(this);
       FrameworkElement.LayoutTransformData layoutTransformData = FrameworkElement.LayoutTransformDataField.GetValue((DependencyObject) this);
       Transform layoutTransform = this.LayoutTransform;
       if (layoutTransform != null && !layoutTransform.IsIdentity)
       {
     if (layoutTransformData == null)
     {
       layoutTransformData = new FrameworkElement.LayoutTransformData();
       FrameworkElement.LayoutTransformDataField.SetValue((DependencyObject) this, layoutTransformData);
     }
     layoutTransformData.CreateTransformSnapshot(layoutTransform);
     layoutTransformData.UntransformedDS = new Size();
     if (useLayoutRounding)
       layoutTransformData.TransformedUnroundedDS = new Size();
       }
       else if (layoutTransformData != null)
       {
     layoutTransformData = (FrameworkElement.LayoutTransformData) null;
     FrameworkElement.LayoutTransformDataField.ClearValue((DependencyObject) this);
       }
       if (layoutTransformData != null)
     size1 = this.FindMaximalAreaLocalSpaceRect(layoutTransformData.Transform, size1);
       size1.Width = Math.Max(minMax.minWidth, Math.Min(size1.Width, minMax.maxWidth));
       size1.Height = Math.Max(minMax.minHeight, Math.Min(size1.Height, minMax.maxHeight));
       if (useLayoutRounding)
     size1 = UIElement.RoundLayoutSize(size1, FrameworkElement.DpiScaleX, FrameworkElement.DpiScaleY);
       Size size2 = this.MeasureOverride(size1);
       size2 = new Size(Math.Max(size2.Width, minMax.minWidth), Math.Max(size2.Height, minMax.minHeight));
       Size size3 = size2;
       if (layoutTransformData != null)
       {
     layoutTransformData.UntransformedDS = size3;
     Rect rect = Rect.Transform(new Rect(0.0, 0.0, size3.Width, size3.Height), layoutTransformData.Transform.Value);
     size3.Width = rect.Width;
     size3.Height = rect.Height;
       }
       bool flag = false;
       if (size2.Width > minMax.maxWidth)
       {
     size2.Width = minMax.maxWidth;
     flag = true;
       }
       if (size2.Height > minMax.maxHeight)
       {
     size2.Height = minMax.maxHeight;
     flag = true;
       }
       if (layoutTransformData != null)
       {
     Rect rect = Rect.Transform(new Rect(0.0, 0.0, size2.Width, size2.Height), layoutTransformData.Transform.Value);
     size2.Width = rect.Width;
     size2.Height = rect.Height;
       }
       double val2_1 = size2.Width + num1;
       double val2_2 = size2.Height + num2;
       if (val2_1 > availableSize.Width)
       {
     val2_1 = availableSize.Width;
     flag = true;
       }
       if (val2_2 > availableSize.Height)
       {
     val2_2 = availableSize.Height;
     flag = true;
       }
       if (layoutTransformData != null)
     layoutTransformData.TransformedUnroundedDS = new Size(Math.Max(0.0, val2_1), Math.Max(0.0, val2_2));
       if (useLayoutRounding)
       {
     val2_1 = UIElement.RoundLayoutValue(val2_1, FrameworkElement.DpiScaleX);
     val2_2 = UIElement.RoundLayoutValue(val2_2, FrameworkElement.DpiScaleY);
       }
       SizeBox sizeBox1 = FrameworkElement.UnclippedDesiredSizeField.GetValue((DependencyObject) this);
       if (flag || val2_1 < 0.0 || val2_2 < 0.0)
       {
     if (sizeBox1 == null)
     {
       SizeBox sizeBox2 = new SizeBox(size3);
       FrameworkElement.UnclippedDesiredSizeField.SetValue((DependencyObject) this, sizeBox2);
     }
     else
     {
       sizeBox1.Width = size3.Width;
       sizeBox1.Height = size3.Height;
     }
       }
       else if (sizeBox1 != null)
     FrameworkElement.UnclippedDesiredSizeField.ClearValue((DependencyObject) this);
       return new Size(Math.Max(0.0, val2_1), Math.Max(0.0, val2_2));
 }