|
|
|
@ -662,31 +662,64 @@ namespace Avalonia.Controls |
|
|
|
{ |
|
|
|
DefinitionBase definitionBase = _registry[i]; |
|
|
|
|
|
|
|
if (sharedMinSizeChanged || definitionBase.LayoutWasUpdated) |
|
|
|
// 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 = !MathUtilities.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) |
|
|
|
{ |
|
|
|
// if definition's min size is different, then need to re-measure
|
|
|
|
if (!MathUtilities.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 (!MathUtilities.AreClose(sharedMinSize, definitionBase.SizeCache)) |
|
|
|
{ |
|
|
|
Grid parentGrid = (Grid)definitionBase.Parent; |
|
|
|
parentGrid.InvalidateArrange(); |
|
|
|
} |
|
|
|
} |
|
|
|
// 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 && |
|
|
|
MathUtilities.GreaterThanOrClose(definitionBase._minSize, this.MinSize)); |
|
|
|
} |
|
|
|
|
|
|
|
definitionBase.LayoutWasUpdated = false; |
|
|
|
if(!measureIsValid) |
|
|
|
{ |
|
|
|
definitionBase.Parent.InvalidateMeasure(); |
|
|
|
} |
|
|
|
else if (!MathUtilities.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
|
|
|
|
definitionBase.Parent.InvalidateArrange(); |
|
|
|
} |
|
|
|
|
|
|
|
// now we can restore the invariant, and clear the layout flag
|
|
|
|
definitionBase.UseSharedMinimum = useSharedMinimum; |
|
|
|
definitionBase.LayoutWasUpdated = false; |
|
|
|
} |
|
|
|
|
|
|
|
_minSize = sharedMinSize; |
|
|
|
|