Merge branch 'tutorial'

This commit is contained in:
hneemann 2019-07-23 12:04:06 +02:00
commit a634efdeb3
14 changed files with 553 additions and 18 deletions

View File

@ -452,7 +452,7 @@ public final class Keys {
* enables the grid * enables the grid
*/ */
public static final Key<Boolean> SETTINGS_GRID public static final Key<Boolean> SETTINGS_GRID
= new Key<>("grid", false); = new Key<>("grid", true);
/** /**
* enables the wire bits view * enables the wire bits view
@ -786,6 +786,14 @@ public final class Keys {
* Circuit is generic * Circuit is generic
*/ */
public static final Key<Boolean> IS_GENERIC = public static final Key<Boolean> IS_GENERIC =
new Key<Boolean>("isGeneric", false).setSecondary(); new Key<>("isGeneric", false).setSecondary();
/**
* Enables the tutorial
*/
public static final Key<Boolean> SETTINGS_SHOW_TUTORIAL =
new Key<>("showTutorial", true).setSecondary();
} }

View File

@ -43,6 +43,7 @@ import de.neemann.digital.gui.components.testing.TestAllDialog;
import de.neemann.digital.gui.components.testing.ValueTableDialog; import de.neemann.digital.gui.components.testing.ValueTableDialog;
import de.neemann.digital.gui.components.tree.LibraryTreeModel; import de.neemann.digital.gui.components.tree.LibraryTreeModel;
import de.neemann.digital.gui.components.tree.SelectTree; import de.neemann.digital.gui.components.tree.SelectTree;
import de.neemann.digital.gui.tutorial.InitialTutorial;
import de.neemann.digital.gui.release.CheckForNewRelease; import de.neemann.digital.gui.release.CheckForNewRelease;
import de.neemann.digital.gui.remote.DigitalHandler; import de.neemann.digital.gui.remote.DigitalHandler;
import de.neemann.digital.gui.remote.RemoteException; import de.neemann.digital.gui.remote.RemoteException;
@ -1863,6 +1864,10 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS
if (file != null) if (file != null)
builder.setFileToOpen(file); builder.setFileToOpen(file);
SwingUtilities.invokeLater(() -> { SwingUtilities.invokeLater(() -> {
final boolean tutorial = Settings.getInstance().getAttributes().get(Keys.SETTINGS_SHOW_TUTORIAL);
if (tutorial)
builder.setCircuit(new Circuit());
Main main = builder.build(); Main main = builder.build();
try { try {
new RemoteSever(new DigitalHandler(main)).start(41114); new RemoteSever(new DigitalHandler(main)).start(41114);
@ -1871,6 +1876,9 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS
} }
main.setVisible(true); main.setVisible(true);
if (tutorial)
new InitialTutorial(main).setVisible(true);
CheckForNewRelease.showReleaseDialog(main); CheckForNewRelease.showReleaseDialog(main);
}); });
} }

View File

@ -133,6 +133,7 @@ public class CircuitComponent extends JComponent implements ChangedListener, Lib
private Mouse mouse = Mouse.getMouse(); private Mouse mouse = Mouse.getMouse();
private Circuit shallowCopy; private Circuit shallowCopy;
private CircuitScrollPanel circuitScrollPanel; private CircuitScrollPanel circuitScrollPanel;
private TutorialListener tutorialListener;
/** /**
@ -429,6 +430,8 @@ public class CircuitComponent extends JComponent implements ChangedListener, Lib
try { try {
if (modification != null) { if (modification != null) {
undoManager.apply(modification); undoManager.apply(modification);
if (tutorialListener != null)
tutorialListener.modified(modification);
if (circuitScrollPanel != null) if (circuitScrollPanel != null)
circuitScrollPanel.sizeChanged(); circuitScrollPanel.sizeChanged();
} }
@ -620,6 +623,9 @@ public class CircuitComponent extends JComponent implements ChangedListener, Lib
getCircuit().clearState(); getCircuit().clearState();
} }
requestFocusInWindow(); requestFocusInWindow();
if (tutorialListener != null)
tutorialListener.modified(null);
} }
/** /**
@ -1548,7 +1554,7 @@ public class CircuitComponent extends JComponent implements ChangedListener, Lib
} }
private void insertWires(VisualElement element) { private void insertWires(VisualElement element) {
if (element.isAutoWireCompatible()) { if (element.isAutoWireCompatible() && tutorialListener == null) {
Modifications.Builder<Circuit> wires = new Modifications.Builder<>(Lang.get("lib_wires")); Modifications.Builder<Circuit> wires = new Modifications.Builder<>(Lang.get("lib_wires"));
for (Pin p : element.getPins()) for (Pin p : element.getPins())
insertWirePin(p, element.getRotate(), wires); insertWirePin(p, element.getRotate(), wires);
@ -2292,6 +2298,8 @@ public class CircuitComponent extends JComponent implements ChangedListener, Lib
SwingUtilities.convertPointToScreen(p, CircuitComponent.this); SwingUtilities.convertPointToScreen(p, CircuitComponent.this);
boolean modelHasChanged = actor.interact(CircuitComponent.this, p, getPosVector(e), modelSync); boolean modelHasChanged = actor.interact(CircuitComponent.this, p, getPosVector(e), modelSync);
if (modelHasChanged) { if (modelHasChanged) {
if (tutorialListener != null)
tutorialListener.modified(null);
modelHasChanged(); modelHasChanged();
} else } else
graphicHasChanged(); graphicHasChanged();
@ -2317,6 +2325,15 @@ public class CircuitComponent extends JComponent implements ChangedListener, Lib
new MouseControllerWizard(wizardNotification).activate(); new MouseControllerWizard(wizardNotification).activate();
} }
/**
* Sets the modification listener.
*
* @param tutorialListener is called every time the circuit is modified
*/
public void setTutorialListener(TutorialListener tutorialListener) {
this.tutorialListener = tutorialListener;
}
/** /**
* Deactivate a wizard * Deactivate a wizard
*/ */
@ -2369,4 +2386,15 @@ public class CircuitComponent extends JComponent implements ChangedListener, Lib
void closed(); void closed();
} }
/**
* Listener to get notified if the circuit has changed
*/
public interface TutorialListener {
/**
* Called if the circuit was modified
*
* @param modification the modification
*/
void modified(Modification<Circuit> modification);
}
} }

