Added a layout shape, which allows pins also at the bottom and the top.

This commit is contained in:
hneemann 2018-07-29 14:49:31 +02:00
parent 43a31a84af
commit 39d57f6f92
5 changed files with 230 additions and 5 deletions

View File

@ -10,10 +10,15 @@ package de.neemann.digital.draw.shapes;
*/
public enum CustomCircuitShapeType {
/**
* The default shape. inputs at the left, outputs at the right
* Uses the shape specified in the circuit itself
*/
DEFAULT,
/**
* The default shape. inputs at the left, outputs at the right
*/
SIMPLE,
/**
* A DIL shape
*/

View File

@ -0,0 +1,215 @@
/*
* Copyright (c) 2018 Helmut Neemann.
* Use of this source code is governed by the GPL v3 license
* that can be found in the LICENSE file.
*/
package de.neemann.digital.draw.shapes;
import de.neemann.digital.core.NodeException;
import de.neemann.digital.core.Observer;
import de.neemann.digital.core.element.ElementAttributes;
import de.neemann.digital.core.element.Keys;
import de.neemann.digital.core.element.PinDescription;
import de.neemann.digital.core.io.In;
import de.neemann.digital.core.io.Out;
import de.neemann.digital.core.wiring.Clock;
import de.neemann.digital.draw.elements.*;
import de.neemann.digital.draw.graphics.*;
import de.neemann.digital.draw.graphics.Polygon;
import de.neemann.digital.draw.library.ElementLibrary;
import de.neemann.digital.lang.Lang;
import java.awt.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import static de.neemann.digital.draw.shapes.GenericShape.SIZE;
/**
* The layout shape.
* The pins are ordered in the same way they are placed inside the circuit.
* Thus the shape feels like a minimized version of the contained circuit in respect to pin ordering.
*/
public class LayoutShape implements Shape {
private final int width;
private final int height;
private final Pins pins;
private final Color color;
private final String name;
private final String label;
private final PinList left;
private final PinList right;
private final PinList top;
private final PinList bottom;
/**
* Creates a new instance
*
* @param custom the type description
* @param elementAttributes the local attributes
* @throws NodeException NodeException
* @throws PinException PinException
*/
public LayoutShape(ElementLibrary.ElementTypeDescriptionCustom custom, ElementAttributes elementAttributes) throws NodeException, PinException {
left = new PinList(false);
right = new PinList(false);
top = new PinList(true);
bottom = new PinList(true);
for (VisualElement ve : custom.getCircuit().getElements()) {
if (ve.equalsDescription(In.DESCRIPTION) || ve.equalsDescription(Clock.DESCRIPTION)) {
switch (ve.getRotate()) {
case 0:
left.add(ve);
break;
case 1:
bottom.add(ve);
break;
case 2:
right.add(ve);
break;
default:
top.add(ve);
break;
}
}
if (ve.equalsDescription(Out.DESCRIPTION)) {
switch (ve.getRotate()) {
case 0:
right.add(ve);
break;
case 1:
top.add(ve);
break;
case 2:
left.add(ve);
break;
default:
bottom.add(ve);
break;
}
}
}
height = Math.max(right.size(), left.size()) + 1;
final int w = Math.max(top.size(), bottom.size()) + 1;
width = Math.max(w, custom.getAttributes().get(Keys.WIDTH));
HashMap<String, PinPos> map = new HashMap<>();
top.createPosition(map, new Vector(((width - top.size()) / 2 + 1) * SIZE, 0));
bottom.createPosition(map, new Vector(((width - bottom.size()) / 2 + 1) * SIZE, SIZE * height));
left.createPosition(map, new Vector(0, SIZE));
right.createPosition(map, new Vector(SIZE * width, SIZE));
pins = new Pins();
for (PinDescription p : custom.getInputDescription(elementAttributes))
pins.add(createPin(map, p));
for (PinDescription p : custom.getOutputDescriptions(elementAttributes))
pins.add(createPin(map, p));
color = custom.getCircuit().getAttributes().get(Keys.BACKGROUND_COLOR);
label = elementAttributes.getCleanLabel();
name = custom.getShortName();
}
private Pin createPin(HashMap<String, PinPos> map, PinDescription p) throws PinException {
PinPos pinPos = map.get(p.getName());
if (pinPos == null)
throw new PinException(Lang.get("err_pin_N_notFound", p.getName()));
return new Pin(pinPos.pos, p);
}
@Override
public Pins getPins() {
return pins;
}
@Override
public InteractorInterface applyStateMonitor(IOState ioState, Observer guiObserver) {
return null;
}
@Override
public void drawTo(Graphic graphic, Style highLight) {
final Polygon poly = new Polygon(true)
.add(0, 0)
.add(width * SIZE, 0)
.add(width * SIZE, height * SIZE)
.add(0, height * SIZE);
graphic.drawPolygon(poly, Style.NORMAL.deriveFillStyle(color));
graphic.drawPolygon(poly, Style.NORMAL);
Vector center = new Vector(width * SIZE / 2, height * SIZE / 2);
Graphic.drawText(graphic, center.add(0, -2), name, Orientation.CENTERBOTTOM, Style.SHAPE_PIN);
Graphic.drawText(graphic, center.add(0, 2), label, Orientation.CENTERTOP, Style.SHAPE_PIN);
for (PinPos p : left)
Graphic.drawText(graphic, p.pos.add(4, 0), p.label, Orientation.LEFTCENTER, Style.SHAPE_PIN);
for (PinPos p : right)
Graphic.drawText(graphic, p.pos.add(-4, 0), p.label, Orientation.RIGHTCENTER, Style.SHAPE_PIN);
for (PinPos p : top)
graphic.drawText(p.pos.add(0, 4), p.pos.add(0, 3), p.label, Orientation.RIGHTCENTER, Style.SHAPE_PIN);
for (PinPos p : bottom)
graphic.drawText(p.pos.add(0, -4), p.pos.add(0, -3), p.label, Orientation.RIGHTCENTER, Style.SHAPE_PIN);
}
private final static class PinPos implements Comparable<PinPos> {
private final int orderPos;
private final String label;
private Vector pos;
private PinPos(VisualElement ve, boolean horizontal) {
if (horizontal)
orderPos = ve.getPos().x;
else
orderPos = ve.getPos().y;
label = ve.getElementAttributes().getLabel();
}
@Override
public int compareTo(PinPos pinPos) {
return orderPos - pinPos.orderPos;
}
}
private final static class PinList implements Iterable<PinPos> {
private final boolean horizontal;
private ArrayList<PinPos> pins;
private PinList(boolean horizontal) {
this.horizontal = horizontal;
pins = new ArrayList<>();
}
private void add(VisualElement ve) {
pins.add(new PinPos(ve, horizontal));
}
private int size() {
return pins.size();
}
private void createPosition(HashMap<String, PinPos> map, Vector pos) {
Collections.sort(pins);
for (PinPos pp : pins) {
map.put(pp.label, pp);
pp.pos = pos;
if (horizontal)
pos = pos.add(SIZE, 0);
else
pos = pos.add(0, SIZE);
}
}
@Override
public Iterator<PinPos> iterator() {
return pins.iterator();
}
}
}

View File

@ -183,6 +183,8 @@ public final class ShapeFactory {
pt.getOutputDescriptions(elementAttributes),
elementAttributes.getLabel(),
customDescr.getAttributes());
case LAYOUT:
return new LayoutShape(customDescr, elementAttributes);
case CUSTOM:
final CustomShapeDescription customShapeDescription = customDescr.getAttributes().get(Keys.CUSTOM_SHAPE);
if (customShapeDescription != CustomShapeDescription.EMPTY)

View File

@ -1189,9 +1189,10 @@ Sind evtl. die Namen der Variablen nicht eindeutig?</string>
<string name="key_shapeType">Form</string>
<string name="key_shapeType_tt">Die Form, welche für die Repräsentation der Schaltung in einer einbettenden
Schaltung verwendet werden soll. Bei "Layout" bestimmt die Lage der Ein- und Ausgänge in der Schaltung die
Position der Pins.</string>
<string name="key_shapeType_DEFAULT">Standard</string>
Schaltung verwendet werden soll. Bei "Layout" bestimmt die Lage und Orientierung der Ein- und Ausgänge in
der Schaltung die Position der Pins.</string>
<string name="key_shapeType_DEFAULT">Vorgabe</string>
<string name="key_shapeType_SIMPLE">Einfach</string>
<string name="key_shapeType_DIL">DIL-Gehäuse</string>
<string name="key_shapeType_LAYOUT">Layout</string>
<string name="key_shapeType_CUSTOM">Benutzerdefiniert</string>

View File

@ -1180,8 +1180,10 @@
<string name="key_shapeType">Shape</string>
<string name="key_shapeType_tt">The shape to be used for the representation of the circuit in an embedding circuit.
With "Layout", the position of the inputs and outputs in the circuit determines the position of the pins.</string>
With "Layout", the position of the inputs and outputs and and their orientation in the circuit determines
the position of the pins.</string>
<string name="key_shapeType_DEFAULT">Default</string>
<string name="key_shapeType_SIMPLE">Simple</string>
<string name="key_shapeType_DIL">DIL-Chip</string>
<string name="key_shapeType_LAYOUT">Layout</string>
<string name="key_shapeType_CUSTOM">User defined</string>