|
@@ -662,31 +662,64 @@ namespace Avalonia.Controls
|
|
|
{
|
|
{
|
|
|
DefinitionBase definitionBase = _registry[i];
|
|
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;
|
|
_minSize = sharedMinSize;
|