View File

@ -0,0 +1,238 @@
/*
* Copyright (c) 2019 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.gui.tutorial;
import de.neemann.digital.core.*;
import de.neemann.digital.core.basic.XOr;
import de.neemann.digital.core.element.Element;
import de.neemann.digital.core.element.ElementTypeDescription;
import de.neemann.digital.core.element.Keys;
import de.neemann.digital.core.io.In;
import de.neemann.digital.core.io.Out;
import de.neemann.digital.draw.elements.Circuit;
import de.neemann.digital.draw.elements.PinException;
import de.neemann.digital.draw.elements.VisualElement;
import de.neemann.digital.draw.library.ElementNotFoundException;
import de.neemann.digital.draw.model.ModelCreator;
import de.neemann.digital.gui.Main;
import de.neemann.digital.gui.Settings;
import de.neemann.digital.gui.components.CircuitComponent;
import de.neemann.digital.gui.components.modification.ModifyInsertWire;
import de.neemann.digital.lang.Lang;
import de.neemann.digital.undo.Modification;
import de.neemann.digital.undo.Modifications;
import de.neemann.gui.LineBreaker;
import de.neemann.gui.Screen;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
/**
* The tutorial dialog.
*/
public class InitialTutorial extends JDialog implements CircuitComponent.TutorialListener {
private static final ArrayList<Step> STEPS = new ArrayList<>();
static {
STEPS.add(new Step("tutorial1", (cc, mod, t) -> contains(cc, In.DESCRIPTION)));
STEPS.add(new Step("tutorial2", (cc, mod, t) -> contains(cc, In.DESCRIPTION, In.DESCRIPTION)));
STEPS.add(new Step("tutorial3", (cc, mod, t) -> contains(cc, In.DESCRIPTION, In.DESCRIPTION, XOr.DESCRIPTION)));
STEPS.add(new Step("tutorial4", (cc, mod, t) -> contains(cc, In.DESCRIPTION, In.DESCRIPTION, XOr.DESCRIPTION, Out.DESCRIPTION)));
STEPS.add(new Step("tutorial5", (cc, mod, t) -> contains(mod, ModifyInsertWire.class)));
STEPS.add(new Step("tutorial6", (cc, mod, t) -> isWorking(cc)));
STEPS.add(new Step("tutorial7", (cc, mod, t) -> t.main.getModel() != null));
STEPS.add(new Step("tutorial8", (cc, mod, t) -> outputIsHigh(t)));
STEPS.add(new Step("tutorial9", (cc, mod, t) -> t.main.getModel() == null));
STEPS.add(new Step("tutorial10", (cc, mod, t) -> isIONamed(cc, 1, t)));
STEPS.add(new Step("tutorial11", (cc, mod, t) -> isIONamed(cc, 3, t)));
}
private final Main main;
private static boolean outputIsHigh(InitialTutorial t) {
Model model = t.main.getModel();
if (model == null)
return false;
List<Node> nl = model.getNodes();
if (nl.size() != 1)
return false;
Node n = nl.get(0);
if (n instanceof Element) {
Element e = (Element) n;
try {
final ObservableValues outputs = e.getOutputs();
if (outputs.size() != 1)
return false;
else
return outputs.get(0).getValue() != 0;
} catch (PinException ex) {
return false;
}
} else
return false;
}
private static boolean isIONamed(CircuitComponent cc, int expected, InitialTutorial t) {
HashSet<String> set = new HashSet<>();
int num = 0;
for (VisualElement ve : cc.getCircuit().getElements()) {
if (ve.equalsDescription(In.DESCRIPTION) || ve.equalsDescription(Out.DESCRIPTION)) {
String l = ve.getElementAttributes().getLabel();
if (!l.isEmpty()) {
if (set.contains(l)) {
t.setTextByID("tutorialUniqueIdents");
return false;
}
set.add(l);
num++;
}
}
}
return num == expected;
}
private static boolean isWorking(CircuitComponent cc) {
try {
new ModelCreator(cc.getCircuit(), cc.getLibrary()).createModel(false);
return true;
} catch (PinException | NodeException | ElementNotFoundException e) {
return false;
}
}
private static boolean contains(Modification<Circuit> mod, Class<? extends Modification> modifyClass) {
if (mod == null)
return false;
if (mod.getClass() == modifyClass)
return true;
if (mod instanceof Modifications) {
Modifications m = (Modifications) mod;
for (Object i : m.getModifications())
if (i.getClass() == modifyClass)
return true;
}
return false;
}
private static boolean contains(CircuitComponent cc, ElementTypeDescription... descriptions) {
ArrayList<VisualElement> el = new ArrayList<>(cc.getCircuit().getElements());
if (el.size() != descriptions.length)
return false;
for (ElementTypeDescription d : descriptions) {
Iterator<VisualElement> it = el.iterator();
while (it.hasNext()) {
if (it.next().equalsDescription(d)) {
it.remove();
break;
}
}
}
return el.isEmpty();
}
private final JTextPane text;
private final CircuitComponent circuitComponent;
private int stepIndex;
/**
* Creates the tutorial dialog.
*
* @param main the main class
*/
public InitialTutorial(Main main) {
super(main, Lang.get("tutorial"), false);
this.main = main;
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setAlwaysOnTop(true);
circuitComponent = main.getCircuitComponent();
circuitComponent.setTutorialListener(this);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent windowEvent) {
circuitComponent.setTutorialListener(null);
}
});
text = new JTextPane();
text.setEditable(false);
text.setFont(Screen.getInstance().getFont(1.2f));
text.setPreferredSize(new Dimension(300, 400));
getContentPane().add(new JScrollPane(text));
getContentPane().add(new JButton(new AbstractAction(Lang.get("tutorialNotNeeded")) {
@Override
public void actionPerformed(ActionEvent actionEvent) {
disableTutorial();
}
}), BorderLayout.SOUTH);
pack();
final Point ml = main.getLocation();
setLocation(ml.x - getWidth(), ml.y);
stepIndex = -1;
incIndex();
}
private void disableTutorial() {
Settings.getInstance().getAttributes().set(Keys.SETTINGS_SHOW_TUTORIAL, false);
dispose();
}
private void incIndex() {
stepIndex++;
if (stepIndex == STEPS.size()) {
disableTutorial();
} else {
setTextByID(STEPS.get(stepIndex).getId());
}
}
private void setTextByID(String id) {
final String s = Lang.get(id);
text.setText(new LineBreaker(1000).breakLines(s));
}
@Override
public void modified(Modification<Circuit> modification) {
if (STEPS.get(stepIndex).getChecker().accomplished(circuitComponent, modification, this))
incIndex();
}
private static final class Step {
private final String id;
private final Checker checker;
private Step(String id, Checker checker) {
this.id = id;
this.checker = checker;
}
public String getId() {
return id;
}
public Checker getChecker() {
return checker;
}
}
private interface Checker {
boolean accomplished(CircuitComponent circuitComponent, Modification<Circuit> modification, InitialTutorial t);
}
}

