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);
      }
    }
  }