mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-10 05:15:51 -04:00
a rough fsm editor is working
This commit is contained in:
parent
66a11ff89a
commit
c6f1b5ce13
@ -146,4 +146,13 @@ public class VectorFloat implements VectorInterface {
|
|||||||
public VectorFloat toFloat() {
|
public VectorFloat toFloat() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates vector which is orthogonal to this one.
|
||||||
|
*
|
||||||
|
* @return the orthogonal vector
|
||||||
|
*/
|
||||||
|
public VectorFloat getOrthogonal() {
|
||||||
|
return new VectorFloat(y, -x);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
*/
|
*/
|
||||||
package de.neemann.digital.fsm;
|
package de.neemann.digital.fsm;
|
||||||
|
|
||||||
|
import com.thoughtworks.xstream.XStream;
|
||||||
|
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
|
||||||
|
import com.thoughtworks.xstream.io.xml.StaxDriver;
|
||||||
import de.neemann.digital.analyse.TruthTable;
|
import de.neemann.digital.analyse.TruthTable;
|
||||||
import de.neemann.digital.analyse.expression.ExpressionException;
|
import de.neemann.digital.analyse.expression.ExpressionException;
|
||||||
import de.neemann.digital.draw.graphics.Graphic;
|
import de.neemann.digital.draw.graphics.Graphic;
|
||||||
@ -12,6 +15,7 @@ import de.neemann.digital.draw.graphics.Vector;
|
|||||||
import de.neemann.digital.draw.graphics.VectorFloat;
|
import de.neemann.digital.draw.graphics.VectorFloat;
|
||||||
import de.neemann.digital.lang.Lang;
|
import de.neemann.digital.lang.Lang;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -23,6 +27,89 @@ public class FSM {
|
|||||||
private ArrayList<State> states;
|
private ArrayList<State> states;
|
||||||
private ArrayList<Transition> transitions;
|
private ArrayList<Transition> transitions;
|
||||||
private transient boolean initChecked;
|
private transient boolean initChecked;
|
||||||
|
private transient boolean modified;
|
||||||
|
private transient ModifiedListener modifiedListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a proper configured XStream instance
|
||||||
|
*
|
||||||
|
* @return the XStream instance
|
||||||
|
*/
|
||||||
|
public static XStream getxStream() {
|
||||||
|
XStream xStream = new XStream(new StaxDriver());
|
||||||
|
xStream.alias("fsm", FSM.class);
|
||||||
|
xStream.alias("state", State.class);
|
||||||
|
xStream.alias("transition", Transition.class);
|
||||||
|
xStream.alias("vector", Vector.class);
|
||||||
|
xStream.aliasAttribute(Vector.class, "x", "x");
|
||||||
|
xStream.aliasAttribute(Vector.class, "y", "y");
|
||||||
|
xStream.alias("vectorf", VectorFloat.class);
|
||||||
|
xStream.aliasAttribute(VectorFloat.class, "x", "x");
|
||||||
|
xStream.aliasAttribute(VectorFloat.class, "y", "y");
|
||||||
|
return xStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new circuit instance from a stored file
|
||||||
|
*
|
||||||
|
* @param filename filename
|
||||||
|
* @return the fsm
|
||||||
|
* @throws IOException IOException
|
||||||
|
*/
|
||||||
|
public static FSM loadFSM(File filename) throws IOException {
|
||||||
|
return loadFSM(new FileInputStream(filename));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new fsm instance from a stored file
|
||||||
|
*
|
||||||
|
* @param in the input stream
|
||||||
|
* @return the fsm
|
||||||
|
* @throws IOException IOException
|
||||||
|
*/
|
||||||
|
public static FSM loadFSM(InputStream in) throws IOException {
|
||||||
|
try {
|
||||||
|
XStream xStream = getxStream();
|
||||||
|
final FSM fsm = (FSM) xStream.fromXML(in);
|
||||||
|
for (Transition t : fsm.transitions)
|
||||||
|
t.setFSM(fsm);
|
||||||
|
for (State s : fsm.states)
|
||||||
|
s.setFSM(fsm);
|
||||||
|
fsm.modified = false;
|
||||||
|
return fsm;
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
throw new IOException(Lang.get("err_invalidFileFormat"), e);
|
||||||
|
} finally {
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the fsm in the given file
|
||||||
|
*
|
||||||
|
* @param filename filename
|
||||||
|
* @throws IOException IOException
|
||||||
|
*/
|
||||||
|
public void save(File filename) throws IOException {
|
||||||
|
save(new FileOutputStream(filename));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the circuit in the given file
|
||||||
|
*
|
||||||
|
* @param out the writer
|
||||||
|
* @throws IOException IOException
|
||||||
|
*/
|
||||||
|
public void save(OutputStream out) throws IOException {
|
||||||
|
try (Writer w = new OutputStreamWriter(out, "utf-8")) {
|
||||||
|
XStream xStream = getxStream();
|
||||||
|
w.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
|
||||||
|
xStream.marshal(this, new PrettyPrintWriter(w));
|
||||||
|
modified = false;
|
||||||
|
if (modifiedListener != null)
|
||||||
|
modifiedListener.modifiedChanged(modified);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new FSM containing the given states
|
* Creates a new FSM containing the given states
|
||||||
@ -45,6 +132,7 @@ public class FSM {
|
|||||||
public FSM add(State state) {
|
public FSM add(State state) {
|
||||||
if (state.getNumber() < 0)
|
if (state.getNumber() < 0)
|
||||||
state.setNumber(states.size());
|
state.setNumber(states.size());
|
||||||
|
state.setFSM(this);
|
||||||
states.add(state);
|
states.add(state);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -57,6 +145,7 @@ public class FSM {
|
|||||||
*/
|
*/
|
||||||
public FSM add(Transition transition) {
|
public FSM add(Transition transition) {
|
||||||
transitions.add(transition);
|
transitions.add(transition);
|
||||||
|
transition.setFSM(this);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,9 +185,9 @@ public class FSM {
|
|||||||
*/
|
*/
|
||||||
public FSM transition(State from, State to, String condition) {
|
public FSM transition(State from, State to, String condition) {
|
||||||
if (!states.contains(from))
|
if (!states.contains(from))
|
||||||
states.add(from);
|
add(from);
|
||||||
if (!states.contains(to))
|
if (!states.contains(to))
|
||||||
states.add(to);
|
add(to);
|
||||||
return add(new Transition(from, to, condition));
|
return add(new Transition(from, to, condition));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,8 +279,10 @@ public class FSM {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Orders all states in a big circle
|
* Orders all states in a big circle
|
||||||
|
*
|
||||||
|
* @return this for chained calls
|
||||||
*/
|
*/
|
||||||
public void circle() {
|
public FSM circle() {
|
||||||
double delta = 2 * Math.PI / states.size();
|
double delta = 2 * Math.PI / states.size();
|
||||||
double rad = 0;
|
double rad = 0;
|
||||||
for (State s : states)
|
for (State s : states)
|
||||||
@ -207,6 +298,8 @@ public class FSM {
|
|||||||
|
|
||||||
for (Transition t : transitions)
|
for (Transition t : transitions)
|
||||||
t.initPos();
|
t.initPos();
|
||||||
|
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -260,6 +353,7 @@ public class FSM {
|
|||||||
*/
|
*/
|
||||||
public void remove(Transition transition) {
|
public void remove(Transition transition) {
|
||||||
transitions.remove(transition);
|
transitions.remove(transition);
|
||||||
|
wasModified();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -270,5 +364,43 @@ public class FSM {
|
|||||||
public void remove(State state) {
|
public void remove(State state) {
|
||||||
states.remove(state);
|
states.remove(state);
|
||||||
transitions.removeIf(t -> t.getStartState() == state || t.getTargetState() == state);
|
transitions.removeIf(t -> t.getStartState() == state || t.getTargetState() == state);
|
||||||
|
wasModified();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks the fsm as modified
|
||||||
|
*/
|
||||||
|
void wasModified() {
|
||||||
|
modified = true;
|
||||||
|
if (modifiedListener != null)
|
||||||
|
modifiedListener.modifiedChanged(modified);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a modified listener
|
||||||
|
*
|
||||||
|
* @param modifiedListener the listener called if fsm was modified
|
||||||
|
*/
|
||||||
|
public void setModifiedListener(ModifiedListener modifiedListener) {
|
||||||
|
this.modifiedListener = modifiedListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if fsm has changed
|
||||||
|
*/
|
||||||
|
public boolean hasChanged() {
|
||||||
|
return modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* a modified listener
|
||||||
|
*/
|
||||||
|
public interface ModifiedListener {
|
||||||
|
/**
|
||||||
|
* called if fsm was modified
|
||||||
|
*
|
||||||
|
* @param wasModified true is fsm is modified
|
||||||
|
*/
|
||||||
|
void modifiedChanged(boolean wasModified);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,9 @@ import de.neemann.digital.draw.graphics.VectorFloat;
|
|||||||
*/
|
*/
|
||||||
public class Movable {
|
public class Movable {
|
||||||
private VectorFloat position;
|
private VectorFloat position;
|
||||||
private VectorFloat speed;
|
private transient VectorFloat speed;
|
||||||
private VectorFloat force;
|
private transient VectorFloat force;
|
||||||
|
private transient FSM fsm;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Creates a new instance
|
||||||
@ -30,7 +31,15 @@ public class Movable {
|
|||||||
* @param position the position
|
* @param position the position
|
||||||
*/
|
*/
|
||||||
public void setPos(VectorFloat position) {
|
public void setPos(VectorFloat position) {
|
||||||
|
if (!this.position.equals(position)) {
|
||||||
this.position = position;
|
this.position = position;
|
||||||
|
wasModified();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wasModified() {
|
||||||
|
if (fsm != null)
|
||||||
|
fsm.wasModified();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -39,6 +48,9 @@ public class Movable {
|
|||||||
* @param df the force to add
|
* @param df the force to add
|
||||||
*/
|
*/
|
||||||
public void addToForce(VectorFloat df) {
|
public void addToForce(VectorFloat df) {
|
||||||
|
if (force == null)
|
||||||
|
force = df;
|
||||||
|
else
|
||||||
force = force.add(df);
|
force = force.add(df);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,6 +104,8 @@ public class Movable {
|
|||||||
* @return the force
|
* @return the force
|
||||||
*/
|
*/
|
||||||
public VectorFloat getForce() {
|
public VectorFloat getForce() {
|
||||||
|
if (force == null)
|
||||||
|
resetForce();
|
||||||
return force;
|
return force;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,9 +129,19 @@ public class Movable {
|
|||||||
* @param dt the time step
|
* @param dt the time step
|
||||||
*/
|
*/
|
||||||
public void move(int dt) {
|
public void move(int dt) {
|
||||||
|
if (speed == null)
|
||||||
|
speed = force.mul(dt / 200f);
|
||||||
|
else
|
||||||
speed = speed.add(force.mul(dt / 200f));
|
speed = speed.add(force.mul(dt / 200f));
|
||||||
setPos(position.add(speed.mul(dt / 1000f)));
|
setPos(position.add(speed.mul(dt / 1000f)));
|
||||||
speed = speed.mul(0.7f);
|
speed = speed.mul(0.7f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setFSM(FSM fsm) {
|
||||||
|
this.fsm = fsm;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSM getFsm() {
|
||||||
|
return fsm;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,8 +47,11 @@ public class State extends Movable {
|
|||||||
* @return this for chained calls
|
* @return this for chained calls
|
||||||
*/
|
*/
|
||||||
public State setValues(String values) {
|
public State setValues(String values) {
|
||||||
|
if (!this.values.equals(values)) {
|
||||||
this.values = values;
|
this.values = values;
|
||||||
valueMap = null;
|
valueMap = null;
|
||||||
|
wasModified();
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +103,10 @@ public class State extends Movable {
|
|||||||
* @param name the name to set
|
* @param name the name to set
|
||||||
*/
|
*/
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
|
if (!this.name.equals(name)) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
wasModified();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -172,7 +178,10 @@ public class State extends Movable {
|
|||||||
* @return this for chained calls
|
* @return this for chained calls
|
||||||
*/
|
*/
|
||||||
public State setNumber(int number) {
|
public State setNumber(int number) {
|
||||||
|
if (this.number!=number) {
|
||||||
this.number = number;
|
this.number = number;
|
||||||
|
wasModified();
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ public class Transition extends Movable {
|
|||||||
if (fromState != toState) {
|
if (fromState != toState) {
|
||||||
VectorFloat dist = fromState.getPos().sub(toState.getPos());
|
VectorFloat dist = fromState.getPos().sub(toState.getPos());
|
||||||
VectorFloat p = position.sub(fromState.getPos());
|
VectorFloat p = position.sub(fromState.getPos());
|
||||||
VectorFloat n = new VectorFloat(dist.getYFloat(), -dist.getXFloat()).norm();
|
VectorFloat n = dist.getOrthogonal().norm();
|
||||||
float l = p.mul(n);
|
float l = p.mul(n);
|
||||||
super.setPos(fromState.getPos().sub(dist.mul(0.5f)).add(n.mul(l)));
|
super.setPos(fromState.getPos().sub(dist.mul(0.5f)).add(n.mul(l)));
|
||||||
} else
|
} else
|
||||||
@ -132,7 +132,7 @@ public class Transition extends Movable {
|
|||||||
gr.drawPolygon(p, arrowStyle);
|
gr.drawPolygon(p, arrowStyle);
|
||||||
|
|
||||||
// arrow
|
// arrow
|
||||||
VectorFloat lot = new VectorFloat(difTo.getYFloat(), -difTo.getXFloat()).mul(0.5f);
|
VectorFloat lot = difTo.getOrthogonal().mul(0.5f);
|
||||||
gr.drawPolygon(new Polygon(false)
|
gr.drawPolygon(new Polygon(false)
|
||||||
.add(end.add(difTo.add(lot).mul(0.2f)))
|
.add(end.add(difTo.add(lot).mul(0.2f)))
|
||||||
.add(arrowTip)
|
.add(arrowTip)
|
||||||
@ -156,9 +156,12 @@ public class Transition extends Movable {
|
|||||||
* @param condition the condition
|
* @param condition the condition
|
||||||
*/
|
*/
|
||||||
public void setCondition(String condition) {
|
public void setCondition(String condition) {
|
||||||
|
if (!this.condition.equals(condition)) {
|
||||||
this.condition = condition;
|
this.condition = condition;
|
||||||
|
wasModified();
|
||||||
conditionExpression = null;
|
conditionExpression = null;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return returns the condition
|
* @return returns the condition
|
||||||
|
@ -8,10 +8,8 @@ package de.neemann.digital.fsm.gui;
|
|||||||
import de.neemann.digital.core.element.ElementAttributes;
|
import de.neemann.digital.core.element.ElementAttributes;
|
||||||
import de.neemann.digital.core.element.Key;
|
import de.neemann.digital.core.element.Key;
|
||||||
import de.neemann.digital.core.element.Keys;
|
import de.neemann.digital.core.element.Keys;
|
||||||
import de.neemann.digital.draw.graphics.GraphicMinMax;
|
import de.neemann.digital.draw.graphics.*;
|
||||||
import de.neemann.digital.draw.graphics.GraphicSwing;
|
import de.neemann.digital.draw.graphics.Polygon;
|
||||||
import de.neemann.digital.draw.graphics.Style;
|
|
||||||
import de.neemann.digital.draw.graphics.Vector;
|
|
||||||
import de.neemann.digital.fsm.FSM;
|
import de.neemann.digital.fsm.FSM;
|
||||||
import de.neemann.digital.fsm.Movable;
|
import de.neemann.digital.fsm.Movable;
|
||||||
import de.neemann.digital.fsm.State;
|
import de.neemann.digital.fsm.State;
|
||||||
@ -50,14 +48,8 @@ public class FSMComponent extends JComponent {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new component
|
* Creates a new component
|
||||||
*
|
|
||||||
* @param fsm the fsm to visualize
|
|
||||||
*/
|
*/
|
||||||
public FSMComponent(FSM fsm) {
|
public FSMComponent() {
|
||||||
this.fsm = fsm;
|
|
||||||
|
|
||||||
fsm.circle();
|
|
||||||
|
|
||||||
addMouseWheelListener(e -> {
|
addMouseWheelListener(e -> {
|
||||||
Vector pos = getPosVector(e);
|
Vector pos = getPosVector(e);
|
||||||
double f = Math.pow(0.9, e.getWheelRotation());
|
double f = Math.pow(0.9, e.getWheelRotation());
|
||||||
@ -69,6 +61,7 @@ public class FSMComponent extends JComponent {
|
|||||||
});
|
});
|
||||||
|
|
||||||
MouseAdapter mouseListener = new MouseAdapter() {
|
MouseAdapter mouseListener = new MouseAdapter() {
|
||||||
|
private boolean screenDrag;
|
||||||
private Vector newTransitionStartPos;
|
private Vector newTransitionStartPos;
|
||||||
private Vector delta;
|
private Vector delta;
|
||||||
private Vector pos;
|
private Vector pos;
|
||||||
@ -77,6 +70,7 @@ public class FSMComponent extends JComponent {
|
|||||||
public void mousePressed(MouseEvent e) {
|
public void mousePressed(MouseEvent e) {
|
||||||
pos = new Vector(e.getX(), e.getY());
|
pos = new Vector(e.getX(), e.getY());
|
||||||
final Vector posVector = getPosVector(e);
|
final Vector posVector = getPosVector(e);
|
||||||
|
screenDrag=false;
|
||||||
if (mouse.isPrimaryClick(e)) {
|
if (mouse.isPrimaryClick(e)) {
|
||||||
elementMoved = fsm.getMovable(posVector);
|
elementMoved = fsm.getMovable(posVector);
|
||||||
if (elementMoved != null)
|
if (elementMoved != null)
|
||||||
@ -88,13 +82,16 @@ public class FSMComponent extends JComponent {
|
|||||||
newTransitionFromState = (State) st;
|
newTransitionFromState = (State) st;
|
||||||
repaint();
|
repaint();
|
||||||
}
|
}
|
||||||
|
screenDrag=true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseReleased(MouseEvent mouseEvent) {
|
public void mouseReleased(MouseEvent mouseEvent) {
|
||||||
if (elementMoved instanceof State)
|
if (elementMoved instanceof State) {
|
||||||
((State) elementMoved).toRaster();
|
((State) elementMoved).toRaster();
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
elementMoved = null;
|
elementMoved = null;
|
||||||
if (newTransitionFromState != null) {
|
if (newTransitionFromState != null) {
|
||||||
final Vector posVector = getPosVector(mouseEvent);
|
final Vector posVector = getPosVector(mouseEvent);
|
||||||
@ -130,7 +127,7 @@ public class FSMComponent extends JComponent {
|
|||||||
@Override
|
@Override
|
||||||
public void mouseDragged(MouseEvent e) {
|
public void mouseDragged(MouseEvent e) {
|
||||||
lastMousePos = getPosVector(e);
|
lastMousePos = getPosVector(e);
|
||||||
if (elementMoved == null && newTransitionFromState == null) {
|
if (elementMoved == null && newTransitionFromState == null && screenDrag) {
|
||||||
Vector newPos = new Vector(e.getX(), e.getY());
|
Vector newPos = new Vector(e.getX(), e.getY());
|
||||||
Vector delta = newPos.sub(pos);
|
Vector delta = newPos.sub(pos);
|
||||||
double s = transform.getScaleX();
|
double s = transform.getScaleX();
|
||||||
@ -139,8 +136,10 @@ public class FSMComponent extends JComponent {
|
|||||||
isManualScale = true;
|
isManualScale = true;
|
||||||
repaint();
|
repaint();
|
||||||
}
|
}
|
||||||
if (elementMoved != null)
|
if (elementMoved != null) {
|
||||||
elementMoved.setPos(getPosVector(e).sub(delta).toFloat());
|
elementMoved.setPos(getPosVector(e).sub(delta).toFloat());
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
if (newTransitionFromState != null)
|
if (newTransitionFromState != null)
|
||||||
repaint();
|
repaint();
|
||||||
}
|
}
|
||||||
@ -177,6 +176,7 @@ public class FSMComponent extends JComponent {
|
|||||||
|
|
||||||
private void createNewState(Vector posVector, Point point) {
|
private void createNewState(Vector posVector, Point point) {
|
||||||
ElementAttributes attr = new ElementAttributes();
|
ElementAttributes attr = new ElementAttributes();
|
||||||
|
attr.set(KEY_NUMBER, fsm.getStates().size());
|
||||||
SwingUtilities.convertPointToScreen(point, this);
|
SwingUtilities.convertPointToScreen(point, this);
|
||||||
AttributeDialog ad = new AttributeDialog(SwingUtilities.getWindowAncestor(this), point, attr, Keys.LABEL, KEY_NUMBER, KEY_VALUES);
|
AttributeDialog ad = new AttributeDialog(SwingUtilities.getWindowAncestor(this), point, attr, Keys.LABEL, KEY_NUMBER, KEY_VALUES);
|
||||||
ad.setTitle(Lang.get("msg_fsmNewState"));
|
ad.setTitle(Lang.get("msg_fsmNewState"));
|
||||||
@ -239,6 +239,7 @@ public class FSMComponent extends JComponent {
|
|||||||
* Fits the FSM to the window
|
* Fits the FSM to the window
|
||||||
*/
|
*/
|
||||||
public void fitFSM() {
|
public void fitFSM() {
|
||||||
|
if (fsm != null) {
|
||||||
GraphicMinMax gr = new GraphicMinMax();
|
GraphicMinMax gr = new GraphicMinMax();
|
||||||
fsm.drawTo(gr);
|
fsm.drawTo(gr);
|
||||||
|
|
||||||
@ -266,6 +267,21 @@ public class FSMComponent extends JComponent {
|
|||||||
repaint();
|
repaint();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* scales the fsm
|
||||||
|
*
|
||||||
|
* @param f factor to scale
|
||||||
|
*/
|
||||||
|
public void scaleCircuit(double f) {
|
||||||
|
Vector dif = getPosVector(getWidth() / 2, getHeight() / 2);
|
||||||
|
transform.translate(dif.x, dif.y);
|
||||||
|
transform.scale(f, f);
|
||||||
|
transform.translate(-dif.x, -dif.y);
|
||||||
|
isManualScale = true;
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the element picked by the mouse
|
* @return the element picked by the mouse
|
||||||
@ -290,7 +306,25 @@ public class FSMComponent extends JComponent {
|
|||||||
GraphicSwing gr = new GraphicSwing(gr2, 1);
|
GraphicSwing gr = new GraphicSwing(gr2, 1);
|
||||||
fsm.drawTo(gr);
|
fsm.drawTo(gr);
|
||||||
|
|
||||||
if (newTransitionFromState != null)
|
if (newTransitionFromState != null) {
|
||||||
gr.drawLine(newTransitionFromState.getPos(), lastMousePos, Style.NORMAL);
|
VectorFloat d = lastMousePos.sub(newTransitionFromState.getPos()).norm().mul(16f);
|
||||||
|
VectorFloat a = d.getOrthogonal().norm().mul(8f);
|
||||||
|
gr.drawPolygon(new Polygon(false)
|
||||||
|
.add(lastMousePos.sub(d).add(a))
|
||||||
|
.add(lastMousePos)
|
||||||
|
.add(lastMousePos.sub(d).sub(a)), Style.NORMAL);
|
||||||
|
gr.drawLine(newTransitionFromState.getPos(), lastMousePos.sub(d.mul(0.2f)), Style.NORMAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the fsm to show
|
||||||
|
*
|
||||||
|
* @param fsm the fsm to show
|
||||||
|
*/
|
||||||
|
public void setFSM(FSM fsm) {
|
||||||
|
this.fsm = fsm;
|
||||||
|
fitFSM();
|
||||||
|
repaint();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,26 +9,41 @@ import de.neemann.digital.draw.library.ElementLibrary;
|
|||||||
import de.neemann.digital.draw.shapes.ShapeFactory;
|
import de.neemann.digital.draw.shapes.ShapeFactory;
|
||||||
import de.neemann.digital.fsm.FSM;
|
import de.neemann.digital.fsm.FSM;
|
||||||
import de.neemann.digital.fsm.FSMDemos;
|
import de.neemann.digital.fsm.FSMDemos;
|
||||||
|
import de.neemann.digital.gui.SaveAsHelper;
|
||||||
import de.neemann.digital.gui.components.table.TableDialog;
|
import de.neemann.digital.gui.components.table.TableDialog;
|
||||||
import de.neemann.digital.lang.Lang;
|
import de.neemann.digital.lang.Lang;
|
||||||
import de.neemann.gui.ErrorMessage;
|
import de.neemann.gui.*;
|
||||||
import de.neemann.gui.ToolTipAction;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.KeyEvent;
|
||||||
import java.awt.event.WindowAdapter;
|
import java.awt.event.WindowAdapter;
|
||||||
import java.awt.event.WindowEvent;
|
import java.awt.event.WindowEvent;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The dialog to show the FSM
|
* The dialog to show the FSM
|
||||||
*/
|
*/
|
||||||
public class FSMFrame extends JFrame {
|
public class FSMFrame extends JFrame implements ClosingWindowListener.ConfirmSave, FSM.ModifiedListener {
|
||||||
|
private static final Icon ICON_NEW = IconCreator.create("document-new.png");
|
||||||
|
private static final Icon ICON_OPEN = IconCreator.create("document-open.png");
|
||||||
|
private static final Icon ICON_SAVE = IconCreator.create("document-save.png");
|
||||||
|
private static final Icon ICON_SAVE_AS = IconCreator.create("document-save-as.png");
|
||||||
|
private static final Icon ICON_EXPAND = IconCreator.create("View-zoom-fit.png");
|
||||||
|
private static final Icon ICON_ZOOM_IN = IconCreator.create("View-zoom-in.png");
|
||||||
|
private static final Icon ICON_ZOOM_OUT = IconCreator.create("View-zoom-out.png");
|
||||||
|
|
||||||
private final FSM fsm;
|
private FSM fsm;
|
||||||
private final FSMComponent fsmComponent;
|
private final FSMComponent fsmComponent;
|
||||||
private final Timer timer;
|
private final Timer timer;
|
||||||
|
private final JComboBox<String> moveControl;
|
||||||
private boolean moveStates = false;
|
private boolean moveStates = false;
|
||||||
|
private ToolTipAction save;
|
||||||
|
private File filename;
|
||||||
|
private boolean lastModified;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use only for tests!
|
* Use only for tests!
|
||||||
@ -45,7 +60,6 @@ public class FSMFrame extends JFrame {
|
|||||||
return library;
|
return library;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Creates a new instance
|
||||||
*
|
*
|
||||||
@ -56,12 +70,12 @@ public class FSMFrame extends JFrame {
|
|||||||
public FSMFrame(JFrame parent, FSM givenFsm, ElementLibrary library) {
|
public FSMFrame(JFrame parent, FSM givenFsm, ElementLibrary library) {
|
||||||
super(Lang.get("fsm_title"));
|
super(Lang.get("fsm_title"));
|
||||||
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
||||||
if (givenFsm == null)
|
if (givenFsm == null) {
|
||||||
givenFsm = FSMDemos.rotDecoder();
|
givenFsm = FSMDemos.rotDecoder();
|
||||||
|
givenFsm.circle();
|
||||||
|
}
|
||||||
|
|
||||||
this.fsm = givenFsm;
|
fsmComponent = new FSMComponent();
|
||||||
|
|
||||||
fsmComponent = new FSMComponent(fsm);
|
|
||||||
getContentPane().add(fsmComponent, BorderLayout.CENTER);
|
getContentPane().add(fsmComponent, BorderLayout.CENTER);
|
||||||
|
|
||||||
timer = new Timer(100, new AbstractAction() {
|
timer = new Timer(100, new AbstractAction() {
|
||||||
@ -73,8 +87,6 @@ public class FSMFrame extends JFrame {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
timer.start();
|
|
||||||
|
|
||||||
addWindowListener(new WindowAdapter() {
|
addWindowListener(new WindowAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void windowClosed(WindowEvent windowEvent) {
|
public void windowClosed(WindowEvent windowEvent) {
|
||||||
@ -83,6 +95,12 @@ public class FSMFrame extends JFrame {
|
|||||||
});
|
});
|
||||||
|
|
||||||
JMenuBar bar = new JMenuBar();
|
JMenuBar bar = new JMenuBar();
|
||||||
|
JToolBar toolBar = new JToolBar();
|
||||||
|
|
||||||
|
createFileMenu(bar, toolBar);
|
||||||
|
toolBar.addSeparator();
|
||||||
|
createViewMenu(bar, toolBar);
|
||||||
|
toolBar.addSeparator();
|
||||||
|
|
||||||
JMenu create = new JMenu(Lang.get("menu_fsm_create"));
|
JMenu create = new JMenu(Lang.get("menu_fsm_create"));
|
||||||
bar.add(create);
|
bar.add(create);
|
||||||
@ -97,44 +115,222 @@ public class FSMFrame extends JFrame {
|
|||||||
}
|
}
|
||||||
}.createJMenuItem());
|
}.createJMenuItem());
|
||||||
|
|
||||||
JToolBar toolBar = new JToolBar();
|
|
||||||
|
|
||||||
final JCheckBox moveCheck = new JCheckBox(Lang.get("fsm_move"));
|
moveControl = new JComboBox<>(new String[]{
|
||||||
moveCheck.addActionListener(new AbstractAction() {
|
Lang.get("fsm_noMove"), Lang.get("fsm_moveTrans"), Lang.get("fsm_moveStates")});
|
||||||
|
moveControl.setSelectedIndex(0);
|
||||||
|
moveControl.addActionListener(new AbstractAction() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent actionEvent) {
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
moveStates = moveCheck.isSelected();
|
switch (moveControl.getSelectedIndex()) {
|
||||||
if (!moveStates) {
|
case 0:
|
||||||
|
timer.stop();
|
||||||
fsm.toRaster();
|
fsm.toRaster();
|
||||||
repaint();
|
fsmComponent.repaint();
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
moveStates = false;
|
||||||
|
timer.start();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
moveStates = true;
|
||||||
|
timer.start();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
moveCheck.setSelected(moveStates);
|
JPanel movePanel = new JPanel(new BorderLayout());
|
||||||
toolBar.add(moveCheck);
|
movePanel.add(moveControl, BorderLayout.WEST);
|
||||||
|
toolBar.add(movePanel);
|
||||||
getContentPane().add(toolBar, BorderLayout.PAGE_START);
|
getContentPane().add(toolBar, BorderLayout.PAGE_START);
|
||||||
|
|
||||||
|
|
||||||
setJMenuBar(bar);
|
setJMenuBar(bar);
|
||||||
|
|
||||||
pack();
|
pack();
|
||||||
fsmComponent.fitFSM();
|
setFSM(givenFsm);
|
||||||
|
|
||||||
setLocationRelativeTo(parent);
|
setLocationRelativeTo(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void createFileMenu(JMenuBar bar, JToolBar toolBar) {
|
||||||
|
ToolTipAction newFile = new ToolTipAction(Lang.get("menu_new"), ICON_NEW) {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
if (ClosingWindowListener.checkForSave(FSMFrame.this, FSMFrame.this)) {
|
||||||
|
setFSM(new FSM());
|
||||||
|
setFilename(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.setAcceleratorCTRLplus('N').setToolTip(Lang.get("menu_new_tt"));
|
||||||
|
|
||||||
|
ToolTipAction open = new ToolTipAction(Lang.get("menu_open"), ICON_OPEN) {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
if (ClosingWindowListener.checkForSave(FSMFrame.this, FSMFrame.this)) {
|
||||||
|
JFileChooser fc = getJFileChooser(filename);
|
||||||
|
if (fc.showOpenDialog(FSMFrame.this) == JFileChooser.APPROVE_OPTION) {
|
||||||
|
loadFile(fc.getSelectedFile());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.setAcceleratorCTRLplus('O');
|
||||||
|
|
||||||
|
// JMenu openRecent = new JMenu(Lang.get("menu_openRecent"));
|
||||||
|
// JMenu openRecentNewWindow = new JMenu(Lang.get("menu_openRecentNewWindow"));
|
||||||
|
// fileHistory.setMenu(openRecent, openRecentNewWindow);
|
||||||
|
|
||||||
|
ToolTipAction saveAs = new ToolTipAction(Lang.get("menu_saveAs"), ICON_SAVE_AS) {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
JFileChooser fc = getJFileChooser(filename);
|
||||||
|
final SaveAsHelper saveAsHelper = new SaveAsHelper(FSMFrame.this, fc, "fsm");
|
||||||
|
saveAsHelper.checkOverwrite(file -> saveFile(file));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
save = new ToolTipAction(Lang.get("menu_save"), ICON_SAVE) {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
if (filename == null)
|
||||||
|
saveAs.actionPerformed(e);
|
||||||
|
else
|
||||||
|
saveFile(filename);
|
||||||
|
}
|
||||||
|
}.setAcceleratorCTRLplus('S').setEnabledChain(false);
|
||||||
|
|
||||||
|
JMenu file = new JMenu(Lang.get("menu_file"));
|
||||||
|
bar.add(file);
|
||||||
|
file.add(newFile.createJMenuItem());
|
||||||
|
file.add(open.createJMenuItem());
|
||||||
|
file.add(save.createJMenuItem());
|
||||||
|
file.add(saveAs.createJMenuItem());
|
||||||
|
|
||||||
|
toolBar.add(newFile.createJButtonNoText());
|
||||||
|
toolBar.add(open.createJButtonNoText());
|
||||||
|
toolBar.add(save.createJButtonNoText());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setFSM(FSM fsm) {
|
||||||
|
this.fsm = fsm;
|
||||||
|
fsmComponent.setFSM(fsm);
|
||||||
|
fsm.setModifiedListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JFileChooser getJFileChooser(File filename) {
|
||||||
|
File folder = null;
|
||||||
|
if (filename != null)
|
||||||
|
folder = filename.getParentFile();
|
||||||
|
|
||||||
|
JFileChooser fileChooser = new MyFileChooser(folder);
|
||||||
|
fileChooser.setFileFilter(new FileNameExtensionFilter("FSM", "fsm"));
|
||||||
|
return fileChooser;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setFilename(File filename) {
|
||||||
|
String fsmTitle;
|
||||||
|
if (filename == null)
|
||||||
|
fsmTitle = Lang.get("fsm_title");
|
||||||
|
else
|
||||||
|
fsmTitle = filename.toString() + " - " + Lang.get("fsm_title");
|
||||||
|
|
||||||
|
if (fsm.hasChanged())
|
||||||
|
fsmTitle = "*" + fsmTitle;
|
||||||
|
setTitle(fsmTitle);
|
||||||
|
|
||||||
|
this.filename = filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isStateChanged() {
|
||||||
|
return fsm.hasChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveChanges() {
|
||||||
|
save.actionPerformed(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void modifiedChanged(boolean modified) {
|
||||||
|
if (lastModified != modified) {
|
||||||
|
lastModified = modified;
|
||||||
|
setFilename(filename);
|
||||||
|
save.setEnabled(modified);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadFile(File file) {
|
||||||
|
try {
|
||||||
|
moveControl.setSelectedIndex(0);
|
||||||
|
setFSM(FSM.loadFSM(file));
|
||||||
|
setFilename(file);
|
||||||
|
} catch (IOException e) {
|
||||||
|
new ErrorMessage(Lang.get("msg_fsm_errorLoadingFile")).addCause(e).show(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveFile(File file) {
|
||||||
|
try {
|
||||||
|
fsm.save(file);
|
||||||
|
setFilename(file);
|
||||||
|
save.setEnabled(false);
|
||||||
|
} catch (IOException e) {
|
||||||
|
new ErrorMessage(Lang.get("msg_fsm_errorStoringFile")).addCause(e).show(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createViewMenu(JMenuBar menuBar, JToolBar toolBar) {
|
||||||
|
ToolTipAction maximize = new ToolTipAction(Lang.get("menu_maximize"), ICON_EXPAND) {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
fsmComponent.fitFSM();
|
||||||
|
}
|
||||||
|
}.setAccelerator("F1");
|
||||||
|
ToolTipAction zoomIn = new ToolTipAction(Lang.get("menu_zoomIn"), ICON_ZOOM_IN) {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
fsmComponent.scaleCircuit(1 / 0.9);
|
||||||
|
}
|
||||||
|
}.setAccelerator("control PLUS");
|
||||||
|
// enable [+] which is SHIFT+[=] on english keyboard layout
|
||||||
|
fsmComponent.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_EQUALS, KeyEvent.CTRL_DOWN_MASK, false), zoomIn);
|
||||||
|
fsmComponent.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ADD, KeyEvent.CTRL_DOWN_MASK, false), zoomIn);
|
||||||
|
fsmComponent.getActionMap().put(zoomIn, zoomIn);
|
||||||
|
|
||||||
|
ToolTipAction zoomOut = new ToolTipAction(Lang.get("menu_zoomOut"), ICON_ZOOM_OUT) {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
fsmComponent.scaleCircuit(0.9);
|
||||||
|
}
|
||||||
|
}.setAccelerator("control MINUS");
|
||||||
|
// enable [+] which is SHIFT+[=] on english keyboard layout
|
||||||
|
fsmComponent.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_SUBTRACT, KeyEvent.CTRL_DOWN_MASK, false), zoomOut);
|
||||||
|
fsmComponent.getActionMap().put(zoomOut, zoomOut);
|
||||||
|
|
||||||
|
toolBar.add(zoomIn.createJButtonNoText());
|
||||||
|
toolBar.add(zoomOut.createJButtonNoText());
|
||||||
|
toolBar.add(maximize.createJButtonNoText());
|
||||||
|
|
||||||
|
JMenu view = new JMenu(Lang.get("menu_view"));
|
||||||
|
menuBar.add(view);
|
||||||
|
view.add(maximize.createJMenuItem());
|
||||||
|
view.add(zoomOut.createJMenuItem());
|
||||||
|
view.add(zoomIn.createJMenuItem());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple test method
|
* A simple test method
|
||||||
*
|
*
|
||||||
* @param args the programs arguments
|
* @param args the programs arguments
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
|
||||||
FSM fsm = FSMDemos.rotDecoder();
|
FSM fsm = FSMDemos.rotDecoder();
|
||||||
|
|
||||||
ElementLibrary library = new ElementLibrary();
|
ElementLibrary library = new ElementLibrary();
|
||||||
new ShapeFactory(library);
|
new ShapeFactory(library);
|
||||||
|
|
||||||
new FSMFrame(null, fsm, library).setVisible(true);
|
new FSMFrame(null, fsm.circle(), library).setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@ -1760,13 +1760,14 @@ Daher steht auch das Signal 'D_out' zur Verfügung, um in diesem Fall den Wert z
|
|||||||
<string name="fsm_title">Endlicher Automat</string>
|
<string name="fsm_title">Endlicher Automat</string>
|
||||||
<string name="menu_fsm_create">Erzeugen</string>
|
<string name="menu_fsm_create">Erzeugen</string>
|
||||||
<string name="menu_fsm_create_table">Zustandsübergangstabelle</string>
|
<string name="menu_fsm_create_table">Zustandsübergangstabelle</string>
|
||||||
<string name="fsm_move">Bewegen</string>
|
|
||||||
<string name="err_notDeterministic_N">Der Automat ist nicht deterministisch: {0}</string>
|
<string name="err_notDeterministic_N">Der Automat ist nicht deterministisch: {0}</string>
|
||||||
<string name="err_fsmNumberUsedTwice_N">Zustandsnummer {0} ist nicht eindeutig.</string>
|
<string name="err_fsmNumberUsedTwice_N">Zustandsnummer {0} ist nicht eindeutig.</string>
|
||||||
<string name="err_fsmNoInitialState">Es gibt keinen Initialzustand.</string>
|
<string name="err_fsmNoInitialState">Es gibt keinen Initialzustand.</string>
|
||||||
<string name="err_fsmState_N_notFound">Zustand ''{0}'' nicht gefunden!</string>
|
<string name="err_fsmState_N_notFound">Zustand ''{0}'' nicht gefunden!</string>
|
||||||
<string name="err_fsmInvalidOutputAssignment_N">Falsche Zuweisung an einen Ausgang (''{0}'')!</string>
|
<string name="err_fsmInvalidOutputAssignment_N">Falsche Zuweisung an einen Ausgang (''{0}'')!</string>
|
||||||
<string name="err_fsmErrorInCondition_N">Fehler in Bedingung ''{0}''!</string>
|
<string name="err_fsmErrorInCondition_N">Fehler in Bedingung ''{0}''!</string>
|
||||||
|
<string name="msg_fsm_errorLoadingFile">Fehler beim Laden der Datei!</string>
|
||||||
|
<string name="msg_fsm_errorStoringFile">Fehler beim Speichern der Datei!</string>
|
||||||
<string name="key_stateNum">Zustandsnummer</string>
|
<string name="key_stateNum">Zustandsnummer</string>
|
||||||
<string name="key_stateNum_tt">Die Nummer welche diesen Zustand representiert.</string>
|
<string name="key_stateNum_tt">Die Nummer welche diesen Zustand representiert.</string>
|
||||||
<string name="key_stateValues">Ausgänge</string>
|
<string name="key_stateValues">Ausgänge</string>
|
||||||
@ -1777,5 +1778,8 @@ Daher steht auch das Signal 'D_out' zur Verfügung, um in diesem Fall den Wert z
|
|||||||
<string name="key_transCond">Bedingung</string>
|
<string name="key_transCond">Bedingung</string>
|
||||||
<string name="key_transCond_tt">Ein boolscher Ausdruck.</string>
|
<string name="key_transCond_tt">Ein boolscher Ausdruck.</string>
|
||||||
<string name="msg_fsmNewState">Neuer Zustand</string>
|
<string name="msg_fsmNewState">Neuer Zustand</string>
|
||||||
|
<string name="fsm_noMove">keine Bewegung</string>
|
||||||
|
<string name="fsm_moveTrans">Übergänge</string>
|
||||||
|
<string name="fsm_moveStates">Übergänge+Zustände</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -1740,13 +1740,14 @@ Therefore, the signal 'D_out' is also available to check the value in this case.
|
|||||||
<string name="fsm_title">Finite State Machine</string>
|
<string name="fsm_title">Finite State Machine</string>
|
||||||
<string name="menu_fsm_create">Create</string>
|
<string name="menu_fsm_create">Create</string>
|
||||||
<string name="menu_fsm_create_table">State Transition Table</string>
|
<string name="menu_fsm_create_table">State Transition Table</string>
|
||||||
<string name="fsm_move">Move</string>
|
|
||||||
<string name="err_notDeterministic_N">The FSM is not deterministic: {0}</string>
|
<string name="err_notDeterministic_N">The FSM is not deterministic: {0}</string>
|
||||||
<string name="err_fsmNumberUsedTwice_N">State Number {0} used twice.</string>
|
<string name="err_fsmNumberUsedTwice_N">State Number {0} used twice.</string>
|
||||||
<string name="err_fsmNoInitialState">There is no initial state (state number zero).</string>
|
<string name="err_fsmNoInitialState">There is no initial state (state number zero).</string>
|
||||||
<string name="err_fsmState_N_notFound">State ''{0}'' not found!</string>
|
<string name="err_fsmState_N_notFound">State ''{0}'' not found!</string>
|
||||||
<string name="err_fsmInvalidOutputAssignment_N">Wrong assignment to output (''{0}'')!</string>
|
<string name="err_fsmInvalidOutputAssignment_N">Wrong assignment to output (''{0}'')!</string>
|
||||||
<string name="err_fsmErrorInCondition_N">Error in condition ''{0}''!</string>
|
<string name="err_fsmErrorInCondition_N">Error in condition ''{0}''!</string>
|
||||||
|
<string name="msg_fsm_errorLoadingFile">Error loading a file!</string>
|
||||||
|
<string name="msg_fsm_errorStoringFile">Error storing a file!</string>
|
||||||
<string name="key_stateNum">State Number</string>
|
<string name="key_stateNum">State Number</string>
|
||||||
<string name="key_stateNum_tt">The number which represents this state.</string>
|
<string name="key_stateNum_tt">The number which represents this state.</string>
|
||||||
<string name="key_stateValues">Outputs</string>
|
<string name="key_stateValues">Outputs</string>
|
||||||
@ -1757,5 +1758,8 @@ Therefore, the signal 'D_out' is also available to check the value in this case.
|
|||||||
<string name="key_transCond">Condition</string>
|
<string name="key_transCond">Condition</string>
|
||||||
<string name="key_transCond_tt">A boolean expression.</string>
|
<string name="key_transCond_tt">A boolean expression.</string>
|
||||||
<string name="msg_fsmNewState">New State</string>
|
<string name="msg_fsmNewState">New State</string>
|
||||||
|
<string name="fsm_noMove">no movement</string>
|
||||||
|
<string name="fsm_moveTrans">Transitions</string>
|
||||||
|
<string name="fsm_moveStates">Transitions+States</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
Loading…
x
Reference in New Issue
Block a user