View File

@ -0,0 +1,10 @@
/*
* Copyright (c) 2019 Helmut Neemann.
* Use of this source code is governed by the GPL v3 license
* that can be found in the LICENSE file.
*/
/**
* Classes used to show the initial tutorial
*/
package de.neemann.digital.gui.tutorial;

View File

@ -27,6 +27,13 @@ public final class Modifications<A extends Copyable<A>> implements Modification<
m.modify(a); m.modify(a);
} }
/**
* @return The contained modifications
*/
public ArrayList<Modification<A>> getModifications() {
return modifications;
}
@Override @Override
public String toString() { public String toString() {
return name; return name;

View File

@ -82,21 +82,28 @@ public class LineBreaker {
StringBuilder word = new StringBuilder(); StringBuilder word = new StringBuilder();
pos = indent; pos = indent;
boolean lastLineBreak=false;
for (int i = 0; i < text.length(); i++) { for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i); char c = text.charAt(i);
switch (c) { switch (c) {
case '\n': case '\n':
if (preserveLineBreaks) { if (preserveLineBreaks || lastLineBreak) {
addWord(word); addWord(word);
lineBreak(); lineBreak();
break; } else {
addWord(word);
lastLineBreak = true;
} }
break;
case '\r': case '\r':
case '\t':
case ' ': case ' ':
addWord(word); addWord(word);
lastLineBreak = false;
break; break;
default: default:
word.append(c); word.append(c);
lastLineBreak = false;
} }
} }
addWord(word); addWord(word);

View File

@ -1349,6 +1349,9 @@ Sind evtl. die Namen der Variablen nicht eindeutig?</string>
<string name="key_isGeneric">Schaltung ist generisch</string> <string name="key_isGeneric">Schaltung ist generisch</string>
<string name="key_isGeneric_tt">Erlaubt die Erzeugung von generischen Schaltungen.</string> <string name="key_isGeneric_tt">Erlaubt die Erzeugung von generischen Schaltungen.</string>
<string name="key_showTutorial">Tutorial beim Start anzeigen</string>
<string name="key_showTutorial_tt">Aktiviert das Tutorial.</string>
<string name="mod_insertWire">Leitung eingefügt.</string> <string name="mod_insertWire">Leitung eingefügt.</string>
<string name="mod_insertCopied">Aus Zwischenablage eingefügt.</string> <string name="mod_insertCopied">Aus Zwischenablage eingefügt.</string>
<string name="mod_setKey_N0_in_element_N1">Wert ''{0}'' in Element ''{1}'' verändert.</string> <string name="mod_setKey_N0_in_element_N1">Wert ''{0}'' in Element ''{1}'' verändert.</string>
@ -1953,4 +1956,64 @@ Daher steht auch das Signal 'D_out' zur Verfügung, um in diesem Fall den Wert z
Gibt es aus einem Zustand keinen unbedingten Übergang, bleibt der Automat in diesem Zustand, wenn keine Gibt es aus einem Zustand keinen unbedingten Übergang, bleibt der Automat in diesem Zustand, wenn keine
andere Übergangsbedingung erfüllt ist. andere Übergangsbedingung erfüllt ist.
</body></html>]]></string> </body></html>]]></string>
<string name="tutorial">Tutorial</string>
<string name="tutorial1">Im Folgenden führt Sie ein kurzes Tutorial zur ersten,
einfachen Schaltung:
Beginnen Sie, indem Sie einen Eingang in die Schaltung einfügen.
Sie finden den Eingang im Menu Bauteile▸IO.</string>
<string name="tutorial2">Fügen Sie nun einen zweiten Eingang in die Schaltung ein.
Sie können auch auf den Eingang in der Toolbar klicken.
Setzen Sie den zweiten Eingang am besten mit etwas Abstand unter den ersten Eingang.
Sie können die Schaltung verschieben, wenn Sie die rechte Maustaste gedrückt halten.
Durch klicken auf Bauteile können Sie diese verschieben.
</string>
<string name="tutorial3">Als nächstes soll ein "Exklusiv Oder" Gatter eingefügt werden.
Sie finden dieses Gatter im Menu Bauteile▸Logisch.
Setzen Sie dieses Bauteil mit etwas Abstand rechts neben die Eingänge.
</string>
<string name="tutorial4">Als letztes Bauteil soll noch ein Ausgang eingefügt werden.
Platzieren Sie den Ausgang etwas rechts des "Exklusiv Oder" Gatters.
</string>
<string name="tutorial5">Um die Schaltung zu vervollständigen, sind Verbindungsleitungen zu ziehen.
Klicken Sie auf den roten Punkt am ersten Eingang und verbinden Sie diesen mit einem Eingang
des "Exklusiv Oder" Gatters, indem Sie danach auf einen blauen Punkt des "Exklusiv Oder"
Gatters klicken. Die Maustaste NICHT gedrückt halten!
</string>
<string name="tutorial6">Verbinden Sie den roten Punkt des zweiten Eingangs mit den zweiten blauen
Punkten des "Exklusiv Oder" Gatters und den roten Punkt des "Exklusiv Oder" Gatters mit dem
blauen Punkt des Ausgangs.
Während Sie die Leitung zeichnen, können Sie sie durch Klicken auf die Arbeitsfläche anheften.
Rechts-Klick bricht das Zeichnen der Leitung ab (Steuerung-Klick unter MacOS).
</string>
<string name="tutorial7">Damit ist Ihre erste Schaltung funktionsfähig.
Um die Simulation zu starten, können Sie auf den Play-Knopf in der Toolbar klicken.
Wenn Sie mit der Maus über die Toolbar fahren, werden Tool-Tipps angezeigt.
</string>
<string name="tutorial8">
Die Simulation ist jetzt aktiv.
Schalten Sie die Eingänge um, indem Sie darauf klicken.
</string>
<string name="tutorial9">
Um die Simulation zu beenden, klicken Sie auf den Stop-Knopf in der Toolbar.
</string>
<string name="tutorial10">
Der Vollständigkeit halber sollen die Ein- und Ausgänge benannt werden.
Durch Rechts-Klick auf einen Eingang öffnet sich ein Dialog (Unter MacOS wird
Steuerung-Klick verwendet). Hier kann der Eingang mit einer Bezeichnung versehen werden.
</string>
<string name="tutorial11">
Benennen Sie alle Ein- und Ausgänge.
</string>
<string name="tutorialUniqueIdents">
Ein- und Ausgänge sollten stets eindeutig benannt sein.
</string>
<string name="tutorialNotNeeded">
Tutorial überspringen
</string>
</resources> </resources>

