package org.archstudio.utils.bna.dot; import java.awt.geom.Point2D; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import org.archstudio.bna.IBNAWorld; import org.archstudio.bna.IThing; import org.archstudio.bna.facets.IHasAnchorPoint; import org.archstudio.bna.facets.IHasBoundingBox; import org.archstudio.bna.facets.IHasMutableReferencePoint; import org.archstudio.bna.facets.IHasReferencePoint; import org.archstudio.bna.keys.IThingKey; import org.archstudio.bna.keys.ThingKey; import org.archstudio.bna.logics.tracking.ThingValueTrackingLogic; import org.archstudio.bna.utils.Assemblies; import org.archstudio.bna.utils.GridUtils; import org.archstudio.bna.utils.UserEditableUtils; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.base.Preconditions; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; public class Node { public static final DecimalFormat SIMPLE_DECIMAL_FORMATTER; static { SIMPLE_DECIMAL_FORMATTER = new DecimalFormat("0", DecimalFormatSymbols.getInstance(Locale.ENGLISH)); // 340 = DecimalFormat.DOUBLE_FRACTION_DIGITS SIMPLE_DECIMAL_FORMATTER.setMaximumFractionDigits(340); } private static long idCounter = 0; private static final IThingKey<String> UID_KEY = ThingKey.create(Lists.newArrayList("uid", Endpoint.class)); public static final String getUniqueId(IThing thing) { String uid = thing.get(UID_KEY); if (uid == null) { thing.set(UID_KEY, uid = "uid_" + ++idCounter); } return uid; } public static final IThing getThingFromUniqueId(IBNAWorld world, String uid) { ThingValueTrackingLogic valueLogic = world.getThingLogicManager().getThingLogic(ThingValueTrackingLogic.class); for (IThing thing : valueLogic.getThings(UID_KEY, uid)) { return thing; } return null; } public static Map<String, Node> scanForNodes(IBNAWorld world, Iterable<? extends IThing> things, double scale) { final Map<String, Node> nodes = new HashMap<>(); for (IThing t : things) { if (UserEditableUtils.isEditableForAnyQualities(t, IHasMutableReferencePoint.USER_MAY_MOVE)) { IThing base = Assemblies.getRoot(world.getBNAModel(), t); String uid = getUniqueId(base); Node node = new Node(base, world); node.setScale(scale); nodes.put(uid, node); } } return nodes; } private final IThing thing; private final IBNAWorld world; private double scale = 1d; public Node(IThing thing, IBNAWorld world) { this.thing = Preconditions.checkNotNull(thing); this.world = Preconditions.checkNotNull(world); } public IThing getThing() { return thing; } public double getScale() { return scale; } public void setScale(double scale) { this.scale = scale; } public String toDotNode() { StringBuilder sb = new StringBuilder(); Map<String, String> attributes = new HashMap<>(); attributes.put("label", "\"\""); if (thing instanceof IHasBoundingBox) { Rectangle r = ((IHasBoundingBox) thing).getBoundingBox(); if (r.height == 0 || r.width == 0) { return ""; } attributes.put("shape", "box"); attributes.put("fixedsize", "true"); attributes.put("height", "" + SIMPLE_DECIMAL_FORMATTER .format((r.height + 2 * GridUtils.getGridSpacing(world)) * scale)); attributes.put("width", "" + SIMPLE_DECIMAL_FORMATTER .format((r.width + 2 * GridUtils.getGridSpacing(world)) * scale)); attributes.put("pos", "\"" + SIMPLE_DECIMAL_FORMATTER.format((r.x + r.width / 2d) * scale) + "," + SIMPLE_DECIMAL_FORMATTER.format((r.y + r.height / 2d) * scale) + "\""); } else if (thing instanceof IHasAnchorPoint) { Point2D p = ((IHasAnchorPoint) thing).getAnchorPoint(); attributes.put("pos", "\"" + SIMPLE_DECIMAL_FORMATTER.format(p.getX() * scale) + "," + SIMPLE_DECIMAL_FORMATTER.format(p.getY() * scale) + "\""); } else if (thing instanceof IHasReferencePoint) { Point p = ((IHasReferencePoint) thing).getReferencePoint(); attributes.put("pos", "\"" + SIMPLE_DECIMAL_FORMATTER.format(p.x * scale) + "," + SIMPLE_DECIMAL_FORMATTER.format(p.y * scale) + "\""); } if (thing instanceof IHasBoundingBox) { sb.append(getUniqueId(thing)); if (!attributes.isEmpty()) { sb.append(" ["); sb.append(Joiner.on(", ").join(Iterables.transform(attributes.entrySet(), new Function<Map.Entry<String, String>, String>() { @Override public String apply(Entry<String, String> input) { return "" + input.getKey() + "=" + input.getValue(); } }))); sb.append("]"); } sb.append(";\n"); } return sb.toString(); } }