mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-12 14:26:09 -04:00
Allows to select the angle at which the init state marker is drawn with the mouse.
This commit is contained in:
parent
4e83b437d8
commit
45e0d68168
@ -301,7 +301,7 @@ public class FSM {
|
||||
* @param dt the time step
|
||||
* @param except element which is fixed
|
||||
*/
|
||||
public void move(int dt, Movable except) {
|
||||
public void move(int dt, MouseMovable except) {
|
||||
if (state != MovingState.STOP) {
|
||||
calculateForces();
|
||||
if (state == MovingState.BOTH)
|
||||
@ -377,8 +377,8 @@ public class FSM {
|
||||
* @param pos the position
|
||||
* @return the element or null
|
||||
*/
|
||||
public Movable getMovable(Vector pos) {
|
||||
Movable found = null;
|
||||
public MouseMovable getMovable(Vector pos) {
|
||||
Movable<?> found = null;
|
||||
float dist = Float.MAX_VALUE;
|
||||
for (Transition t : transitions)
|
||||
if (t.matches(pos)) {
|
||||
@ -400,7 +400,8 @@ public class FSM {
|
||||
dist = d;
|
||||
found = s;
|
||||
}
|
||||
}
|
||||
} else if (s.matchesInitial(pos))
|
||||
return s.getInitialMarkerMovable();
|
||||
|
||||
return found;
|
||||
}
|
||||
@ -439,7 +440,7 @@ public class FSM {
|
||||
* @param movable the element changed
|
||||
* @param prop the property which has changed
|
||||
*/
|
||||
void wasModified(Movable movable, Movable.Property prop) {
|
||||
void wasModified(Movable<?> movable, Movable.Property prop) {
|
||||
modified = true;
|
||||
|
||||
if (movable instanceof State) {
|
||||
|
35
src/main/java/de/neemann/digital/fsm/MouseMovable.java
Normal file
35
src/main/java/de/neemann/digital/fsm/MouseMovable.java
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2020 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.fsm;
|
||||
|
||||
import de.neemann.digital.draw.graphics.VectorFloat;
|
||||
import de.neemann.digital.draw.graphics.VectorInterface;
|
||||
|
||||
/**
|
||||
* Element which can be moved by the mouse
|
||||
*/
|
||||
public interface MouseMovable {
|
||||
/**
|
||||
* @return the position
|
||||
*/
|
||||
VectorInterface getPos();
|
||||
|
||||
/**
|
||||
* Sets the position by the mouse.
|
||||
* Is called while dragging.
|
||||
*
|
||||
* @param pos the position
|
||||
*/
|
||||
void setPosByMouse(VectorFloat pos);
|
||||
|
||||
/**
|
||||
* Sets the position by the mouse.
|
||||
* Is called if mouse button is released.
|
||||
*
|
||||
* @param pos the position
|
||||
*/
|
||||
void setPos(VectorFloat pos);
|
||||
}
|
@ -12,9 +12,9 @@ import de.neemann.digital.draw.graphics.VectorFloat;
|
||||
*
|
||||
* @param <A> the type of the implementing class
|
||||
*/
|
||||
public class Movable<A extends Movable> {
|
||||
public class Movable<A extends Movable<?>> implements MouseMovable {
|
||||
|
||||
enum Property {POS, REMOVED, CONDITION, NAME, NUMBER, MOUSEPOS, VALUES, INITIAL, ADDED}
|
||||
enum Property {POS, REMOVED, CONDITION, NAME, NUMBER, MOUSEPOS, VALUES, INITIAL, ADDED, INITIAL_ANGLE}
|
||||
|
||||
private static final float MASS = 50f;
|
||||
private static final float FRICTION = 0.8f;
|
||||
|
@ -99,9 +99,7 @@ public class State extends Movable<State> {
|
||||
|
||||
if (isInitial) {
|
||||
Vector initRad = new Vector(INIT_RAD, INIT_RAD);
|
||||
int r = radius + INIT_RAD * 6;
|
||||
double angle = 2 * Math.PI / 32 * initialAngle;
|
||||
VectorInterface pos = getPos().add(new VectorFloat((float) (Math.cos(angle) * r), -(float) (Math.sin(angle) * r)));
|
||||
VectorInterface pos = getInitialMarkerPos();
|
||||
gr.drawCircle(pos.sub(initRad), pos.add(initRad), Style.FILLED);
|
||||
VectorInterface delta = getPos().sub(pos).norm();
|
||||
VectorInterface a0 = pos.add(delta.mul(INIT_RAD + Style.FILLED.getThickness()));
|
||||
@ -122,6 +120,15 @@ public class State extends Movable<State> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the initial marker position
|
||||
*/
|
||||
VectorInterface getInitialMarkerPos() {
|
||||
int r = radius + INIT_RAD * 6;
|
||||
double angle = 2 * Math.PI / 32 * initialAngle;
|
||||
return getPos().add(new VectorFloat((float) (Math.cos(angle) * r), -(float) (Math.sin(angle) * r)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the radius of the state
|
||||
*/
|
||||
@ -176,6 +183,18 @@ public class State extends Movable<State> {
|
||||
return pos.sub(getPos()).len() <= radius;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the position matches the states initial marker
|
||||
*
|
||||
* @param pos the position
|
||||
* @return true if pos inside of the states initial marker
|
||||
*/
|
||||
public boolean matchesInitial(Vector pos) {
|
||||
if (!isInitial)
|
||||
return false;
|
||||
return pos.sub(getInitialMarkerPos()).len() <= INIT_RAD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (name != null && name.length() > 0)
|
||||
@ -221,18 +240,31 @@ public class State extends Movable<State> {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the angle of the initial marker
|
||||
* @return a movable that represents the initial marker.
|
||||
*/
|
||||
public int getInitialAngle() {
|
||||
return initialAngle;
|
||||
}
|
||||
public MouseMovable getInitialMarkerMovable() {
|
||||
return new MouseMovable() {
|
||||
@Override
|
||||
public VectorInterface getPos() {
|
||||
return getInitialMarkerPos();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the angle of the initial marker
|
||||
*
|
||||
* @param angle the angle
|
||||
*/
|
||||
public void setInitialAngle(Integer angle) {
|
||||
initialAngle = angle;
|
||||
@Override
|
||||
public void setPosByMouse(VectorFloat pos) {
|
||||
VectorInterface delta = pos.sub(State.this.getPos());
|
||||
double angle = Math.atan2(-delta.getYFloat(), delta.getXFloat()) / Math.PI * 16;
|
||||
if (angle < 0)
|
||||
angle += 32;
|
||||
int ia = (int) Math.round(angle);
|
||||
if (initialAngle != ia) {
|
||||
initialAngle = ia;
|
||||
wasModified(Property.INITIAL_ANGLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPos(VectorFloat pos) {
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -10,10 +10,7 @@ import de.neemann.digital.core.element.Key;
|
||||
import de.neemann.digital.core.element.Keys;
|
||||
import de.neemann.digital.draw.graphics.*;
|
||||
import de.neemann.digital.draw.graphics.Polygon;
|
||||
import de.neemann.digital.fsm.FSM;
|
||||
import de.neemann.digital.fsm.Movable;
|
||||
import de.neemann.digital.fsm.State;
|
||||
import de.neemann.digital.fsm.Transition;
|
||||
import de.neemann.digital.fsm.*;
|
||||
import de.neemann.digital.gui.components.AttributeDialog;
|
||||
import de.neemann.digital.lang.Lang;
|
||||
import de.neemann.gui.Mouse;
|
||||
@ -34,12 +31,6 @@ import static de.neemann.digital.gui.components.CircuitComponent.ICON_DELETE;
|
||||
public class FSMComponent extends JComponent {
|
||||
private static final Key<Integer> KEY_NUMBER = new Key.KeyInteger("stateNum", 0);
|
||||
private static final Key<Boolean> KEY_INITIAL = new Key<>("isInitialState", false);
|
||||
private static final Key<Integer> KEY_INITIAL_ANGLE = new Key.KeyInteger("initialAngle", 12)
|
||||
.setComboBoxValues(4, 12, 20, 28)
|
||||
.setMin(0)
|
||||
.setMax(31)
|
||||
.setDependsOn(KEY_INITIAL)
|
||||
.setSecondary();
|
||||
private static final Key<String> KEY_VALUES = new Key<>("stateValues", "");
|
||||
private static final Key<String> KEY_CONDITION = new Key<>("transCond", "");
|
||||
private static final Key<Integer> KEY_RADIUS = new Key.KeyInteger("transRad", 70)
|
||||
@ -51,7 +42,7 @@ public class FSMComponent extends JComponent {
|
||||
|
||||
private boolean isManualScale;
|
||||
private AffineTransform transform = new AffineTransform();
|
||||
private Movable<?> elementMoved;
|
||||
private MouseMovable elementMoved;
|
||||
private FSM fsm;
|
||||
private Vector lastMousePos;
|
||||
private State newTransitionFromState;
|
||||
@ -87,7 +78,7 @@ public class FSMComponent extends JComponent {
|
||||
if (elementMoved != null)
|
||||
delta = posVector.sub(elementMoved.getPos());
|
||||
} else if (mouse.isSecondaryClick(e)) {
|
||||
Movable<?> st = fsm.getMovable(posVector);
|
||||
MouseMovable st = fsm.getMovable(posVector);
|
||||
if (st instanceof State) {
|
||||
newTransitionStartPos = posVector;
|
||||
newTransitionFromState = (State) st;
|
||||
@ -107,7 +98,7 @@ public class FSMComponent extends JComponent {
|
||||
if (newTransitionFromState != null) {
|
||||
final Vector posVector = getPosVector(mouseEvent);
|
||||
if (newTransitionStartPos.sub(posVector).len() > MIN_NEW_TRANS_DIST) {
|
||||
Movable<?> target = fsm.getMovable(posVector);
|
||||
MouseMovable target = fsm.getMovable(posVector);
|
||||
if (target instanceof State)
|
||||
fsm.add(new Transition(newTransitionFromState, (State) target, lastCondition));
|
||||
}
|
||||
@ -119,7 +110,7 @@ public class FSMComponent extends JComponent {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent mouseEvent) {
|
||||
final Vector posVector = getPosVector(mouseEvent);
|
||||
Movable<?> elementClicked = fsm.getMovable(posVector);
|
||||
MouseMovable elementClicked = fsm.getMovable(posVector);
|
||||
if (mouse.isSecondaryClick(mouseEvent)) {
|
||||
if (elementClicked == null)
|
||||
createNewState(posVector, new Point(mouseEvent.getX(), mouseEvent.getY()));
|
||||
@ -161,7 +152,7 @@ public class FSMComponent extends JComponent {
|
||||
ToolTipAction deleteAction = new ToolTipAction(Lang.get("menu_delete"), ICON_DELETE) {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
Movable<?> element = fsm.getMovable(lastMousePos);
|
||||
MouseMovable element = fsm.getMovable(lastMousePos);
|
||||
if (element instanceof State) {
|
||||
fsm.remove((State) element);
|
||||
repaint();
|
||||
@ -188,7 +179,7 @@ public class FSMComponent extends JComponent {
|
||||
setPreferredSize(new Dimension(600, 600));
|
||||
}
|
||||
|
||||
private static final Key<?>[] STATE_EDIT_KEYS = {Keys.LABEL, KEY_NUMBER, KEY_INITIAL, KEY_INITIAL_ANGLE, KEY_VALUES, KEY_RADIUS};
|
||||
private static final Key<?>[] STATE_EDIT_KEYS = {Keys.LABEL, KEY_NUMBER, KEY_INITIAL, KEY_VALUES, KEY_RADIUS};
|
||||
|
||||
private void createNewState(Vector posVector, Point point) {
|
||||
ElementAttributes attr = new ElementAttributes();
|
||||
@ -216,7 +207,6 @@ public class FSMComponent extends JComponent {
|
||||
ElementAttributes attr = new ElementAttributes()
|
||||
.set(KEY_NUMBER, state.getNumber())
|
||||
.set(KEY_INITIAL, state.isInitial())
|
||||
.set(KEY_INITIAL_ANGLE, state.getInitialAngle())
|
||||
.set(KEY_VALUES, state.getValues())
|
||||
.set(KEY_RADIUS, state.getVisualRadius())
|
||||
.set(Keys.LABEL, state.getName());
|
||||
@ -228,7 +218,6 @@ public class FSMComponent extends JComponent {
|
||||
if (newAttr != null) {
|
||||
state.setNumber(newAttr.get(KEY_NUMBER));
|
||||
state.setInitial(newAttr.get(KEY_INITIAL));
|
||||
state.setInitialAngle(newAttr.get(KEY_INITIAL_ANGLE));
|
||||
state.setValues(newAttr.get(KEY_VALUES));
|
||||
state.setRadius(newAttr.get(KEY_RADIUS));
|
||||
state.setName(newAttr.get(Keys.LABEL));
|
||||
@ -318,7 +307,7 @@ public class FSMComponent extends JComponent {
|
||||
/**
|
||||
* @return the element picked by the mouse
|
||||
*/
|
||||
Movable<?> getElementMoved() {
|
||||
MouseMovable getElementMoved() {
|
||||
return elementMoved;
|
||||
}
|
||||
|
||||
|
@ -2080,10 +2080,6 @@ Daher steht auch das Signal 'D_out' zur Verfügung, um in diesem Fall den Wert z
|
||||
<string name="key_isInitialState_tt">Wenn gesetzt, ist dies der Initialzustand, in welchem der Automat gestartet
|
||||
wird.
|
||||
</string>
|
||||
<string name="key_initialAngle">Winkel Initial-Marker</string>
|
||||
<string name="key_initialAngle_tt">Winkel bei dem der Marker des Initialzustandes gezeichnet werden soll.
|
||||
Ist ein Wert zwischen 0 und 31.
|
||||
</string>
|
||||
<string name="key_stateValues">Ausgänge</string>
|
||||
<string name="key_stateValues_tt">Legt Ausgangswerte fest.
|
||||
Mit einfachen Zuweisungen wie "A=1, B=0" können Ausgänge gesetzt werden.
|
||||
|
@ -2035,10 +2035,6 @@ Therefore, the signal 'D_out' is also available to check the value in this case.
|
||||
<string name="key_stateNum_tt">The number which represents this state.</string>
|
||||
<string name="key_isInitialState">Initial State</string>
|
||||
<string name="key_isInitialState_tt">If set, this state is the initial state.</string>
|
||||
<string name="key_initialAngle">Angle Initial Marker</string>
|
||||
<string name="key_initialAngle_tt">Angle at which the marker of the initial state should be drawn.
|
||||
Is a value between 0 and 31.
|
||||
</string>
|
||||
<string name="key_stateValues">Outputs</string>
|
||||
<string name="key_stateValues_tt">Defines the output values.
|
||||
With simple assignments like "A=1, B=0" outputs can be set.
|
||||
|
Loading…
x
Reference in New Issue
Block a user