View File

@ -129,7 +129,7 @@
<!-- IO --> <!-- IO -->
<string name="elem_Out">Out</string> <string name="elem_Out">Output</string>
<string name="elem_Out_tt">Can be used to display an output signal in a circuit. <string name="elem_Out_tt">Can be used to display an output signal in a circuit.
This element is also used to connect a circuit to an embedding circuit. This element is also used to connect a circuit to an embedding circuit.
In this case the connection is bidirectional. In this case the connection is bidirectional.
@ -1335,6 +1335,9 @@
<string name="key_isGeneric">Circuit is generic</string> <string name="key_isGeneric">Circuit is generic</string>
<string name="key_isGeneric_tt">Allows to create a generic circuit.</string> <string name="key_isGeneric_tt">Allows to create a generic circuit.</string>
<string name="key_showTutorial">Show Tutorial at Startup</string>
<string name="key_showTutorial_tt">Enables the tutorial.</string>
<string name="mod_insertWire">Inserted wire.</string> <string name="mod_insertWire">Inserted wire.</string>
<string name="mod_insertCopied">Insert from clipboard.</string> <string name="mod_insertCopied">Insert from clipboard.</string>
<string name="mod_setKey_N0_in_element_N1">Value ''{0}'' in component ''{1}'' modified.</string> <string name="mod_setKey_N0_in_element_N1">Value ''{0}'' in component ''{1}'' modified.</string>
@ -1922,4 +1925,56 @@ Therefore, the signal 'D_out' is also available to check the value in this case.
transition condition is met. transition condition is met.
</body></html>]]></string> </body></html>]]></string>
<string name="tutorial">Tutorial</string>
<string name="tutorial1">In the following a short tutorial leads you to the first, simple circuit:
First, insert an input into the circuit. You will find the input in the menu Components▸IO.</string>
<string name="tutorial2">Now add a second input to the circuit. You can also click on the input
in the toolbar.
It is best to place the second input slightly below the first input.
You can move the circuit by holding down the right mouse button.
By clicking on components you can move them.</string>
<string name="tutorial3">Next, an "Exclusive Or" gate is to be inserted.
You can find this gate in the menu Components▸Logic.
Place this component with some distance to the right of the inputs.</string>
<string name="tutorial4">The last component to be inserted is an output.
Place it with some distance to the right of the "Exclusive Or" gate.
</string>
<string name="tutorial5">In order to complete the circuit, connecting wires must be drawn.
Click on the red dot at the first input and connect it to an input of the "Exclusive Or" gate,
by clicking on a blue dot of the "Exclusive Or" gate afterwards.
Do NOT drag with mouse button down!
</string>
<string name="tutorial6">Connect the red dot of the second input to the second blue dot of the
"Exclusive Or" gate and the red dot of the "Exclusive Or" gate to the blue dot of the output.
While drawing, you can pin the wire by clicking somewhere on the canvas.
Right-click cancels the drawing of the wire (control-click on MacOS).
</string>
<string name="tutorial7">Your first circuit is now functional.
To start the simulation, you can click on the Play button in the toolbar.
If you move the mouse over the toolbar, tool tips are shown.
</string>
<string name="tutorial8">
The simulation is now active. Switch the inputs by clicking on them.
</string>
<string name="tutorial9">
To stop the simulation, click on the Stop button in the toolbar.
</string>
<string name="tutorial10">
For completeness, the inputs and outputs should be labeled.
Right-click on an input to open a dialog. On MacOS control-click is used.
Here the input can be given a name.</string>
<string name="tutorial11">
Label all inputs and outputs.
</string>
<string name="tutorialUniqueIdents">
Inputs and outputs should always be uniquely named.
</string>
<string name="tutorialNotNeeded">
Skip Tutorial
</string>
</resources> </resources>

