added move and delete

This commit is contained in:
hneemann 2016-03-16 22:50:05 +01:00
parent 1095d1c626
commit 12d5f00312
8 changed files with 362 additions and 35 deletions

View File

@ -38,7 +38,13 @@ public class Main extends JFrame {
parts.add(createSimpleMenu("OR", inputs -> Or.createFactory(1, inputs))); parts.add(createSimpleMenu("OR", inputs -> Or.createFactory(1, inputs)));
parts.add(createSimpleMenu("NAND", inputs -> NAnd.createFactory(1, inputs))); parts.add(createSimpleMenu("NAND", inputs -> NAnd.createFactory(1, inputs)));
parts.add(createSimpleMenu("NOR", inputs -> NOr.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); setJMenuBar(bar);
} }
@ -50,7 +56,7 @@ public class Main extends JFrame {
private JMenu createSimpleMenu(String name, DescriptionFactory factory) { private JMenu createSimpleMenu(String name, DescriptionFactory factory) {
JMenu m = new JMenu(name); JMenu m = new JMenu(name);
for (int i = 2; i < 16; i++) { 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; return m;
} }
@ -59,18 +65,33 @@ public class Main extends JFrame {
PartDescription create(int inputs); PartDescription create(int inputs);
} }
private class InsertAbstractAction extends AbstractAction { private class InsertAction extends AbstractAction {
private final PartDescription partDescription; private final PartDescription partDescription;
public InsertAbstractAction(String name, PartDescription partDescription) { public InsertAction(String name, PartDescription partDescription) {
super(name); super(name);
this.partDescription = partDescription; this.partDescription = partDescription;
} }
@Override @Override
public void actionPerformed(ActionEvent e) { 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);
}
}
} }

View File

@ -1,30 +1,79 @@
package de.neemann.digital.gui.components; package de.neemann.digital.gui.components;
import de.neemann.digital.gui.draw.graphics.GraphicSwing; import de.neemann.digital.gui.draw.graphics.*;
import de.neemann.digital.gui.draw.graphics.Vector; import de.neemann.digital.gui.draw.graphics.Polygon;
import de.neemann.digital.gui.draw.parts.Circuit; 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.VisualPart;
import de.neemann.digital.gui.draw.parts.Wire;
import de.neemann.digital.gui.draw.shapes.GenericShape; import de.neemann.digital.gui.draw.shapes.GenericShape;
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.awt.event.MouseListener; import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener; import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
/** /**
* @author hneemann * @author hneemann
*/ */
public class CircuitComponent extends JComponent { public class CircuitComponent extends JComponent {
private static final String delAction = "myDelAction";
private final Circuit circuit; private final Circuit circuit;
;
private Mouse listener;
public CircuitComponent(Circuit circuit) { public CircuitComponent(Circuit circuit) {
this.circuit = circuit; this.circuit = circuit;
setMode(Mode.part);
MyMouseMotionListener l = new MyMouseMotionListener(); KeyStroke delKey = KeyStroke.getKeyStroke("DELETE");
addMouseMotionListener(l); getInputMap().put(delKey, delAction);
addMouseListener(l); 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 @Override
@ -35,6 +84,8 @@ public class CircuitComponent extends JComponent {
GraphicSwing gr = new GraphicSwing((Graphics2D) g); GraphicSwing gr = new GraphicSwing((Graphics2D) g);
circuit.drawTo(gr); circuit.drawTo(gr);
listener.drawTo(gr);
} }
private Vector raster(Vector pos) { private Vector raster(Vector pos) {
@ -42,21 +93,84 @@ public class CircuitComponent extends JComponent {
((pos.y + GenericShape.SIZE2) / GenericShape.SIZE) * GenericShape.SIZE); ((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 VisualPart partToDrag;
private boolean autoPick = false;
private Vector delta;
@Override @Override
public void mouseDragged(MouseEvent e) { public void mouseDragged(MouseEvent e) {
Vector pos = new Vector(e.getX(), e.getY()); Vector pos = new Vector(e.getX(), e.getY());
if (partToDrag != null) { if (partToDrag != null) {
partToDrag.move(pos.sub(lastPos)); partToDrag.setPos(raster(pos.add(delta)));
repaint(); repaint();
} }
lastPos = pos;
} }
@Override @Override
@ -70,28 +184,129 @@ public class CircuitComponent extends JComponent {
@Override @Override
public void mousePressed(MouseEvent e) { 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()) for (VisualPart vp : circuit.getParts())
if (vp.matches(lastPos)) { if (vp.matches(pos)) {
partToDrag = vp; partToDrag = vp;
delta = partToDrag.getPos().sub(pos);
break; break;
} }
} }
@Override @Override
public void mouseReleased(MouseEvent e) { public void mouseReleased(MouseEvent e) {
partToDrag.setPos(raster(partToDrag.getPos())); if (partToDrag != null) {
repaint(); partToDrag.setPos(raster(partToDrag.getPos()));
partToDrag = null; repaint();
partToDrag = null;
}
} }
@Override @Override
public void mouseEntered(MouseEvent e) { public void mouseEntered(MouseEvent e) {
if (autoPick && partToDrag != null) {
partToDrag.setPos(raster(new Vector(e.getX(), e.getY())));
autoPick = false;
repaint();
}
} }
@Override @Override
public void mouseExited(MouseEvent e) { 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);
}
}
} }
} }

