private HashMap<Component,Component> copyComponents(Collection<Component> components) {
// determine translation offset where we can legally place the clipboard
int dx;
int dy;
Bounds bds = computeBounds(components);
for (int index = 0; ; index++) {
// compute offset to try: We try points along successively larger
// squares radiating outward from 0,0
if (index == 0) {
dx = 0;
dy = 0;
} else {
int side = 1;
while (side * side <= index) side += 2;
int offs = index - (side - 2) * (side - 2);
dx = side / 2;
dy = side / 2;
if (offs < side - 1) { // top edge of square
dx -= offs;
} else if (offs < 2 * (side - 1)) { // left edge
offs -= side - 1;
dx = -dx;
dy -= offs;
} else if (offs < 3 * (side - 1)) { // right edge
offs -= 2 * (side - 1);
dx = -dx + offs;
dy = -dy;
} else {
offs -= 3 * (side - 1);
dy = -dy + offs;
}
dx *= 10;
dy *= 10;
}
if (bds.getX() + dx >= 0 && bds.getY() + dy >= 0
&& !hasConflictTranslated(components, dx, dy, true)) {
return copyComponents(components, dx, dy);
}
}
}