View File

@ -241,7 +241,8 @@
<string name="elem_Splitter">Divisor</string> <string name="elem_Splitter">Divisor</string>
<string name="elem_Splitter_tt">Divide o crea un haz de cables o un bus de datos con más de un bit. <string name="elem_Splitter_tt">Divide o crea un haz de cables o un bus de datos con más de un bit.
Con un bus es posible, por ejemplo, generar conexiones de 16 bits sin tener que generar 16 cables individuales. Con un bus es posible, por ejemplo, generar conexiones de 16 bits sin tener que generar 16 cables individuales.
Las 16 conexiones pueden agruparse en un cable.</string> Las 16 conexiones pueden agruparse en un cable.
El divisor tiene una dirección, es decir, sólo puede transmitir señales en una dirección.</string>
<string name="elem_Splitter_pin_in">Los bits de entrada {0}</string> <string name="elem_Splitter_pin_in">Los bits de entrada {0}</string>
<string name="elem_Splitter_pin_in_one">El bit de entrada {0}</string> <string name="elem_Splitter_pin_in_one">El bit de entrada {0}</string>
<string name="elem_Splitter_pin_out">Los bits de salida {0}</string> <string name="elem_Splitter_pin_out">Los bits de salida {0}</string>
@ -716,7 +717,8 @@
<string name="err_aSingleClockNecessary">Se necesita un componente de reloj. Todos los flip-flops deben usar una señal de reloj.</string> <string name="err_aSingleClockNecessary">Se necesita un componente de reloj. Todos los flip-flops deben usar una señal de reloj.</string>
<string name="err_analyseNoInputs">Este circuito no tiene entradas etiquetadas.</string> <string name="err_analyseNoInputs">Este circuito no tiene entradas etiquetadas.</string>
<string name="err_analyseNoOutputs">Este circuito no tiene salidas etiquetadas.</string> <string name="err_analyseNoOutputs">Este circuito no tiene salidas etiquetadas.</string>
<string name="err_breakTimeOut">Después de {0} ciclos, no se produjo ninguna interrupción en el punto de interrupción ''{1}''.</string> <string name="err_breakTimeOut">Después de {0} ciclos, no se produjo ninguna interrupción en el punto de interrupción ''{1}''.
Posiblemente el número de ciclos de tiempo muerto en el componente de interrupción deberían incrementarse.</string>
<string name="err_builder_exprNotSupported">Expresión {0} no soportada.</string> <string name="err_builder_exprNotSupported">Expresión {0} no soportada.</string>
<string name="err_builder_operationNotSupported">Operación {0} no soportada.</string> <string name="err_builder_operationNotSupported">Operación {0} no soportada.</string>
<string name="err_builder_couldNotFillLUT">Error creando la tabla de consulta (LUT).</string> <string name="err_builder_couldNotFillLUT">Error creando la tabla de consulta (LUT).</string>
@ -1257,7 +1259,7 @@
<string name="menu_saveData_tt">Guardar los datos en archivo CSV</string> <string name="menu_saveData_tt">Guardar los datos en archivo CSV</string>
<string name="menu_speedTest">Test de velocidad</string> <string name="menu_speedTest">Test de velocidad</string>
<string name="menu_speedTest_tt">Hace un test de velocidad calculando la frecuencia de reloj máxima.</string> <string name="menu_speedTest_tt">Hace un test de velocidad calculando la frecuencia de reloj máxima.</string>
<string name="menu_step">Paso</string> <string name="menu_step">Paso de puerta</string>
<string name="menu_step_tt">Calcula un paso de puerta simple</string> <string name="menu_step_tt">Calcula un paso de puerta simple</string>
<string name="menu_synthesise">Sintetizar</string> <string name="menu_synthesise">Sintetizar</string>
<string name="menu_synthesise_tt">Genera la expresión booleana mínima a partir de una tabla de verdad.</string> <string name="menu_synthesise_tt">Genera la expresión booleana mínima a partir de una tabla de verdad.</string>
@ -1723,4 +1725,55 @@ Por tanto, la señal 'D_out' estará también disponible para chequear el valor
<string name="msg_errorReadingToolchainConfig_N">Error al leer la configuración de la toolchain {0}</string> <string name="msg_errorReadingToolchainConfig_N">Error al leer la configuración de la toolchain {0}</string>
<string name="msg_commandStarted_N">¡El comando "{0}" ha empezado! ¡El procesado puede llevar un tiempo!</string> <string name="msg_commandStarted_N">¡El comando "{0}" ha empezado! ¡El procesado puede llevar un tiempo!</string>
<string name="msg_commandEnded_N">¡El comando "{0}" ha sido completado!</string> <string name="msg_commandEnded_N">¡El comando "{0}" ha sido completado!</string>
<string name="err_thereIsAUnnamedIO">Hay una entrada o una salida sin nombre</string>
<string name="err_NameOfIOIsInvalidOrNotUnique_N">La señal "{0}" no es válida o se ha usado varias veces</string>
<string name="err_substitutingError">Error al sustituir componentes para el análisis.</string>
<string name="err_evaluatingGenericsCode_N_N">Error en la evaluación del código genérico del circuito. Código {1} en el Componente: {0}</string>
<string name="msg_errParsingGenerics">Error al analizar código genérico</string>
<string name="key_generic">Parametrización genérica</string>
<string name="key_generic_tt">Declaraciones hechas para generar un circuito</string>
<string name="key_isGeneric">El circuito es genérico</string>
<string name="key_isGeneric_tt">Permite crear un circuito genérico</string>
<string name="key_showTutorial">Muestra el tutorial en el arranque</string>
<string name="key_showTutorial_tt">Habilita el tutorial</string>
<string name="stat_inputs">Entradas</string>
<string name="stat_bits">Bits</string>
<string name="stat_addrBits">Bits de dirección</string>
<string name="tutorial">Tutorial</string>
<string name="tutorial1">A continuación, podrás diseñar tu primer circuito tras un breve tutorial:
Primero, pon una entrada en el circuito. Encontrarás las entradas en el menú Componentes▸Entrada-Salida</string>
<string name="tutorial2">Ahora, añade una segunda entrada al circuito. También puedes hacer clic sobre la entrada que ha aparecido en la barra de herramientas.
Es mejor colocar la segunda entrada a dos espacios de rejilla debajo de la primera.
Puedes mover el circuito presionando el botón derecho del ratón.
Haciendo clic sobre las entradas puedes moverlas.</string>
<string name="tutorial3">A continuación vamos a insertar una puerta "OR Exclusiva".
Puedes encontrarla en el menú Componentes▸Lógica.
Coloca el componente a dos espacios de rejilla a la derecha de las entradas.</string>
<string name="tutorial4">El último componente que vamos a insertar es una salida.
Colócala a dos espacios de rejilla a la derecha de la puerta "OR Exclusiva".</string>
<string name="tutorial5">Para completar el circuito hay que dibujar los cables.
Haz clic en el punto rojo de la primera entrada y conecta el cable que aparece a una entrada de la puerta "OR Exclusiva"
haciendo clic en uno de los puntos azules de dicha puerta.
¡NO pinches y arrastres con el botón del ratón!</string>
<string name="tutorial6">Conecta los puntos rojos de las entradas con los puntos azules de la puerta "OR Exclusiva"
y el punto rojo de dicha puerta con el punto azul de la salida.
Así de fácil: un punto rojo va a un punto azul.</string>
<string name="tutorial7">Tu primer circuito ya funcionará.
Para empezar la simulación, puedes hacer clic en el botón "Simular" de la barra de herramientas.</string>
<string name="tutorial8">La simulación ya está activa. Ahora puedes cambiar los valores de las entradas haciendo clic en ellas.</string>
<string name="tutorial9">Para terminar la simulación, haz clic en el botón "Stop" de la barra de herramientas.</string>
<string name="tutorial10">Para que todo quede perfecto, tendrías que poner etiquetas a las entradas y salidas.
Haz clic con el botón derecho en una entrada para abrir un cuadro de diálogo.
En MacOS puedes usar el control-clic.
Así podrás nombrar la entrada.</string>
<string name="tutorial11">Etiqueta todas las entradas y salidas.</string>
<string name="tutorialUniqueIdents">Los nombres de las entradas y salidas deben ser únicos.</string>
<string name="tutorialNotNeeded">Saltar el tutorial</string>
<string name="menu_runToBreakMicro">Ejecutar hasta parar en modo de puerta simple.</string>
<string name="menu_runToBreakMicro_tt">Ejecuta todos los pasos de puerta sencillos hasta que se detecta un flanco de subida en un componente de parada.
Si no hay componente de parada, se ejecutan los pasos de puerta simple restantes.</string>
</resources> </resources>

