Set<Location> usedLocs = new HashSet<Location>();
List<Instance> sameWay = new ArrayList<Instance>();
Direction facing = pin.getAttributeValue(StdAttr.FACING);
for (Map.Entry<Instance, AppearancePort> entry : others.entrySet()) {
Instance pin2 = entry.getKey();
Location loc = entry.getValue().getLocation();
usedLocs.add(loc);
if (pin2.getAttributeValue(StdAttr.FACING) == facing) {
sameWay.add(pin2);
}
}
// if at least one faces the same way, place pin relative to that
if (sameWay.size() > 0) {
sameWay.add(pin);
DefaultAppearance.sortPinList(sameWay, facing);
boolean isFirst = false;
Instance neighbor = null; // (preferably previous in map)
for (Instance p : sameWay) {
if (p == pin) {
break;
} else {
neighbor = p;
}
}
if (neighbor == null) { // pin must have been first in list
neighbor = sameWay.get(1);
}
int dx;
int dy;
if (facing == Direction.EAST || facing == Direction.WEST) {
dx = 0;
dy = isFirst? -10 : 10;
} else {
dx = isFirst ? -10 : 10;
dy = 0;
}
Location loc = others.get(neighbor).getLocation();
do {
loc = loc.translate(dx, dy);
} while (usedLocs.contains(loc));
if (loc.getX() >= 0 && loc.getY() >= 0) {
return loc;
}
do {
loc = loc.translate(-dx, -dy);
} while (usedLocs.contains(loc));
return loc;
}
// otherwise place it on the boundary of the bounding rectangle
Bounds bds = appear.getAbsoluteBounds();
int x;
int y;
int dx = 0;
int dy = 0;
if (facing == Direction.EAST) { // on west side by default
x = bds.getX() - 7;
y = bds.getY() + 5;
dy = 10;
} else if (facing == Direction.WEST) { // on east side by default
x = bds.getX() + bds.getWidth() - 3;
y = bds.getY() + 5;
dy = 10;
} else if (facing == Direction.SOUTH) { // on north side by default
x = bds.getX() + 5;
y = bds.getY() - 7;
dx = 10;
} else { // on south side by default
x = bds.getX() + 5;
y = bds.getY() + bds.getHeight() - 3;
dx = 10;
}
x = (x + 9) / 10 * 10; // round coordinates up to ensure they're on grid
y = (y + 9) / 10 * 10;
Location loc = Location.create(x, y);
while (usedLocs.contains(loc)) {
loc = loc.translate(dx, dy);
}
return loc;
}