improved mouse handing when editing the circuit

This commit is contained in:
hneemann 2016-04-07 11:57:06 +02:00
parent 7060f47bbf
commit 38c5ea0c1a
4 changed files with 511 additions and 303 deletions

View File

@ -109,4 +109,8 @@ public class Vector implements Moveable {
result = 31 * result + y; result = 31 * result + y;
return result; return result;
} }
public boolean isZero() {
return x == 0 && y == 0;
}
} }

View File

@ -80,7 +80,7 @@ public class LibrarySelector implements ElementNotFoundNotification {
ElementTypeDescription des = importElement(fc.getSelectedFile()); ElementTypeDescription des = importElement(fc.getSelectedFile());
if (des != null) { if (des != null) {
VisualElement visualElement = new VisualElement(des.getName()).setPos(new Vector(10, 10)).setShapeFactory(shapeFactory); VisualElement visualElement = new VisualElement(des.getName()).setPos(new Vector(10, 10)).setShapeFactory(shapeFactory);
circuitComponent.setPartToDrag(visualElement); circuitComponent.setPartToInsert(visualElement);
} }
} }
} }
@ -143,7 +143,7 @@ public class LibrarySelector implements ElementNotFoundNotification {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
VisualElement visualElement = new VisualElement(name).setPos(new Vector(10, 10)).setShapeFactory(shapeFactory); VisualElement visualElement = new VisualElement(name).setPos(new Vector(10, 10)).setShapeFactory(shapeFactory);
elementState.activate(); elementState.activate();
circuitComponent.setPartToDrag(visualElement); circuitComponent.setPartToInsert(visualElement);
insertHistory.add(this); insertHistory.add(this);
} }
} }

View File