View File

@ -111,7 +111,7 @@
This component can be used to realize any necessary propagation delay.</string> This component can be used to realize any necessary propagation delay.</string>
<string name="elem_Delay_pin_in">Input of the signal to be delayed.</string> <string name="elem_Delay_pin_in">Input of the signal to be delayed.</string>
<string name="elem_Delay_pin_out">The input signal delayed by one gate delay time.</string> <string name="elem_Delay_pin_out">The input signal delayed by one gate delay time.</string>
<string name="elem_Out">Out</string> <string name="elem_Out">Output</string>
<string name="elem_Out_tt">Can be used to display an output signal in a circuit. <string name="elem_Out_tt">Can be used to display an output signal in a circuit.
This element is also used to connect a circuit to an embedding circuit. This element is also used to connect a circuit to an embedding circuit.
In this case the connection is bidirectional. In this case the connection is bidirectional.
@ -246,7 +246,8 @@
<string name="elem_Splitter">Splitter</string> <string name="elem_Splitter">Splitter</string>
<string name="elem_Splitter_tt">Splits or creates a wire bundle or a data bus with more than one bit. <string name="elem_Splitter_tt">Splits or creates a wire bundle or a data bus with more than one bit.
With a bus it is e.g. possible to generate 16-bit connections without having to route 16 individual wires. With a bus it is e.g. possible to generate 16-bit connections without having to route 16 individual wires.
All 16 connections can be merged into one wire.</string> All 16 connections can be merged into one wire.
The splitter has a direction, meaning it can only transmit signals in one direction.</string>
<string name="elem_Splitter_pin_in">The input bits {0}.</string> <string name="elem_Splitter_pin_in">The input bits {0}.</string>
<string name="elem_Splitter_pin_in_one">The input bit {0}.</string> <string name="elem_Splitter_pin_in_one">The input bit {0}.</string>
<string name="elem_Splitter_pin_out">The output bits {0}.</string> <string name="elem_Splitter_pin_out">The output bits {0}.</string>
@ -725,7 +726,8 @@
<string name="err_aSingleClockNecessary">A single clock component is necessary. All flip-flops must use this clock signal.</string> <string name="err_aSingleClockNecessary">A single clock component is necessary. All flip-flops must use this clock signal.</string>
<string name="err_analyseNoInputs">The circuit has no labeled inputs</string> <string name="err_analyseNoInputs">The circuit has no labeled inputs</string>
<string name="err_analyseNoOutputs">The circuit has no labeled outputs</string> <string name="err_analyseNoOutputs">The circuit has no labeled outputs</string>
<string name="err_breakTimeOut">No break detected after {0} cycles at break point ''{1}''.</string> <string name="err_breakTimeOut">No break detected after {0} cycles at break point ''{1}''.
Possibly the number of timout cycles in the break component should be increased.</string>
<string name="err_builder_exprNotSupported">Expression {0} not supported</string> <string name="err_builder_exprNotSupported">Expression {0} not supported</string>
<string name="err_builder_operationNotSupported">Operation {0} not supported</string> <string name="err_builder_operationNotSupported">Operation {0} not supported</string>
<string name="err_builder_couldNotFillLUT">Error creating the lookup table.</string> <string name="err_builder_couldNotFillLUT">Error creating the lookup table.</string>
@ -1270,8 +1272,8 @@
<string name="menu_saveData_tt">Save data as CSV file</string> <string name="menu_saveData_tt">Save data as CSV file</string>
<string name="menu_speedTest">Speed Test</string> <string name="menu_speedTest">Speed Test</string>
<string name="menu_speedTest_tt">Performs a speed test by calculating the max. clock frequency.</string> <string name="menu_speedTest_tt">Performs a speed test by calculating the max. clock frequency.</string>
<string name="menu_step">Step</string> <string name="menu_step">Gate Step</string>
<string name="menu_step_tt">Calculating a single gate step</string> <string name="menu_step_tt">Calculates a single gate step</string>
<string name="menu_synthesise">Synthesise</string> <string name="menu_synthesise">Synthesise</string>
<string name="menu_synthesise_tt">Generates the minimal bool expressions described by a truth table.</string> <string name="menu_synthesise_tt">Generates the minimal bool expressions described by a truth table.</string>
<string name="menu_table_N_variables">{0} variables</string> <string name="menu_table_N_variables">{0} variables</string>
@ -1739,4 +1741,60 @@ Therefore, the signal 'D_out' is also available to check the value in this case.
<string name="msg_errorReadingToolchainConfig_N">Error while reading the toolchain configuration {0}</string> <string name="msg_errorReadingToolchainConfig_N">Error while reading the toolchain configuration {0}</string>
<string name="msg_commandStarted_N">Command "{0}" has been started! Processing may take some time!</string> <string name="msg_commandStarted_N">Command "{0}" has been started! Processing may take some time!</string>
<string name="msg_commandEnded_N">The command "{0}" has been completed!</string> <string name="msg_commandEnded_N">The command "{0}" has been completed!</string>
<string name="err_thereIsAUnnamedIO">There is a unnamed input or output!</string>
<string name="err_NameOfIOIsInvalidOrNotUnique_N">The signal name "{0}" is invalid or used multiple times!</string>
<string name="err_substitutingError">Error when substituting components for the analysis.</string>
<string name="err_evaluatingGenericsCode_N_N">Error in the evaluation of the generic code of the circuit. Code
{1}
at Component: {0}</string>
<string name="msg_errParsingGenerics">Error while parsing generics code.</string>
<string name="key_generic">Generic Parameterization</string>
<string name="key_generic_tt">Statements used to generify a circuit.</string>
<string name="key_isGeneric">Circuit is generic</string>
<string name="key_isGeneric_tt">Allows to create a generic circuit.</string>
<string name="key_showTutorial">Show Tutorial at Startup</string>
<string name="key_showTutorial_tt">Enables the tutorial.</string>
<string name="stat_inputs">Inputs</string>
<string name="stat_bits">Bits</string>
<string name="stat_addrBits">Addr. Bits</string>
<string name="tutorial">Tutorial</string>
<string name="tutorial1">In the following a short tutorial leads you to the first, simple circuit:
First, insert an input into the circuit. You will find the input in the menu Components▸IO.</string>
<string name="tutorial2">Now add a second input to the circuit. You can also click on the input
in the toolbar.
It is best to place the second input slightly below the first input.
You can move the circuit by holding down the right mouse button.
By clicking on components you can move them.</string>
<string name="tutorial3">Next, an "Exclusive Or" gate is to be inserted.
You can find this gate in the menu Components▸Logic.
Place this component with some distance to the right of the inputs.</string>
<string name="tutorial4">The last component to be inserted is an output.
Place it with some distance to the right of the "Exclusive Or" gate.</string>
<string name="tutorial5">In order to complete the circuit, connecting wires must be drawn.
Click on the red dot at the first input and connect it to an input of the "Exclusive Or" gate,
by clicking on a blue dot of the "Exclusive Or" gate afterwards.
Do NOT drag with mouse button down!</string>
<string name="tutorial6">Connect the red dot of the second input to the second blue dot of the
"Exclusive Or" gate and the red dot of the "Exclusive Or" gate to the blue dot of the output.
While drawing, you can pin the wire by clicking somewhere on the canvas.
Right-click cancels the drawing of the wire (control-click on MacOS).</string>
<string name="tutorial7">Your first circuit is now functional.
To start the simulation, you can click on the Play button in the toolbar.
If you move the mouse over the toolbar, tool tips are shown.</string>
<string name="tutorial8">The simulation is now active. Switch the inputs by clicking on them.</string>
<string name="tutorial9">To stop the simulation, click on the Stop button in the toolbar.</string>
<string name="tutorial10">For completeness, the inputs and outputs should be labeled.
Right-click on an input to open a dialog. On MacOS control-click is used.
Here the input can be given a name.</string>
<string name="tutorial11">Label all inputs and outputs.</string>
<string name="tutorialUniqueIdents">Inputs and outputs should always be uniquely named.</string>
<string name="tutorialNotNeeded">Skip Tutorial</string>
<string name="menu_runToBreakMicro">Run To Break in Single Gate Mode</string>
<string name="menu_runToBreakMicro_tt">Executes all single gate steps until a rising edge is detected on a break component.
If there is no break component, the remaining single gate steps are executed.</string>
</resources> </resources>

