GENERIC MODULE TypeSelector(Type); IMPORT MG, MGV, R2, R2Box, VBT; TYPE SelectorIter = MG.GroupIterator OBJECT closest: MG.T := NIL; dist : REAL := 999999999.0; pos: R2.T; OVERRIDES proc := SelectorProc; END; PROCEDURE Closest (<* UNUSED *> s : MGV.Selector; v : MGV.V; READONLY pos: R2.T; <* UNUSED *> READONLY cd : VBT.MouseRec): MG.T = VAR iter := NEW(SelectorIter, v := v, pos := pos); BEGIN EVAL v.displayList.iterate(iter, TRUE, FALSE); RETURN iter.closest; END Closest; PROCEDURE SelectorProc (iter: SelectorIter; t: MG.T): BOOLEAN = VAR dx, dy, dist: REAL; pos := iter.pos; bounds: R2Box.T; BEGIN TYPECASE t OF | Type.T => bounds := t.appearance.boundingBox(t, iter.v); IF pos[0] < bounds[0].lo THEN dx := bounds[0].lo - pos[0] ELSIF pos[0] > bounds[0].hi THEN dx := pos[0] - bounds[0].hi ELSE dx := 0.0; END; IF pos[1] < bounds[1].lo THEN dy := bounds[1].lo - pos[1] ELSIF pos[1] > bounds[1].hi THEN dy := pos[1] - bounds[1].hi ELSE dy := 0.0; END; IF dx = 0.0 AND dy = 0.00 THEN iter.closest := t; iter.dist := 0.0; RETURN FALSE ELSE dist := dx * dx + dy * dy; IF dist < iter.dist THEN iter.closest := t; iter.dist := dist; END; RETURN TRUE; END; ELSE RETURN TRUE END; END SelectorProc; BEGIN closest := NEW(MGV.Selector, select := Closest); END TypeSelector.