@ -48,12 +48,12 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave {
ATTR_LIST.add(AttributeKey.ShowListing); ATTR_LIST.add(AttributeKey.ShowListing);
ATTR_LIST.add(AttributeKey.StartTimer); ATTR_LIST.add(AttributeKey.StartTimer);
} }
private static final String MESSAGE = Lang.get("message"); private static final String MESSAGE = Lang.get("message");
private static final Icon ICON_RUN = IconCreator.create("run.gif"); private static final Icon ICON_RUN = IconCreator.create("run.gif");
private static final Icon ICON_MICRO = IconCreator.create("micro.gif"); private static final Icon ICON_MICRO = IconCreator.create("micro.gif");
private static final Icon ICON_STEP = IconCreator.create("step.gif"); private static final Icon ICON_STEP = IconCreator.create("step.gif");
private static final Icon ICON_ELEMENT = IconCreator.create("element.gif"); private static final Icon ICON_ELEMENT = IconCreator.create("element.gif");
private static final Icon ICON_SELECT = IconCreator.create("Select24.gif");
private static final Icon ICON_NEW = IconCreator.create("New24.gif"); private static final Icon ICON_NEW = IconCreator.create("New24.gif");
private static final Icon ICON_OPEN = IconCreator.create("Open24.gif"); private static final Icon ICON_OPEN = IconCreator.create("Open24.gif");
private static final Icon ICON_OPEN_WIN = IconCreator.create("OpenNew24.gif"); private static final Icon ICON_OPEN_WIN = IconCreator.create("OpenNew24.gif");
@ -77,7 +77,6 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave {
private ScheduledThreadPoolExecutor timerExecuter = new ScheduledThreadPoolExecutor(1); private ScheduledThreadPoolExecutor timerExecuter = new ScheduledThreadPoolExecutor(1);
private State elementState; private State elementState;
private State selectState;
private State runModelState; private State runModelState;
private State runModelMicroState; private State runModelMicroState;
private ElementAttributes settings = new ElementAttributes(); private ElementAttributes settings = new ElementAttributes();
@ -208,7 +207,6 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave {
bar.add(edit); bar.add(edit);
ToolTipAction elementStateAction = elementState.createToolTipAction(Lang.get("menu_element"), ICON_ELEMENT).setToolTip(Lang.get("menu_element_tt")); ToolTipAction elementStateAction = elementState.createToolTipAction(Lang.get("menu_element"), ICON_ELEMENT).setToolTip(Lang.get("menu_element_tt"));
ToolTipAction selectStateAction = selectState.createToolTipAction(Lang.get("menu_select"), ICON_SELECT).setToolTip(Lang.get("menu_select_tt"));
ToolTipAction orderInputs = new ToolTipAction(Lang.get("menu_orderInputs")) { ToolTipAction orderInputs = new ToolTipAction(Lang.get("menu_orderInputs")) {
@Override @Override
@ -243,7 +241,6 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave {
edit.add(elementStateAction.createJMenuItem()); edit.add(elementStateAction.createJMenuItem());
edit.add(selectStateAction.createJMenuItem());
edit.add(orderInputs.createJMenuItem()); edit.add(orderInputs.createJMenuItem());
edit.add(orderOutputs.createJMenuItem()); edit.add(orderOutputs.createJMenuItem());
edit.add(orderMeasurements.createJMenuItem()); edit.add(orderMeasurements.createJMenuItem());
@ -322,7 +319,6 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave {
toolBar.add(save.createJButtonNoText()); toolBar.add(save.createJButtonNoText());
toolBar.addSeparator(); toolBar.addSeparator();
toolBar.add(elementState.setIndicator(elementStateAction.createJButtonNoText())); toolBar.add(elementState.setIndicator(elementStateAction.createJButtonNoText()));
toolBar.add(selectState.setIndicator(selectStateAction.createJButtonNoText()));
toolBar.add(circuitComponent.getDeleteAction().createJButtonNoText()); toolBar.add(circuitComponent.getDeleteAction().createJButtonNoText());
toolBar.addSeparator(); toolBar.addSeparator();
toolBar.add(runModelState.setIndicator(runModelAction.createJButtonNoText())); toolBar.add(runModelState.setIndicator(runModelAction.createJButtonNoText()));
@ -362,8 +358,16 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave {
} }
private void setupStates() { private void setupStates() {
elementState = stateManager.register(new ModeState(CircuitComponent.Mode.part)); elementState = stateManager.register(new State() {
selectState = stateManager.register(new ModeState(CircuitComponent.Mode.select)); @Override
public void enter() {
super.enter();
clearModelDescription();
circuitComponent.setModeAndReset(false);
doStep.setEnabled(false);
}
});
runModelState = stateManager.register(new State() { runModelState = stateManager.register(new State() {
@Override @Override
public void enter() { public void enter() {
@ -413,7 +417,7 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave {
private boolean createAndStartModel(boolean runClock, ModelEvent.Event updateEvent) { private boolean createAndStartModel(boolean runClock, ModelEvent.Event updateEvent) {
try { try {
circuitComponent.removeHighLighted(); circuitComponent.removeHighLighted();
circuitComponent.setModeAndReset(CircuitComponent.Mode.running); circuitComponent.setModeAndReset(true);
setModelDescription(new ModelDescription(circuitComponent.getCircuit(), library)); setModelDescription(new ModelDescription(circuitComponent.getCircuit(), library));
if (runClock) { if (runClock) {
@ -535,22 +539,6 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave {
setTitle(Lang.get("digital")); setTitle(Lang.get("digital"));
} }
private class ModeState extends State {
private final CircuitComponent.Mode mode;
ModeState(CircuitComponent.Mode mode) {
this.mode = mode;
}
@Override
public void enter() {
super.enter();
clearModelDescription();
circuitComponent.setModeAndReset(mode);
doStep.setEnabled(false);
}
}
private class FullStepObserver implements Observer { private class FullStepObserver implements Observer {
private final Model model; private final Model model;

View File

@ -45,18 +45,40 @@ public class CircuitComponent extends JComponent {
private final ElementLibrary library; private final ElementLibrary library;
private final ShapeFactory shapeFactory; private final ShapeFactory shapeFactory;
private final HashSet<Drawable> highLighted; private final HashSet<Drawable> highLighted;
private final DelAction deleteAction; private final ToolTipAction deleteAction;
private final MouseController mouseNormal;
private final MouseControllerInsertElement mouseInsertElement;
private final MouseControllerMoveElement mouseMoveElement;
private final MouseControllerWire mouseWire;
private final MouseControllerSelect mouseSelect;
private final MouseControllerMoveSelected mouseMoveSelected;
private final MouseControllerCopySelected mouseCopySelected;
private final MouseController mouseRun;
private Circuit circuit; private Circuit circuit;
private Mouse listener; private MouseController activeMouseController;
private AffineTransform transform = new AffineTransform(); private AffineTransform transform = new AffineTransform();
private Observer manualChangeObserver; private Observer manualChangeObserver;
/**
* Creates a new instance
*
* @param aCircuit the circuit to show
* @param library the library used to edit the attributes of the elements
* @param shapeFactory the shapeFactory used for copied elements
*/
public CircuitComponent(Circuit aCircuit, ElementLibrary library, ShapeFactory shapeFactory) { public CircuitComponent(Circuit aCircuit, ElementLibrary library, ShapeFactory shapeFactory) {
this.library = library; this.library = library;
this.shapeFactory = shapeFactory; this.shapeFactory = shapeFactory;
highLighted = new HashSet<>(); highLighted = new HashSet<>();
deleteAction = new DelAction();
setCircuit(aCircuit); deleteAction = new ToolTipAction(Lang.get("menu_delete"), ICON_DELETE) {
@Override
public void actionPerformed(ActionEvent e) {
activeMouseController.delete();
}
}.setToolTip(Lang.get("menu_delete_tt"));
KeyStroke delKey = KeyStroke.getKeyStroke("DELETE"); KeyStroke delKey = KeyStroke.getKeyStroke("DELETE");
getInputMap().put(delKey, DEL_ACTION); getInputMap().put(delKey, DEL_ACTION);
@ -72,55 +94,86 @@ public class CircuitComponent extends JComponent {
transform.translate(-pos.x, -pos.y); transform.translate(-pos.x, -pos.y);
repaint(); repaint();
}); });
Cursor normalCursor = new Cursor(Cursor.DEFAULT_CURSOR);
mouseNormal = new MouseControllerNormal(normalCursor);
mouseInsertElement = new MouseControllerInsertElement(normalCursor);
mouseMoveElement = new MouseControllerMoveElement(normalCursor);
mouseWire = new MouseControllerWire(normalCursor);
mouseSelect = new MouseControllerSelect(new Cursor(Cursor.CROSSHAIR_CURSOR));
mouseMoveSelected = new MouseControllerMoveSelected(new Cursor(Cursor.MOVE_CURSOR));
mouseCopySelected = new MouseControllerCopySelected(new Cursor(Cursor.MOVE_CURSOR));
mouseRun = new MouseControllerRun(normalCursor);
setCircuit(aCircuit);
MouseDispatcher disp = new MouseDispatcher();
addMouseMotionListener(disp);
addMouseListener(disp);
} }
/**
* @return the delete action to put it to the toolbar
*/
public ToolTipAction getDeleteAction() { public ToolTipAction getDeleteAction() {
return deleteAction; return deleteAction;
} }
/**
* Sets the observer to call if the user is clicking on elements while running.
*
* @param callOnManualChange the listener
*/
public void setManualChangeObserver(Observer callOnManualChange) { public void setManualChangeObserver(Observer callOnManualChange) {
this.manualChangeObserver = callOnManualChange; this.manualChangeObserver = callOnManualChange;
} }
public void setModeAndReset(Mode mode) { /**
if (listener != null) { * Sets the edit mode and resets the circuit
removeMouseListener(listener); *
removeMouseMotionListener(listener); * @param runMode true if running, false if editing
} */
switch (mode) { public void setModeAndReset(boolean runMode) {
case part: if (runMode)
listener = new PartMouseListener(); mouseRun.activate();
setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); else
break; mouseNormal.activate();
case select:
listener = new SelectMouseListener();
setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
break;
case running:
listener = new RunningMouseListener();
setCursor(new Cursor(Cursor.HAND_CURSOR));
break;
}
addMouseMotionListener(listener);
addMouseListener(listener);
requestFocusInWindow(); requestFocusInWindow();
circuit.clearState(); circuit.clearState();
deleteAction.setEnabled(false);
repaint();
} }
/**
* @return the high lighted elements
*/
public Collection<Drawable> getHighLighted() { public Collection<Drawable> getHighLighted() {
return highLighted; return highLighted;
} }
/**
* Adds a drawable to the highlighted list
*
* @param drawable the drawable to add
* @param <T> type of drawable
*/
public <T extends Drawable> void addHighLighted(T drawable) { public <T extends Drawable> void addHighLighted(T drawable) {
highLighted.add(drawable); highLighted.add(drawable);
} }
/**
* Add a list of drawables to high light
*
* @param drawables the list of drawables
*/
public void addHighLighted(Collection<? extends Drawable> drawables) { public void addHighLighted(Collection<? extends Drawable> drawables) {
highLighted.addAll(drawables); highLighted.addAll(drawables);
} }
/**
* Adds alle the wires representing the given value to the highlighted list
*
* @param values the value
*/
public void addHighLightedWires(ObservableValue[] values) { public void addHighLightedWires(ObservableValue[] values) {
HashSet<ObservableValue> ov = new HashSet<>(); HashSet<ObservableValue> ov = new HashSet<>();
ov.addAll(Arrays.asList(values)); ov.addAll(Arrays.asList(values));
@ -129,13 +182,20 @@ public class CircuitComponent extends JComponent {
addHighLighted(w); addHighLighted(w);
} }
/**
* remove all highlighted elements
*/
public void removeHighLighted() { public void removeHighLighted() {
highLighted.clear(); highLighted.clear();
} }
public void setPartToDrag(VisualElement part) { /**
if (listener instanceof PartMouseListener) * Addes the given element to insert to the circuit
((PartMouseListener) listener).setPartToInsert(part); *
* @param element the element to insert
*/
public void setPartToInsert(VisualElement element) {
mouseInsertElement.activate(element);
} }
@Override @Override
@ -150,7 +210,7 @@ public class CircuitComponent extends JComponent {
GraphicSwing gr = new GraphicSwing(gr2); GraphicSwing gr = new GraphicSwing(gr2);
circuit.drawTo(gr, highLighted); circuit.drawTo(gr, highLighted);
listener.drawTo(gr); activeMouseController.drawTo(gr);
gr2.setTransform(oldTrans); gr2.setTransform(oldTrans);
} }
@ -169,10 +229,17 @@ public class CircuitComponent extends JComponent {
(int) Math.round((double) pos.y / GenericShape.SIZE) * GenericShape.SIZE); (int) Math.round((double) pos.y / GenericShape.SIZE) * GenericShape.SIZE);
} }
/**
* @return the circuit shown
*/
public Circuit getCircuit() { public Circuit getCircuit() {
return circuit; return circuit;
} }
/**
* Sets a circuit to this component
* @param circuit the circuit
*/
public void setCircuit(Circuit circuit) { public void setCircuit(Circuit circuit) {
this.circuit = circuit; this.circuit = circuit;
@ -195,255 +262,357 @@ public class CircuitComponent extends JComponent {
} else } else
transform = new AffineTransform(); transform = new AffineTransform();
setModeAndReset(Mode.part); setModeAndReset(false);
} }
private boolean editAttributes(MouseEvent e) { private void editAttributes(VisualElement vp, MouseEvent e) {
VisualElement vp = circuit.getElementAt(getPosVector(e)); String name = vp.getElementName();
if (vp != null) { ElementTypeDescription elementType = library.getElementType(name);
String name = vp.getElementName(); if (elementType instanceof LibrarySelector.ElementTypeDescriptionCustom) {
ElementTypeDescription elementType = library.getElementType(name); new Main(this, ((LibrarySelector.ElementTypeDescriptionCustom) elementType).getFile(), new SavedListener() {
if (elementType instanceof LibrarySelector.ElementTypeDescriptionCustom) { @Override
new Main(this, ((LibrarySelector.ElementTypeDescriptionCustom) elementType).getFile(), new SavedListener() { public void saved(File filename) {
@Override library.removeElement(filename.getName());
public void saved(File filename) { circuit.clearState();
library.removeElement(filename.getName());
circuit.clearState();
repaint();
}
}).setVisible(true);
} else {
ArrayList<AttributeKey> list = elementType.getAttributeList();
if (list.size() > 0) {
Point p = new Point(e.getX(), e.getY());
SwingUtilities.convertPointToScreen(p, CircuitComponent.this);
if (new AttributeDialog(this, p, list, vp.getElementAttributes()).showDialog()) {
circuit.modified();
repaint();
}
return true;
}
}
}
return false;
}
private class DelAction extends ToolTipAction {
DelAction() {
super(Lang.get("menu_delete"), ICON_DELETE);
setToolTip(Lang.get("menu_delete_tt"));
}
@Override
public void actionPerformed(ActionEvent e) {
if (listener instanceof SelectMouseListener) {
SelectMouseListener mml = (SelectMouseListener) 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(); repaint();
} }
} else if (listener instanceof PartMouseListener) { }).setVisible(true);
PartMouseListener pml = (PartMouseListener) listener; } else {
if (!pml.insert) { ArrayList<AttributeKey> list = elementType.getAttributeList();
circuit.delete(pml.partToInsert); if (list.size() > 0) {
Point p = new Point(e.getX(), e.getY());
SwingUtilities.convertPointToScreen(p, CircuitComponent.this);
if (new AttributeDialog(this, p, list, vp.getElementAttributes()).showDialog()) {
circuit.modified();
repaint();
} }
pml.partToInsert = null;
deleteAction.setEnabled(false);
repaint();
} }
} }
} }
private class MouseDispatcher extends MouseAdapter implements MouseMotionListener {
public enum Mode {part, running, select}
private abstract class Mouse extends MouseAdapter implements MouseMotionListener {
private Vector pos; private Vector pos;
abstract void drawTo(Graphic gr); @Override
public void mouseClicked(MouseEvent e) {
activeMouseController.clicked(e);
}
@Override @Override
public void mousePressed(MouseEvent e) { public void mousePressed(MouseEvent e) {
pos = new Vector(e.getX(), e.getY()); pos = new Vector(e.getX(), e.getY());
} activeMouseController.pressed(e);
@Override
public void mouseDragged(MouseEvent e) {
Vector newPos = new Vector(e.getX(), e.getY());
Vector delta = newPos.sub(pos);
double s = transform.getScaleX();
transform.translate(delta.x / s, delta.y / s);
pos = newPos;
repaint();
}
}
private class PartMouseListener extends Mouse {
private VisualElement partToInsert;
private Wire wire;
private boolean autoPick = false;
private Vector delta;
private boolean insert;
@Override
public void mouseMoved(MouseEvent e) {
if (partToInsert != null) {
Vector pos = getPosVector(e);
partToInsert.setPos(raster(pos.add(delta)));
repaint();
}
if (wire != null) {
wire.setP2(raster(getPosVector(e)));
repaint();
}
}
@Override
public void mouseClicked(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
if (partToInsert == null) {
insert = false;
if (wire == null) {
Vector pos = getPosVector(e);
VisualElement vp = circuit.getElementAt(pos);
if (vp != null) {
Vector startPos = raster(pos);
if (circuit.isPinPos(startPos)) {
wire = new Wire(startPos, startPos);
} else {
partToInsert = vp;
delta = partToInsert.getPos().sub(pos);
}
repaint();
} else {
Vector startPos = raster(pos);
wire = new Wire(startPos, startPos);
}
} else {
circuit.add(wire);
Vector startPos = raster(getPosVector(e));
if (circuit.isPinPos(startPos))
wire = null;
else
wire = new Wire(startPos, startPos);
}
} else {
partToInsert.setPos(raster(partToInsert.getPos()));
if (insert)
circuit.add(partToInsert);
circuit.modified();
repaint();
partToInsert = null;
}
deleteAction.setEnabled(partToInsert != null);
} else {
if (wire != null) {
wire = null;
repaint();
} else
editAttributes(e);
}
}
@Override
public void mouseEntered(MouseEvent e) {
if (autoPick && partToInsert != null) {
GraphicMinMax minMax = partToInsert.getMinMax();
delta = partToInsert.getPos().sub(minMax.getMax());
Vector pos = getPosVector(e);
partToInsert.setPos(raster(pos.add(delta)));
autoPick = false;
deleteAction.setEnabled(true);
repaint();
}
}
public void setPartToInsert(VisualElement partToInsert) {
this.partToInsert = partToInsert;
insert = true;
autoPick = true;
}
@Override
public void drawTo(Graphic gr) {
if (partToInsert != null && !autoPick)
partToInsert.drawTo(gr, true);
if (wire != null)
wire.drawTo(gr, false);
}
}
private enum State {COPY, MOVE}
private class SelectMouseListener extends Mouse {
private Vector corner1;
private Vector corner2;
private ArrayList<Moveable> elements;
private Vector lastPos;
private State state;
private Vector copyStartPosition;
private boolean wasRealyDragged;
@Override
public void mouseClicked(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1)
reset();
else
editAttributes(e);
}
private void reset() {
corner1 = null;
corner2 = null;
elements = null;
deleteAction.setEnabled(false);
repaint();
}
@Override
public void mousePressed(MouseEvent e) {
if (corner1 == null) {
corner1 = getPosVector(e);
wasRealyDragged = false;
} else {
if (corner2 != null) {
if (e.getButton() == MouseEvent.BUTTON1) {
elements = circuit.getElementsToMove(Vector.min(corner1, corner2), Vector.max(corner1, corner2));
state = State.MOVE;
} else {
elements = circuit.getElementsToCopy(Vector.min(corner1, corner2), Vector.max(corner1, corner2), shapeFactory);
copyStartPosition = raster(getPosVector(e));
state = State.COPY;
}
}
lastPos = getPosVector(e);
}
deleteAction.setEnabled(corner1 != null && corner2 != null);
} }
@Override @Override
public void mouseReleased(MouseEvent e) { public void mouseReleased(MouseEvent e) {
if (elements != null && state == State.COPY && copyStartPosition != null && !copyStartPosition.equals(raster(getPosVector(e)))) { activeMouseController.released(e);
for (Moveable m : elements) { }
if (m instanceof Wire)
circuit.add((Wire) m); @Override
if (m instanceof VisualElement) public void mouseMoved(MouseEvent e) {
circuit.add((VisualElement) m); activeMouseController.moved(e);
}
copyStartPosition = null;
}
if (wasRealyDragged)
reset();
else
deleteAction.setEnabled(corner1 != null && corner2 != null);
} }
@Override @Override
public void mouseDragged(MouseEvent e) { public void mouseDragged(MouseEvent e) {
if (!activeMouseController.dragged(e)) {
Vector newPos = new Vector(e.getX(), e.getY());
Vector delta = newPos.sub(pos);
double s = transform.getScaleX();
transform.translate(delta.x / s, delta.y / s);
pos = newPos;
repaint();
}
}
}
private class MouseController {
private final Cursor mouseCursor;
private MouseController(Cursor mouseCursor) {
this.mouseCursor = mouseCursor;
}
private void activate() {
activeMouseController = this;
deleteAction.setActive(false);
setCursor(mouseCursor);
repaint();
}
void clicked(MouseEvent e) {
}
void pressed(MouseEvent e) {
}
void released(MouseEvent e) {
}
void moved(MouseEvent e) {
}
boolean dragged(MouseEvent e) {
return false;
}
public void drawTo(Graphic gr) {
}
public void delete() {
}
}
private final class MouseControllerNormal extends MouseController {
private Vector pos;
private int downButton;
private MouseControllerNormal(Cursor cursor) {
super(cursor);
}
@Override
void clicked(MouseEvent e) {
Vector pos = getPosVector(e);
VisualElement vp = circuit.getElementAt(pos);
if (e.getButton() == MouseEvent.BUTTON3) {
if (vp != null)
editAttributes(vp, e);
} else if (e.getButton() == MouseEvent.BUTTON1) {
if (vp != null) {
if (circuit.isPinPos(raster(pos), vp))
mouseWire.activate(pos);
else
mouseMoveElement.activate(vp, pos);
} else {
mouseWire.activate(pos);
}
}
}
@Override
void pressed(MouseEvent e) {
downButton = e.getButton();
pos = getPosVector(e);
}
@Override
boolean dragged(MouseEvent e) {
if (downButton == MouseEvent.BUTTON3) {
mouseSelect.activate(pos, getPosVector(e));
return true;
}
return false;
}
}
private final class MouseControllerInsertElement extends MouseController {
private VisualElement element;
private Vector delta;
private MouseControllerInsertElement(Cursor cursor) {
super(cursor);
}
private void activate(VisualElement element) {
super.activate();
this.element = element;
delta = null;
deleteAction.setActive(true);
}
@Override
void moved(MouseEvent e) {
if (delta == null) {
GraphicMinMax minMax = element.getMinMax();
delta = element.getPos().sub(minMax.getMax());
}
element.setPos(raster(getPosVector(e).add(delta)));
repaint();
}
@Override
public void delete() {
mouseNormal.activate();
}
@Override
public void drawTo(Graphic gr) {
if (delta != null)
element.drawTo(gr, true);
}
@Override
void clicked(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
circuit.add(element);
repaint();
}
mouseNormal.activate();
}
}
private final class MouseControllerMoveElement extends MouseController {
private VisualElement visualElement;
private Vector delta;
private MouseControllerMoveElement(Cursor cursor) {
super(cursor);
}
private void activate(VisualElement visualElement, Vector pos) {
super.activate();
this.visualElement = visualElement;
delta = visualElement.getPos().sub(pos);
deleteAction.setActive(true);
repaint();
}
@Override
void clicked(MouseEvent e) {
visualElement.setPos(raster(visualElement.getPos()));
mouseNormal.activate();
}
@Override
void moved(MouseEvent e) {
Vector pos = getPosVector(e);
visualElement.setPos(raster(pos.add(delta)));
repaint();
}
@Override
public void drawTo(Graphic gr) {
visualElement.drawTo(gr, true);
}
@Override
public void delete() {
circuit.delete(visualElement);
mouseNormal.activate();
}
}
private final class MouseControllerWire extends MouseController {
private Wire wire;
private MouseControllerWire(Cursor cursor) {
super(cursor);
}
private void activate(Vector startPos) {
super.activate();
Vector pos = raster(startPos);
wire = new Wire(pos, pos);
}
@Override
void moved(MouseEvent e) {
wire.setP2(raster(getPosVector(e)));
repaint();
}
@Override
void clicked(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON3)
mouseNormal.activate();
else {
circuit.add(wire);
if (circuit.isPinPos(wire.p2))
mouseNormal.activate();
else
wire = new Wire(wire.p2, wire.p2);
}
}
@Override
public void drawTo(Graphic gr) {
wire.drawTo(gr, false);
}
}
private final class MouseControllerSelect extends MouseController {
private Vector corner1;
private Vector corner2;
private int downButton;
private boolean wasReleased;
private MouseControllerSelect(Cursor cursor) {
super(cursor);
}
private void activate(Vector corner1, Vector corner2) {
super.activate();
this.corner1 = corner1;
this.corner2 = corner2;
deleteAction.setActive(true);
wasReleased = false;
}
@Override
void clicked(MouseEvent e) {
mouseNormal.activate();
}
@Override
void pressed(MouseEvent e) {
downButton = e.getButton();
}
@Override
void released(MouseEvent e) {
wasReleased = true;
}
@Override
boolean dragged(MouseEvent e) {
if (wasReleased) {
if (downButton == MouseEvent.BUTTON1)
mouseMoveSelected.activate(corner1, corner2, getPosVector(e));
else if (downButton == MouseEvent.BUTTON3)
mouseCopySelected.activate(corner1, corner2, getPosVector(e));
} else {
corner2 = getPosVector(e);
repaint();
}
return true;
}
@Override
public void drawTo(Graphic gr) {
Vector p1 = new Vector(corner1.x, corner2.y);
Vector p2 = new Vector(corner2.x, corner1.y);
gr.drawLine(corner1, p1, Style.DASH);
gr.drawLine(p1, corner2, Style.DASH);
gr.drawLine(corner2, p2, Style.DASH);
gr.drawLine(p2, corner1, Style.DASH);
}
@Override
public void delete() {
circuit.delete(Vector.min(corner1, corner2), Vector.max(corner1, corner2));
mouseNormal.activate();
}
}
private final class MouseControllerMoveSelected extends MouseController {
private ArrayList<Moveable> elements;
private Vector lastPos;
private MouseControllerMoveSelected(Cursor cursor) {
super(cursor);
}
private void activate(Vector corner1, Vector corner2, Vector pos) {
super.activate();
lastPos = pos;
elements = circuit.getElementsToMove(Vector.min(corner1, corner2), Vector.max(corner1, corner2));
}
@Override
boolean dragged(MouseEvent e) {
if (elements != null) { if (elements != null) {
Vector pos = getPosVector(e); Vector pos = getPosVector(e);
Vector delta = raster(pos.sub(lastPos)); Vector delta = raster(pos.sub(lastPos));
@ -453,43 +622,90 @@ public class CircuitComponent extends JComponent {
m.move(delta); m.move(delta);
circuit.modified(); circuit.modified();
corner1.move(delta);
corner2.move(delta);
repaint(); repaint();
lastPos = lastPos.add(delta); lastPos = lastPos.add(delta);
wasRealyDragged = true;
} }
} else {
corner2 = getPosVector(e);
repaint();
} }
return true;
}
@Override
void released(MouseEvent e) {
mouseNormal.activate();
}
}
private final class MouseControllerCopySelected extends MouseController {
private ArrayList<Moveable> elements;
private Vector lastPos;
private Vector movement;
private MouseControllerCopySelected(Cursor cursor) {
super(cursor);
}
private void activate(Vector corner1, Vector corner2, Vector pos) {
super.activate();
lastPos = pos;
movement = new Vector(0, 0);
deleteAction.setActive(true);
elements = circuit.getElementsToCopy(Vector.min(corner1, corner2), Vector.max(corner1, corner2), shapeFactory);
}
@Override
boolean dragged(MouseEvent e) {
if (elements != null) {
Vector pos = getPosVector(e);
Vector delta = raster(pos.sub(lastPos));
if (delta.x != 0 || delta.y != 0) {
for (Moveable m : elements)
m.move(delta);
movement = movement.add(delta);
repaint();
lastPos = lastPos.add(delta);
}
}
return true;
} }
@Override @Override
public void drawTo(Graphic gr) { public void drawTo(Graphic gr) {
if (corner1 != null && corner2 != null) { if (elements != null)
Vector p1 = new Vector(corner1.x, corner2.y);
Vector p2 = new Vector(corner2.x, corner1.y);
gr.drawLine(corner1, p1, Style.DASH);
gr.drawLine(p1, corner2, Style.DASH);
gr.drawLine(corner2, p2, Style.DASH);
gr.drawLine(p2, corner1, Style.DASH);
}
if (state == State.COPY && elements != null)
for (Moveable m : elements) for (Moveable m : elements)
if (m instanceof Drawable) if (m instanceof Drawable)
((Drawable) m).drawTo(gr, true); ((Drawable) m).drawTo(gr, true);
} }
}
private class RunningMouseListener extends Mouse {
@Override @Override
public void drawTo(Graphic gr) { public void delete() {
mouseNormal.activate();
} }
@Override @Override
public void mouseClicked(MouseEvent e) { void released(MouseEvent e) {
if (elements != null && !movement.isZero()) {
for (Moveable m : elements) {
if (m instanceof Wire)
circuit.add((Wire) m);
if (m instanceof VisualElement)
circuit.add((VisualElement) m);
}
}
mouseNormal.activate();
}
}
private final class MouseControllerRun extends MouseController {
private MouseControllerRun(Cursor cursor) {
super(cursor);
}
@Override
void clicked(MouseEvent e) {
VisualElement ve = circuit.getElementAt(getPosVector(e)); VisualElement ve = circuit.getElementAt(getPosVector(e));
if (ve != null) { if (ve != null) {
Point p = new Point(e.getX(), e.getY()); Point p = new Point(e.getX(), e.getY());