View File

@ -114,7 +114,7 @@
<string name="elem_Delay_pin_in">Input of the signal to be delayed.</string> <string name="elem_Delay_pin_in">Input of the signal to be delayed.</string>
<string name="elem_Delay_pin_out">The input signal delayed by one gate delay time.</string> <string name="elem_Delay_pin_out">The input signal delayed by one gate delay time.</string>
<!-- IO --> <!-- IO -->
<string name="elem_Out">Out</string> <string name="elem_Out">Output</string>
<string name="elem_Out_tt">Can be used to display an output signal in a circuit. <string name="elem_Out_tt">Can be used to display an output signal in a circuit.
This element is also used to connect a circuit to an embedding circuit. This element is also used to connect a circuit to an embedding circuit.
In this case the connection is bidirectional. In this case the connection is bidirectional.

View File

@ -68,7 +68,7 @@ public class TestLang extends TestCase {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
for (String key : map.keySet()) { for (String key : map.keySet()) {
if (!keys.contains(key)) { if (!keys.contains(key)) {
if (!(key.startsWith("key_") || key.startsWith("elem_"))) { if (!(key.startsWith("key_") || key.startsWith("elem_") || key.startsWith("tutorial"))) {
if (sb.length() > 0) if (sb.length() > 0)
sb.append(", "); sb.append(", ");
sb.append('"').append(key).append('"'); sb.append('"').append(key).append('"');

View File

@ -12,8 +12,8 @@ import junit.framework.TestCase;
public class LineBreakerTest extends TestCase { public class LineBreakerTest extends TestCase {
public void testBreakLines() throws Exception { public void testBreakLines() throws Exception {
assertEquals("this is a test string", new LineBreaker(60).breakLines("this \n\n is \n a test \n\r string")); assertEquals("this\nis a test string", new LineBreaker(60).breakLines("this \n\n is \n a test \n\r string"));
assertEquals("this is a test\nstring", new LineBreaker(14).breakLines("this \n\n is \n a test \n\r string")); assertEquals("this\nis a test\nstring", new LineBreaker(14).breakLines("this \n\n is \n a test \n\r string"));
assertEquals("This is a test string. This\n" + assertEquals("This is a test string. This\n" +
"is a test string. This is a\n" + "is a test string. This is a\n" +
"test string.", new LineBreaker(27).breakLines("This is a test string. This is a test string. This is a test string.")); "test string.", new LineBreaker(27).breakLines("This is a test string. This is a test string. This is a test string."));