View File

@ -7,8 +7,10 @@ import java.awt.*;
*/ */
public class Style { public class Style {
public static final Style NORMAL = new Style(2, false, Color.BLACK); 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 FILLED = new Style(2, true, Color.BLACK);
public static final Style THIN = new Style(1, false, Color.BLACK);
;
private final int thickness; private final int thickness;
private final boolean filled; private final boolean filled;

View File

@ -1,12 +1,14 @@
package de.neemann.digital.gui.draw.graphics; package de.neemann.digital.gui.draw.graphics;
import de.neemann.digital.gui.draw.parts.Moveable;
/** /**
* @author hneemann * @author hneemann
*/ */
public class Vector { public class Vector implements Moveable {
public final int x; public int x;
public final int y; public int y;
public Vector(int x, int y) { public Vector(int x, int y) {
this.x = x; this.x = x;
@ -66,4 +68,14 @@ public class Vector {
", y=" + y + ", 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;
}
} }

View File

@ -1,9 +1,11 @@
package de.neemann.digital.gui.draw.parts; package de.neemann.digital.gui.draw.parts;
import de.neemann.digital.gui.draw.graphics.Graphic; 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 de.neemann.digital.gui.draw.shapes.Drawable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
/** /**
* @author hneemann * @author hneemann
@ -30,7 +32,44 @@ public class Circuit implements Drawable {
visualParts.add(visualPart); visualParts.add(visualPart);
} }
public void add(Wire wire) {
wires.add(wire);
}
public ArrayList<VisualPart> getParts() { public ArrayList<VisualPart> getParts() {
return visualParts; 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();
}
}
}
} }

View File

@ -37,6 +37,15 @@ public class VisualPart implements Drawable, Moveable {
(p.y <= m.getMax().y); (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() { public int getRotate() {
return rotate; return rotate;
} }

View File

@ -10,8 +10,13 @@ import de.neemann.digital.gui.draw.shapes.Drawable;
*/ */
public class Wire implements Drawable, Moveable { public class Wire implements Drawable, Moveable {
private Vector p1; public Vector p1;
private Vector p2; public Vector p2;
public Wire(Vector p1, Vector p2) {
this.p1 = p1;
this.p2 = p2;
}
@Override @Override
public void drawTo(Graphic graphic) { public void drawTo(Graphic graphic) {
@ -23,4 +28,8 @@ public class Wire implements Drawable, Moveable {
p1 = p1.add(delta); p1 = p1.add(delta);
p2 = p2.add(delta); p2 = p2.add(delta);
} }
public void setP2(Vector p2) {
this.p2 = p2;
}
} }

View File

@ -19,9 +19,12 @@ public class GenericShape implements Shape {
private final String name; private final String name;
private final int inputs; private final int inputs;
private final int outputs; private final int outputs;
private transient ArrayList<Pin> pins; private final int width;
private final boolean symetric;
private boolean invert = false; private boolean invert = false;
private transient ArrayList<Pin> pins;
public GenericShape(String name, int inputs) { public GenericShape(String name, int inputs) {
this(name, inputs, 1); this(name, inputs, 1);
} }
@ -30,6 +33,8 @@ public class GenericShape implements Shape {
this.name = name; this.name = name;
this.inputs = inputs; this.inputs = inputs;
this.outputs = outputs; this.outputs = outputs;
width = inputs == 1 && outputs == 1 ? 1 : 3;
symetric = outputs == 1;
} }
public GenericShape invert(boolean invert) { public GenericShape invert(boolean invert) {
@ -43,15 +48,25 @@ public class GenericShape implements Shape {
ObservableValue[] outputValues = partDescription.create().getOutputs(); ObservableValue[] outputValues = partDescription.create().getOutputs();
String[] inputs = partDescription.getInputNames(); String[] inputs = partDescription.getInputNames();
pins = new ArrayList<>(inputs.length + outputs); 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) { if (invert) {
for (int i = 0; i < outputs; i++) 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 { } else {
for (int i = 0; i < outputs; i++) 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; return pins;
@ -61,15 +76,20 @@ public class GenericShape implements Shape {
public void drawTo(Graphic graphic) { public void drawTo(Graphic graphic) {
int max = Math.max(inputs, outputs); int max = Math.max(inputs, outputs);
int height = (max - 1) * SIZE + SIZE2; int height = (max - 1) * SIZE + SIZE2;
if (symetric && ((inputs & 1) == 0)) height += SIZE;
graphic.drawPolygon(new Polygon(true) graphic.drawPolygon(new Polygon(true)
.add(1, -SIZE2) .add(1, -SIZE2)
.add(SIZE * 3 - 1, -SIZE2) .add(SIZE * width - 1, -SIZE2)
.add(SIZE * 3 - 1, height) .add(SIZE * width - 1, height)
.add(1, height), Style.NORMAL); .add(1, height), Style.NORMAL);
if (invert) { if (invert) {
int offs = symetric ? inputs / 2 * SIZE : 0;
for (int i = 0; i < outputs; i++) 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);
} }