mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-13 06:49:36 -04:00
added move and delete
This commit is contained in:
parent
1095d1c626
commit
12d5f00312
@ -38,7 +38,13 @@ public class Main extends JFrame {
|
||||
parts.add(createSimpleMenu("OR", inputs -> Or.createFactory(1, inputs)));
|
||||
parts.add(createSimpleMenu("NAND", inputs -> NAnd.createFactory(1, inputs)));
|
||||
parts.add(createSimpleMenu("NOR", inputs -> NOr.createFactory(1, inputs)));
|
||||
parts.add(new InsertAbstractAction("Not", Not.createFactory(1)));
|
||||
parts.add(new InsertAction("Not", Not.createFactory(1)));
|
||||
|
||||
JMenu edit = new JMenu("Edit");
|
||||
bar.add(edit);
|
||||
edit.add(new JMenuItem(new ModeAction("Wire", CircuitComponent.Mode.wire)));
|
||||
edit.add(new JMenuItem(new ModeAction("Parts", CircuitComponent.Mode.part)));
|
||||
edit.add(new JMenuItem(new ModeAction("Move", CircuitComponent.Mode.move)));
|
||||
|
||||
setJMenuBar(bar);
|
||||
}
|
||||
@ -50,7 +56,7 @@ public class Main extends JFrame {
|
||||
private JMenu createSimpleMenu(String name, DescriptionFactory factory) {
|
||||
JMenu m = new JMenu(name);
|
||||
for (int i = 2; i < 16; i++) {
|
||||
m.add(new JMenuItem(new InsertAbstractAction(Integer.toString(i), factory.create(i))));
|
||||
m.add(new JMenuItem(new InsertAction(Integer.toString(i), factory.create(i))));
|
||||
}
|
||||
return m;
|
||||
}
|
||||
@ -59,18 +65,33 @@ public class Main extends JFrame {
|
||||
PartDescription create(int inputs);
|
||||
}
|
||||
|
||||
private class InsertAbstractAction extends AbstractAction {
|
||||
private class InsertAction extends AbstractAction {
|
||||
private final PartDescription partDescription;
|
||||
|
||||
public InsertAbstractAction(String name, PartDescription partDescription) {
|
||||
public InsertAction(String name, PartDescription partDescription) {
|
||||
super(name);
|
||||
this.partDescription = partDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
cr.add(new VisualPart(partDescription).setPos(new Vector(10, 10)));
|
||||
VisualPart visualPart = new VisualPart(partDescription).setPos(new Vector(10, 10));
|
||||
cr.add(visualPart);
|
||||
circuitComponent.setPartToDrag(visualPart);
|
||||
}
|
||||
}
|
||||
|
||||
private class ModeAction extends AbstractAction {
|
||||
private final CircuitComponent.Mode mode;
|
||||
|
||||
public ModeAction(String name, CircuitComponent.Mode mode) {
|
||||
super(name);
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
circuitComponent.setMode(mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,30 +1,79 @@
|
||||
package de.neemann.digital.gui.components;
|
||||
|
||||
import de.neemann.digital.gui.draw.graphics.GraphicSwing;
|
||||
import de.neemann.digital.gui.draw.graphics.Vector;
|
||||
import de.neemann.digital.gui.draw.graphics.*;
|
||||
import de.neemann.digital.gui.draw.graphics.Polygon;
|
||||
import de.neemann.digital.gui.draw.parts.Circuit;
|
||||
import de.neemann.digital.gui.draw.parts.Moveable;
|
||||
import de.neemann.digital.gui.draw.parts.VisualPart;
|
||||
import de.neemann.digital.gui.draw.parts.Wire;
|
||||
import de.neemann.digital.gui.draw.shapes.GenericShape;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.awt.event.MouseMotionListener;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* @author hneemann
|
||||
*/
|
||||
public class CircuitComponent extends JComponent {
|
||||
|
||||
private static final String delAction = "myDelAction";
|
||||
private final Circuit circuit;
|
||||
|
||||
;
|
||||
private Mouse listener;
|
||||
public CircuitComponent(Circuit circuit) {
|
||||
this.circuit = circuit;
|
||||
setMode(Mode.part);
|
||||
|
||||
MyMouseMotionListener l = new MyMouseMotionListener();
|
||||
addMouseMotionListener(l);
|
||||
addMouseListener(l);
|
||||
KeyStroke delKey = KeyStroke.getKeyStroke("DELETE");
|
||||
getInputMap().put(delKey, delAction);
|
||||
getActionMap().put(delAction, new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (listener instanceof MoveMouseListener) {
|
||||
MoveMouseListener mml = (MoveMouseListener) listener;
|
||||
if (mml.corner1 != null && mml.corner2 != null) {
|
||||
circuit.delete(Vector.min(mml.corner1, mml.corner2), Vector.max(mml.corner1, mml.corner2));
|
||||
mml.reset();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public void setMode(Mode mode) {
|
||||
if (listener != null) {
|
||||
removeMouseListener(listener);
|
||||
removeMouseMotionListener(listener);
|
||||
}
|
||||
switch (mode) {
|
||||
case part:
|
||||
listener = new PartMouseListener();
|
||||
setCursor(new Cursor(Cursor.HAND_CURSOR));
|
||||
break;
|
||||
case wire:
|
||||
listener = new WireMouseListener();
|
||||
setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
|
||||
break;
|
||||
case move:
|
||||
listener = new MoveMouseListener();
|
||||
setCursor(new Cursor(Cursor.MOVE_CURSOR));
|
||||
break;
|
||||
}
|
||||
addMouseMotionListener(listener);
|
||||
addMouseListener(listener);
|
||||
repaint();
|
||||
}
|
||||
|
||||
public void setPartToDrag(VisualPart part) {
|
||||
setMode(Mode.part);
|
||||
((PartMouseListener) listener).setPartToDrag(part);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -35,6 +84,8 @@ public class CircuitComponent extends JComponent {
|
||||
|
||||
GraphicSwing gr = new GraphicSwing((Graphics2D) g);
|
||||
circuit.drawTo(gr);
|
||||
|
||||
listener.drawTo(gr);
|
||||
}
|
||||
|
||||
private Vector raster(Vector pos) {
|
||||
@ -42,21 +93,84 @@ public class CircuitComponent extends JComponent {
|
||||
((pos.y + GenericShape.SIZE2) / GenericShape.SIZE) * GenericShape.SIZE);
|
||||
}
|
||||
|
||||
private class MyMouseMotionListener implements MouseMotionListener, MouseListener {
|
||||
public enum Mode {part, move, wire}
|
||||
|
||||
private interface Mouse extends MouseMotionListener, MouseListener {
|
||||
void drawTo(Graphic gr);
|
||||
}
|
||||
|
||||
private class WireMouseListener implements Mouse {
|
||||
|
||||
private Wire wire;
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (e.getButton() == MouseEvent.BUTTON1) {
|
||||
if (wire != null) {
|
||||
circuit.add(wire);
|
||||
repaint();
|
||||
}
|
||||
Vector startPos = raster(new Vector(e.getX(), e.getY()));
|
||||
wire = new Wire(startPos, startPos);
|
||||
repaint();
|
||||
} else {
|
||||
wire = null;
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
if (wire != null) {
|
||||
wire.setP2(raster(new Vector(e.getX(), e.getY())));
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawTo(Graphic gr) {
|
||||
if (wire != null)
|
||||
wire.drawTo(gr);
|
||||
}
|
||||
}
|
||||
|
||||
private class PartMouseListener implements Mouse {
|
||||
|
||||
private Vector lastPos;
|
||||
private VisualPart partToDrag;
|
||||
private boolean autoPick = false;
|
||||
private Vector delta;
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
Vector pos = new Vector(e.getX(), e.getY());
|
||||
|
||||
if (partToDrag != null) {
|
||||
partToDrag.move(pos.sub(lastPos));
|
||||
partToDrag.setPos(raster(pos.add(delta)));
|
||||
repaint();
|
||||
}
|
||||
|
||||
lastPos = pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -70,28 +184,129 @@ public class CircuitComponent extends JComponent {
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
lastPos = new Vector(e.getX(), e.getY());
|
||||
Vector pos = new Vector(e.getX(), e.getY());
|
||||
for (VisualPart vp : circuit.getParts())
|
||||
if (vp.matches(lastPos)) {
|
||||
if (vp.matches(pos)) {
|
||||
partToDrag = vp;
|
||||
delta = partToDrag.getPos().sub(pos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
partToDrag.setPos(raster(partToDrag.getPos()));
|
||||
repaint();
|
||||
partToDrag = null;
|
||||
if (partToDrag != null) {
|
||||
partToDrag.setPos(raster(partToDrag.getPos()));
|
||||
repaint();
|
||||
partToDrag = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
if (autoPick && partToDrag != null) {
|
||||
partToDrag.setPos(raster(new Vector(e.getX(), e.getY())));
|
||||
autoPick = false;
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e) {
|
||||
}
|
||||
|
||||
public void setPartToDrag(VisualPart partToDrag) {
|
||||
this.partToDrag = partToDrag;
|
||||
autoPick = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawTo(Graphic gr) {
|
||||
}
|
||||
}
|
||||
|
||||
private class MoveMouseListener implements Mouse {
|
||||
private Vector corner1;
|
||||
private Vector corner2;
|
||||
private ArrayList<Moveable> elementsToMove;
|
||||
private Vector lastPos;
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
reset();
|
||||
repaint();
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
corner1 = null;
|
||||
corner2 = null;
|
||||
elementsToMove = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
if (corner1 == null) {
|
||||
corner1 = new Vector(e.getX(), e.getY());
|
||||
} else {
|
||||
elementsToMove = circuit.getElementsMatching(Vector.min(corner1, corner2), Vector.max(corner1, corner2));
|
||||
lastPos = new Vector(e.getX(), e.getY());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
if (elementsToMove != null) {
|
||||
Vector pos = new Vector(e.getX(), e.getY());
|
||||
Vector delta = raster(pos.sub(lastPos));
|
||||
|
||||
if (delta.x != 0 || delta.y != 0) {
|
||||
|
||||
for (Moveable m : elementsToMove)
|
||||
m.move(delta);
|
||||
|
||||
corner1.move(delta);
|
||||
corner2.move(delta);
|
||||
repaint();
|
||||
|
||||
lastPos = lastPos.add(delta);
|
||||
}
|
||||
} else {
|
||||
corner2 = new Vector(e.getX(), e.getY());
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawTo(Graphic gr) {
|
||||
if (corner1 != null && corner2 != null) {
|
||||
Polygon p = new Polygon(true)
|
||||
.add(corner1)
|
||||
.add(new Vector(corner1.x, corner2.y))
|
||||
.add(corner2)
|
||||
.add(new Vector(corner2.x, corner1.y));
|
||||
gr.drawPolygon(p, Style.THIN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,8 +7,10 @@ import java.awt.*;
|
||||
*/
|
||||
public class Style {
|
||||
public static final Style NORMAL = new Style(2, false, Color.BLACK);
|
||||
public static final Style WIRE = new Style(2, false, Color.BLUE);
|
||||
public static final Style WIRE = new Style(2, true, Color.BLUE);
|
||||
public static final Style FILLED = new Style(2, true, Color.BLACK);
|
||||
public static final Style THIN = new Style(1, false, Color.BLACK);
|
||||
;
|
||||
|
||||
private final int thickness;
|
||||
private final boolean filled;
|
||||
|
@ -1,12 +1,14 @@
|
||||
package de.neemann.digital.gui.draw.graphics;
|
||||
|
||||
import de.neemann.digital.gui.draw.parts.Moveable;
|
||||
|
||||
/**
|
||||
* @author hneemann
|
||||
*/
|
||||
public class Vector {
|
||||
public class Vector implements Moveable {
|
||||
|
||||
public final int x;
|
||||
public final int y;
|
||||
public int x;
|
||||
public int y;
|
||||
|
||||
public Vector(int x, int y) {
|
||||
this.x = x;
|
||||
@ -66,4 +68,14 @@ public class Vector {
|
||||
", y=" + y +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public void move(Vector delta) {
|
||||
x += delta.x;
|
||||
y += delta.y;
|
||||
}
|
||||
|
||||
public boolean inside(Vector min, Vector max) {
|
||||
return min.x <= x && x <= max.x && min.y <= y && y <= max.y;
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
package de.neemann.digital.gui.draw.parts;
|
||||
|
||||
import de.neemann.digital.gui.draw.graphics.Graphic;
|
||||
import de.neemann.digital.gui.draw.graphics.Vector;
|
||||
import de.neemann.digital.gui.draw.shapes.Drawable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* @author hneemann
|
||||
@ -30,7 +32,44 @@ public class Circuit implements Drawable {
|
||||
visualParts.add(visualPart);
|
||||
}
|
||||
|
||||
public void add(Wire wire) {
|
||||
wires.add(wire);
|
||||
}
|
||||
|
||||
public ArrayList<VisualPart> getParts() {
|
||||
return visualParts;
|
||||
}
|
||||
|
||||
public ArrayList<Moveable> getElementsMatching(Vector min, Vector max) {
|
||||
ArrayList<Moveable> m = new ArrayList<>();
|
||||
for (VisualPart vp : visualParts)
|
||||
if (vp.matches(min, max))
|
||||
m.add(vp);
|
||||
|
||||
for (Wire w : wires) {
|
||||
if (w.p1.inside(min, max))
|
||||
m.add(w.p1);
|
||||
if (w.p2.inside(min, max))
|
||||
m.add(w.p2);
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
public void delete(Vector min, Vector max) {
|
||||
{
|
||||
Iterator<VisualPart> it = visualParts.iterator();
|
||||
while (it.hasNext())
|
||||
if (it.next().matches(min, max))
|
||||
it.remove();
|
||||
}
|
||||
{
|
||||
Iterator<Wire> it = wires.iterator();
|
||||
while (it.hasNext()) {
|
||||
Wire w = it.next();
|
||||
if (w.p1.inside(min, max) || w.p2.inside(min, max))
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,15 @@ public class VisualPart implements Drawable, Moveable {
|
||||
(p.y <= m.getMax().y);
|
||||
}
|
||||
|
||||
public boolean matches(Vector min, Vector max) {
|
||||
GraphicMinMax m = getMinMax();
|
||||
return (min.x <= m.getMin().x) &&
|
||||
(m.getMax().x <= max.x) &&
|
||||
(min.y <= m.getMin().y) &&
|
||||
(m.getMax().y <= max.y);
|
||||
}
|
||||
|
||||
|
||||
public int getRotate() {
|
||||
return rotate;
|
||||
}
|
||||
|
@ -10,8 +10,13 @@ import de.neemann.digital.gui.draw.shapes.Drawable;
|
||||
*/
|
||||
public class Wire implements Drawable, Moveable {
|
||||
|
||||
private Vector p1;
|
||||
private Vector p2;
|
||||
public Vector p1;
|
||||
public Vector p2;
|
||||
|
||||
public Wire(Vector p1, Vector p2) {
|
||||
this.p1 = p1;
|
||||
this.p2 = p2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawTo(Graphic graphic) {
|
||||
@ -23,4 +28,8 @@ public class Wire implements Drawable, Moveable {
|
||||
p1 = p1.add(delta);
|
||||
p2 = p2.add(delta);
|
||||
}
|
||||
|
||||
public void setP2(Vector p2) {
|
||||
this.p2 = p2;
|
||||
}
|
||||
}
|
||||
|
@ -19,9 +19,12 @@ public class GenericShape implements Shape {
|
||||
private final String name;
|
||||
private final int inputs;
|
||||
private final int outputs;
|
||||
private transient ArrayList<Pin> pins;
|
||||
private final int width;
|
||||
private final boolean symetric;
|
||||
private boolean invert = false;
|
||||
|
||||
private transient ArrayList<Pin> pins;
|
||||
|
||||
public GenericShape(String name, int inputs) {
|
||||
this(name, inputs, 1);
|
||||
}
|
||||
@ -30,6 +33,8 @@ public class GenericShape implements Shape {
|
||||
this.name = name;
|
||||
this.inputs = inputs;
|
||||
this.outputs = outputs;
|
||||
width = inputs == 1 && outputs == 1 ? 1 : 3;
|
||||
symetric = outputs == 1;
|
||||
}
|
||||
|
||||
public GenericShape invert(boolean invert) {
|
||||
@ -43,15 +48,25 @@ public class GenericShape implements Shape {
|
||||
ObservableValue[] outputValues = partDescription.create().getOutputs();
|
||||
String[] inputs = partDescription.getInputNames();
|
||||
pins = new ArrayList<>(inputs.length + outputs);
|
||||
for (int i = 0; i < inputs.length; i++)
|
||||
pins.add(new Pin(new Vector(0, i * SIZE), inputs[i], Pin.Direction.input));
|
||||
|
||||
int offs = symetric ? inputs.length / 2 * SIZE : 0;
|
||||
|
||||
for (int i = 0; i < inputs.length; i++) {
|
||||
int correct = 0;
|
||||
if (symetric && ((inputs.length & 1) == 0) && i >= inputs.length / 2)
|
||||
correct = SIZE;
|
||||
|
||||
pins.add(new Pin(new Vector(0, i * SIZE + correct), inputs[i], Pin.Direction.input));
|
||||
}
|
||||
|
||||
|
||||
if (invert) {
|
||||
for (int i = 0; i < outputs; i++)
|
||||
pins.add(new Pin(new Vector(SIZE * 4, i * SIZE), outputValues[i].getName(), Pin.Direction.output));
|
||||
pins.add(new Pin(new Vector(SIZE * (width + 1), i * SIZE + offs), outputValues[i].getName(), Pin.Direction.output));
|
||||
|
||||
} else {
|
||||
for (int i = 0; i < outputs; i++)
|
||||
pins.add(new Pin(new Vector(SIZE * 3, i * SIZE), outputValues[i].getName(), Pin.Direction.output));
|
||||
pins.add(new Pin(new Vector(SIZE * width, i * SIZE + offs), outputValues[i].getName(), Pin.Direction.output));
|
||||
}
|
||||
}
|
||||
return pins;
|
||||
@ -61,15 +76,20 @@ public class GenericShape implements Shape {
|
||||
public void drawTo(Graphic graphic) {
|
||||
int max = Math.max(inputs, outputs);
|
||||
int height = (max - 1) * SIZE + SIZE2;
|
||||
|
||||
if (symetric && ((inputs & 1) == 0)) height += SIZE;
|
||||
|
||||
graphic.drawPolygon(new Polygon(true)
|
||||
.add(1, -SIZE2)
|
||||
.add(SIZE * 3 - 1, -SIZE2)
|
||||
.add(SIZE * 3 - 1, height)
|
||||
.add(SIZE * width - 1, -SIZE2)
|
||||
.add(SIZE * width - 1, height)
|
||||
.add(1, height), Style.NORMAL);
|
||||
|
||||
if (invert) {
|
||||
int offs = symetric ? inputs / 2 * SIZE : 0;
|
||||
for (int i = 0; i < outputs; i++)
|
||||
graphic.drawCircle(new Vector(SIZE * 3, i * SIZE - SIZE2 + 1), new Vector(SIZE * 4 - 2, i * SIZE + SIZE2 - 1), Style.NORMAL);
|
||||
graphic.drawCircle(new Vector(SIZE * width, i * SIZE - SIZE2 + 1 + offs),
|
||||
new Vector(SIZE * (width + 1) - 2, i * SIZE + SIZE2 - 1 + offs), Style.NORMAL);
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user