gfx/movement_watcher.h
ComponentMovementWatcher: told when a component moves on screen -- because it moved, or because ANY of its parents did -- when it is resized, when it might have been shown or hidden, and when the window it is in appears or goes.
#include <sonore/gfx/movement_watcher.h>- 1type
- Guides: The native editor
On this page
Design notes
Why the component's own listener is not enough
ComponentListener::componentMovedOrResized fires when a component's bounds change, and bounds are relative to the parent. A knob inside a panel that slides in from the side has not moved at all by that measure, and is nevertheless somewhere else on the screen. Anything tracking a component's place in the WINDOW -- a native child view laid over it, a tooltip or popup anchored to it, an accessibility rectangle, an overlay drawn in another tree -- needs to hear about every ancestor's move too, and has to re-attach itself whenever the chain of ancestors changes. That bookkeeping is this class.
What counts as a move
The component's top-left in its ROOT's coordinates, compared with the last time one was reported; its size likewise. So a parent resized without moving the child reports nothing, a parent moved reports wasMoved, and a re-parenting that happens to leave it at the same place reports nothing -- what the watcher's users care about is where it IS, not what happened.
"Peer" here is the window's MouseRouter: what puts a tree in a window. componentPeerChanged fires when routerFor(component) changes -- the tree was put in a window, taken out of one, or the component moved between trees.
Types 1
class ComponentMovementWatcher : private ComponentListener
Watches one component's place on screen, through every ancestor -- the reference's ComponentMovementWatcher. The file comment says what counts as a move and what "peer" means here.
Derive and override the three protected functions, or set the matching onMovedOrResized / onPeerChanged / onVisibilityChanged. It does not own the component, and survives it: getComponent() turns null when the component is destroyed, and the watcher can be destroyed at any time after. The notifications arrive inside the setBounds, addChild or setVisible call that caused them -- message thread only.