diff --git a/src/main/java/de/neemann/digital/draw/builder/Builder.java b/src/main/java/de/neemann/digital/draw/builder/Builder.java index 8d869f3a7..de3df0dad 100644 --- a/src/main/java/de/neemann/digital/draw/builder/Builder.java +++ b/src/main/java/de/neemann/digital/draw/builder/Builder.java @@ -4,8 +4,12 @@ import de.neemann.digital.analyse.expression.*; import de.neemann.digital.core.basic.And; import de.neemann.digital.core.basic.Or; import de.neemann.digital.core.element.Keys; +import de.neemann.digital.core.element.Rotation; +import de.neemann.digital.core.io.In; import de.neemann.digital.core.io.Out; import de.neemann.digital.draw.elements.Circuit; +import de.neemann.digital.draw.elements.VisualElement; +import de.neemann.digital.draw.elements.Wire; import de.neemann.digital.draw.graphics.Vector; import de.neemann.digital.draw.library.ElementLibrary; import de.neemann.digital.draw.shapes.ShapeFactory; @@ -13,10 +17,13 @@ import de.neemann.digital.gui.Main; import javax.swing.*; import java.util.ArrayList; +import java.util.HashMap; import static de.neemann.digital.draw.shapes.GenericShape.SIZE; /** + * Builder to create a circuit from an expression + * * @author hneemann */ public class Builder { @@ -25,14 +32,28 @@ public class Builder { private final VariableVisitor variableVisitor; private final ShapeFactory shapeFactory; private int pos; + private ArrayList fragmentVariables; + /** + * Creates a new builder + * + * @param shapeFactory ShapeFactory used ti set to the created VisualElements + */ public Builder(ShapeFactory shapeFactory) { this.shapeFactory = shapeFactory; circuit = new Circuit(); variableVisitor = new VariableVisitor(); + fragmentVariables = new ArrayList<>(); } - public Builder addCircuit(String name, Expression expression) { + /** + * Adds an expression to the circuit + * + * @param name the output name + * @param expression the expression + * @return this for chained calls + */ + public Builder addExpression(String name, Expression expression) { Fragment fr = createFragment(expression); fr = new FragmentExpression(fr, new FragmentVisualElement(Out.DESCRIPTION, shapeFactory).setAttr(Keys.LABEL, name)); @@ -63,17 +84,66 @@ public class Builder { throw new RuntimeException("nyi"); } else if (expression instanceof Not) { Not n = (Not) expression; - return new FragmentExpression(createFragment(n.getExpression()), new FragmentVisualElement(de.neemann.digital.core.basic.Not.DESCRIPTION, shapeFactory)); + if (n.getExpression() instanceof Variable) { + FragmentVariable fragmentVariable = new FragmentVariable((Variable) n.getExpression(), true); + fragmentVariables.add(fragmentVariable); + return fragmentVariable; + } else + return new FragmentExpression(createFragment(n.getExpression()), new FragmentVisualElement(de.neemann.digital.core.basic.Not.DESCRIPTION, shapeFactory)); } else if (expression instanceof Variable) { - return new FragmentVariable(((Variable) expression)); + FragmentVariable fragmentVariable = new FragmentVariable((Variable) expression, false); + fragmentVariables.add(fragmentVariable); + return fragmentVariable; } else throw new RuntimeException("nyi"); } - public Circuit getCircuit() { + private void createInputBus() { + HashMap varPos = new HashMap<>(); + int dx = -variableVisitor.getVariables().size() * SIZE * 2; + for (Variable v : variableVisitor.getVariables()) { + VisualElement visualElement = new VisualElement(In.DESCRIPTION.getName()).setShapeFactory(shapeFactory); + visualElement.getElementAttributes() + .set(Keys.ROTATE, new Rotation(3)) + .set(Keys.LABEL, v.getIdentifier()); + visualElement.setPos(new Vector(dx, -SIZE * 5)); + circuit.add(visualElement); + + visualElement = new VisualElement(de.neemann.digital.core.basic.Not.DESCRIPTION.getName()).setShapeFactory(shapeFactory); + visualElement.getElementAttributes() + .set(Keys.ROTATE, new Rotation(3)); + visualElement.setPos(new Vector(dx + SIZE, -SIZE * 3)); + circuit.add(visualElement); + + circuit.add(new Wire(new Vector(dx, -SIZE * 4), new Vector(dx + SIZE, -SIZE * 4))); + circuit.add(new Wire(new Vector(dx + SIZE, -SIZE * 3), new Vector(dx + SIZE, -SIZE * 4))); + + circuit.add(new Wire(new Vector(dx, -SIZE * 5), new Vector(dx, pos))); + circuit.add(new Wire(new Vector(dx + SIZE, -SIZE), new Vector(dx + SIZE, pos))); + + varPos.put(v.getIdentifier(), dx); + dx += SIZE * 2; + } + + for (FragmentVariable f : fragmentVariables) { + Vector p = f.getCircuitPos(); + int in = varPos.get(f.getVariable().getIdentifier()); + if (f.isNeg()) in += SIZE; + circuit.add(new Wire(p, new Vector(in, p.y))); + } + } + + /** + * Creates the circuit + * + * @return the circuit + */ + public Circuit createCircuit() { + createInputBus(); return circuit; } + public static void main(String[] args) { Variable a = new Variable("A"); Variable b = new Variable("B"); @@ -86,9 +156,9 @@ public class Builder { Builder builder = new Builder(new ShapeFactory(new ElementLibrary())); Circuit circuit = builder - .addCircuit("L", l) - .addCircuit("Y", y) - .getCircuit(); + .addExpression("L", l) + .addExpression("Y", y) + .createCircuit(); SwingUtilities.invokeLater(() -> new Main(null, circuit).setVisible(true)); } diff --git a/src/main/java/de/neemann/digital/draw/builder/FragmentExpression.java b/src/main/java/de/neemann/digital/draw/builder/FragmentExpression.java index 346992044..174b0c7e1 100644 --- a/src/main/java/de/neemann/digital/draw/builder/FragmentExpression.java +++ b/src/main/java/de/neemann/digital/draw/builder/FragmentExpression.java @@ -38,18 +38,12 @@ public class FragmentExpression implements Fragment { @Override public Box doLayout() { - int centerHeight = 0; int height = 0; int width = 0; - int centerIndex = fragments.size() / 2; - for (int i = 0; i < fragments.size(); i++) { - FragmentHolder fr = fragments.get(i); + for (FragmentHolder fr : fragments) { fr.fragment.setPos(new Vector(0, height)); fr.box = fr.fragment.doLayout(); - if (i == centerIndex) - centerHeight = height; - height += fr.box.getHeight(); int w = fr.box.getWidth(); if (w > width) @@ -74,6 +68,7 @@ public class FragmentExpression implements Fragment { merger.setPos(new Vector(width, raster((height - mergerBox.getHeight()) / 2))); } else { // odd number of inputs + int centerIndex = fragments.size() / 2; int y = fragments.get(centerIndex).fragment.getOutputs().get(0).y - centerIndex * SIZE; merger.setPos(new Vector(width, y)); } @@ -138,7 +133,7 @@ public class FragmentExpression implements Fragment { return Vector.add(merger.getOutputs(), pos); } - public boolean isLong() { + private boolean isLong() { return fragments.size() > 1; } diff --git a/src/main/java/de/neemann/digital/draw/builder/FragmentVariable.java b/src/main/java/de/neemann/digital/draw/builder/FragmentVariable.java index d35342721..c15d50c73 100644 --- a/src/main/java/de/neemann/digital/draw/builder/FragmentVariable.java +++ b/src/main/java/de/neemann/digital/draw/builder/FragmentVariable.java @@ -12,10 +12,13 @@ import java.util.List; */ public class FragmentVariable implements Fragment { private final Variable variable; + private final boolean neg; private Vector pos; + private Vector circuitPos; - public FragmentVariable(Variable variable) { + public FragmentVariable(Variable variable, boolean neg) { this.variable = variable; + this.neg = neg; } @Override @@ -30,6 +33,15 @@ public class FragmentVariable implements Fragment { @Override public void addToCircuit(Vector pos, Circuit circuit) { + circuitPos = pos.add(this.pos); + } + + public Vector getCircuitPos() { + return circuitPos; + } + + public boolean isNeg() { + return neg; } @Override @@ -43,4 +55,8 @@ public class FragmentVariable implements Fragment { o.add(pos); return o; } + + public Variable getVariable() { + return variable; + } }