protected virtual bool ValidateFullBounds() {
// 1. Only compute new bounds if invalid flags are set.
if (FullBoundsInvalid || ChildBoundsInvalid || BoundsVolatile || ChildBoundsVolatile) {
// 2. If my bounds are volatile and they have not been changed then signal a change.
// For most cases this will do nothing, but if a node's bounds depend on its model,
// then validate bounds has the responsibility of making the bounds match the model's
// value. For example PPaths ValidateBounds method makes sure that the bounds are
// equal to the bounds of the GraphicsPath model.
if (BoundsVolatile && !BoundsModified) {
SignalBoundsChanged();
}
// 3. If the bounds of one of my decendents are invalid then validate the bounds of all
// of my children.
if (ChildBoundsInvalid || ChildBoundsVolatile) {
ChildBoundsVolatile = false;
int count = ChildrenCount;
for (int i = 0; i < count; i++) {
ChildBoundsVolatile |= children[i].ValidateFullBounds();
}
}
// 4. Now that my children’s bounds are valid and my own bounds are valid run any
// layout algorithm here. Note that if you try to layout volatile children piccolo
// will most likely start a "soft" infinite loop. It won't freeze your program, but
// it will make an infinite number of calls to BeginInvoke later. You don't
// want to do that.
LayoutChildren();
// 5. If the full bounds cache is invalid then recompute the full bounds cache
// here after our own bounds and the children’s bounds have been computed above.
if (FullBoundsInvalid) {
RectangleF oldRect = fullBoundsCache;
bool oldEmpty = fullBoundsCache.IsEmpty;
// 6. This will call FullBounds on all of the children. So if the above
// layoutChildren method changed the bounds of any of the children they will be
// validated again here.
fullBoundsCache = ComputeFullBounds();
bool fullBoundsChanged =
!RectangleF.Equals(oldRect, fullBoundsCache) ||
oldEmpty != fullBoundsCache.IsEmpty;
// 7. If the new full bounds cache differs from the previous cache then
// tell our parent to invalidate their full bounds. This is how bounds changes
// deep in the tree percolate up.
if (fullBoundsChanged) {
if (parent != null) {
parent.InvalidateFullBounds();
}
FirePropertyChangedEvent(PROPERTY_KEY_FULLBOUNDS, PROPERTY_CODE_FULLBOUNDS, null, fullBoundsCache);
// 8. If our paint was invalid make sure to repaint our old full bounds. The
// new bounds will be computed later in the ValidatePaint pass.
if (PaintInvalid && !oldEmpty) {
RepaintFrom(oldRect, this);
}
}
}
// 9. Clear the invalid bounds flags.
BoundsModified = false;
FullBoundsInvalid = false;
ChildBoundsInvalid = false;
}
return BoundsVolatile || childBoundsVolatile;
}