package de.ph87.electro.circuit.part; import de.ph87.electro.circuit.part.node.Node; import de.ph87.electro.circuit.part.node.NodeDto; import de.ph87.electro.circuit.part.parts.*; import lombok.Getter; import lombok.NonNull; import lombok.Setter; import lombok.ToString; import java.awt.*; import java.awt.geom.AffineTransform; import java.awt.geom.Point2D; import java.util.List; import java.util.*; import static de.ph87.electro.CONFIG.P50; import static de.ph87.electro.CONFIG.PART_BACK_COLOR; import static java.lang.Math.round; @Getter @ToString(onlyExplicitlyIncluded = true) public abstract class Part { @NonNull @ToString.Include private final String uuid; @NonNull private final List nodes = new ArrayList<>(); @NonNull protected Orientation orientation = Orientation.R0; @NonNull @Setter @ToString.Include private String name; @NonNull private Point position; @NonNull private AffineTransform transform = new AffineTransform(); protected Part(@NonNull final String name, @NonNull final Point position) { this.uuid = UUID.randomUUID().toString(); this.name = name; this.position = position; updateTransform(); } protected Part(@NonNull final PartDto dto) { this.uuid = dto.getUuid(); this.name = dto.getName(); this.orientation = dto.getOrientation(); this.position = dto.getPosition(); updateTransform(); } @NonNull public static Part fromDto(@NonNull final PartDto abstractDto) { return switch (abstractDto) { case final BatteryDto dto -> new Battery(dto); case final LightDto dto -> new Light(dto); case final ConnectorSubDto dto -> new ConnectorSub(dto); case final Switch1x1Dto dto -> new Switch1x1(dto); case final Switch1x2Dto dto -> new Switch1x2(dto); case final SwitchCrossDto dto -> new SwitchCross(dto); case final PotiDto dto -> new Poti(dto); case final VoltmeterDto dto -> new Voltmeter(dto); case null, default -> throw new RuntimeException(); }; } @NonNull public abstract Point getSize(); public void setPosition(@NonNull final Point position) { this.position = position; updateTransform(); } public void rotate() { this.orientation = orientation.clockwise(); updateTransform(); } @NonNull private void updateTransform() { transform = new AffineTransform(); transform.translate(position.x, position.y); transform.rotate(orientation.getRadians(), P50, P50); nodes.forEach(Node::positionChanged); } @NonNull public Point transform(@NonNull final Point point) { final Point2D result = transform.transform(point, new Point2D.Double()); return new Point((int) round(result.getX()), (int) round(result.getY())); } @NonNull protected Node addNode(@NonNull final String name, final int x, final int y) { return addNode(new Node(this, name, new Point(x, y))); } @NonNull protected Node addNode(@NonNull final NodeDto dto, final int x, final int y) { return addNode(new Node(this, dto, new Point(x, y))); } @NonNull private Node addNode(@NonNull final Node node) { nodes.add(node); return node; } public final void draw(@NonNull final Graphics2D g) { g.setColor(PART_BACK_COLOR); g.fillRect(0, 0, getSize().x, getSize().y); _render(g); nodes.forEach(node -> node.draw(g)); _labels(g); } protected void _render(@NonNull final Graphics2D g) { // - } protected void _labels(@NonNull final Graphics2D g) { // - } public void action() { // - } public void postCalculate() { // - } @NonNull public List getInnerConnections() { return Collections.emptyList(); } @NonNull public Optional findNodeByUuid(@NonNull final String nodeUuid) { return nodes.stream().filter(node -> node.getUuid().equals(nodeUuid)).findFirst(); } @NonNull public Optional findNodeByPosition(@NonNull final Point position) { return nodes.stream().filter(node -> node.intersects(position)).findFirst(); } public boolean intersects(@NonNull final Point point) { return this.position.x <= point.x && point.x < this.position.x + this.getSize().x && this.position.y <= point.y && point.y < this.position.y + this.getSize().y; } }