Node drag snapping

This is achieved by calculating offsets which cause snapping once in dragEnter(), and then snapping to them where possible in dragMove(). The offsets are stored as a sorted vector in each axis so that the closest snap point can be found quickly. Nodes snap to their inputs and outputs such that nodes are centered, connections are horizontal/vertical and nodes butt up nicely to each other.