A collapsed node contributes its own row and nothing beneath it, which is what collapsing is;
its children keep whatever expansion state they had, so expanding a branch again shows what was
showing before rather than a flattened one.
Cheap enough to call every frame, and it allocates nothing once the deepest tree it has seen
has been seen.
The refusal is SceneNode's and is not re-implemented here, which was checked rather than
assumed: attachChild already rejects a node as its own child and any ancestor as its own
descendant. What this adds is answering rather than throwing, because the caller is a drag in a
frame and an exception there takes down the frame somebody is dragging in.