From 94d42a60889659c67ffa8c58a45b49e90383db35 Mon Sep 17 00:00:00 2001 From: hneemann Date: Wed, 25 Sep 2019 09:02:01 +0200 Subject: [PATCH 1/7] simplified table modification --- .../neemann/digital/analyse/TruthTable.java | 29 ++++++------------- .../analyse/quinemc/BoolTableByteArray.java | 24 ++++++++------- .../digital/fsm/TransitionTableCreator.java | 6 ++-- .../gui/components/table/TableDialog.java | 26 ++++++++--------- src/main/resources/lang/lang_de.xml | 3 ++ src/main/resources/lang/lang_en.xml | 2 ++ 6 files changed, 43 insertions(+), 47 deletions(-) diff --git a/src/main/java/de/neemann/digital/analyse/TruthTable.java b/src/main/java/de/neemann/digital/analyse/TruthTable.java index 1bbd7f229..e865f7f7c 100644 --- a/src/main/java/de/neemann/digital/analyse/TruthTable.java +++ b/src/main/java/de/neemann/digital/analyse/TruthTable.java @@ -18,6 +18,7 @@ import de.neemann.digital.analyse.quinemc.ThreeStateValue; import de.neemann.digital.lang.Lang; import java.io.*; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; /** @@ -52,7 +53,7 @@ public class TruthTable { */ public void save(File filename) throws IOException { XStream xStream = getxStream(); - try (Writer out = new OutputStreamWriter(new FileOutputStream(filename), "utf-8")) { + try (Writer out = new OutputStreamWriter(new FileOutputStream(filename), StandardCharsets.UTF_8)) { out.write("\n"); xStream.marshal(this, new PrettyPrintWriter(out)); } @@ -68,7 +69,7 @@ public class TruthTable { if (results.size() > 63) throw new IOException(Lang.get("err_tableHasToManyResultColumns")); - try (Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filename), "utf-8"))) { + try (Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filename), StandardCharsets.UTF_8))) { saveHex(out); } } @@ -456,30 +457,18 @@ public class TruthTable { } /** - * Sets the don't cares to a given value + * Modifies all column in the table * - * @param b the value to set + * @param m the modifier to use + * @return this for chained calls */ - public void setXto(boolean b) { + public TruthTable modifyValues(BoolTableByteArray.TableModifier m) { for (Result r : results) { BoolTable bt = r.getValues(); if (bt instanceof BoolTableByteArray) - ((BoolTableByteArray) bt).setXTo(b ? 1 : 0); - } - } - - /** - * Set all table entries to the given value. - * Zero and one behave as expected. All other values represent "don't care" - * - * @param value the value to set - */ - public void setAllTo(int value) { - for (Result r : results) { - BoolTable bt = r.getValues(); - if (bt instanceof BoolTableByteArray) - ((BoolTableByteArray) bt).setAllTo(value); + ((BoolTableByteArray) bt).modify(m); } + return this; } /** diff --git a/src/main/java/de/neemann/digital/analyse/quinemc/BoolTableByteArray.java b/src/main/java/de/neemann/digital/analyse/quinemc/BoolTableByteArray.java index 09d56c76e..3228e05a5 100644 --- a/src/main/java/de/neemann/digital/analyse/quinemc/BoolTableByteArray.java +++ b/src/main/java/de/neemann/digital/analyse/quinemc/BoolTableByteArray.java @@ -79,23 +79,25 @@ public class BoolTableByteArray implements BoolTable { } /** - * Sets the don't cares to the given value + * Modifies all the table elements using the given modifier. * - * @param value the value + * @param m the modifier */ - public void setXTo(int value) { + public void modify(TableModifier m) { for (int i = 0; i < table.length; i++) - if (table[i] > 1) - table[i] = (byte) value; + table[i] = m.modify(table[i]); } /** - * Sets all entries to the given value - * - * @param value the value + * Modifier to modify the table */ - public void setAllTo(int value) { - for (int i = 0; i < table.length; i++) - table[i] = (byte) value; + public interface TableModifier { + /** + * Creates the modified value + * + * @param b the original value + * @return the modified value + */ + byte modify(byte b); } } diff --git a/src/main/java/de/neemann/digital/fsm/TransitionTableCreator.java b/src/main/java/de/neemann/digital/fsm/TransitionTableCreator.java index 563ee337b..042ce97f9 100644 --- a/src/main/java/de/neemann/digital/fsm/TransitionTableCreator.java +++ b/src/main/java/de/neemann/digital/fsm/TransitionTableCreator.java @@ -83,7 +83,7 @@ public class TransitionTableCreator { // create state variables ArrayList vars = new ArrayList<>(); for (int i = stateBits - 1; i >= 0; i--) { - final Variable var = new Variable(STATE_VAR+"_" + i + "^n"); + final Variable var = new Variable(STATE_VAR + "_" + i + "^n"); vars.add(var); boolean initVal = (initState & (1 << i)) != 0; modelAnalyserInfo.setSequentialInitValue(var.getIdentifier(), initVal ? 1 : 0); @@ -93,7 +93,7 @@ public class TransitionTableCreator { // create the next state result variables for (int i = stateBits - 1; i >= 0; i--) - truthTable.addResult(STATE_VAR+"_" + i + "^{n+1}"); + truthTable.addResult(STATE_VAR + "_" + i + "^{n+1}"); // add the output variables TreeSet results = new TreeSet<>(); @@ -108,7 +108,7 @@ public class TransitionTableCreator { } // set all to dc - truthTable.setAllTo(2); + truthTable.modifyValues(v -> (byte) 2); // set state output variables for (State s : states) { diff --git a/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java b/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java index 6964b77b2..7d4a42c01 100644 --- a/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java +++ b/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java @@ -366,44 +366,44 @@ public class TableDialog extends JDialog { setMenu.add(new ToolTipAction(Lang.get("menu_table_setXTo0")) { @Override public void actionPerformed(ActionEvent e) { - TruthTable t = model.getTable(); - t.setXto(false); - setModel(new TruthTableTableModel(t)); + modifyTable(v -> v > 1 ? 0 : v); } }.setToolTip(Lang.get("menu_table_setXTo0_tt")).createJMenuItem()); setMenu.add(new ToolTipAction(Lang.get("menu_table_setXTo1")) { @Override public void actionPerformed(ActionEvent e) { - TruthTable t = model.getTable(); - t.setXto(true); - setModel(new TruthTableTableModel(t)); + modifyTable(v -> v > 1 ? 1 : v); } }.setToolTip(Lang.get("menu_table_setXTo1_tt")).createJMenuItem()); setMenu.add(new ToolTipAction(Lang.get("menu_table_setAllToX")) { @Override public void actionPerformed(ActionEvent e) { - setAllValuesTo(2); + modifyTable(v -> (byte) 2); } }.setToolTip(Lang.get("menu_table_setAllToX_tt")).createJMenuItem()); setMenu.add(new ToolTipAction(Lang.get("menu_table_setAllTo0")) { @Override public void actionPerformed(ActionEvent e) { - setAllValuesTo(0); + modifyTable(v -> (byte) 0); } }.setToolTip(Lang.get("menu_table_setAllTo0_tt")).createJMenuItem()); setMenu.add(new ToolTipAction(Lang.get("menu_table_setAllTo1")) { @Override public void actionPerformed(ActionEvent e) { - setAllValuesTo(1); + modifyTable(v -> (byte) 1); } }.setToolTip(Lang.get("menu_table_setAllTo1_tt")).createJMenuItem()); + setMenu.add(new ToolTipAction(Lang.get("menu_table_invert")) { + @Override + public void actionPerformed(ActionEvent e) { + modifyTable(v -> v > 1 ? v : (byte) (1 - v)); + } + }.setToolTip(Lang.get("menu_table_invert_tt")).createJMenuItem()); return setMenu; } - private void setAllValuesTo(int value) { - TruthTable t = model.getTable(); - t.setAllTo(value); - setModel(new TruthTableTableModel(t)); + private void modifyTable(BoolTableByteArray.TableModifier m) { + setModel(new TruthTableTableModel(model.getTable().modifyValues(m))); } private JMenu createCreateMenu() { diff --git a/src/main/resources/lang/lang_de.xml b/src/main/resources/lang/lang_de.xml index 76bf5475a..61f12aff5 100644 --- a/src/main/resources/lang/lang_de.xml +++ b/src/main/resources/lang/lang_de.xml @@ -1565,6 +1565,9 @@ Sind evtl. die Namen der Variablen nicht eindeutig? Setzt alle Werte auf Null. Alles auf 1 setzen Setzt alle Werte auf Eins. + Alle Bits invertieren + Aus einer "1" wird eine "0" und umgekehrt. Don't Cares bleiben unverändert. + Lösungsdialog anzeigen Zeigt den Lösungsdialog wieder an, wenn er manuell geschlossen wurde. Löschen diff --git a/src/main/resources/lang/lang_en.xml b/src/main/resources/lang/lang_en.xml index f079a5e6f..786738aae 100644 --- a/src/main/resources/lang/lang_en.xml +++ b/src/main/resources/lang/lang_en.xml @@ -1548,6 +1548,8 @@ Set all values to zero. Set all to 1 Set all values to one. + Invert all bits + A "1" becomes a "0" and vice versa. Don't cares remain unchanged. Show results dialog Shows the results dialog again if it was closed manually. Delete From e17fbfe8ff837782ce4dad9e7314b8c9d7e36699 Mon Sep 17 00:00:00 2001 From: hneemann Date: Wed, 25 Sep 2019 17:09:45 +0200 Subject: [PATCH 2/7] new table undo compiles --- .../neemann/digital/analyse/TruthTable.java | 52 ++++- .../digital/analyse/TruthTableTableModel.java | 74 ++++--- .../analyse/quinemc/BoolTableByteArray.java | 11 + .../table/LaTeXExpressionListener.java | 8 +- .../gui/components/table/ProgressDialog.java | 2 +- .../gui/components/table/ReorderInputs.java | 22 +- .../gui/components/table/ReorderOutputs.java | 17 +- .../gui/components/table/TableDialog.java | 208 ++++++++++++------ .../components/table/TableReorderManager.java | 49 +++-- src/main/resources/lang/lang_de.xml | 2 - src/main/resources/lang/lang_en.xml | 2 - src/main/resources/lang/lang_es.xml | 2 - src/main/resources/lang/lang_es_ref.xml | 2 - src/main/resources/lang/lang_pt.xml | 2 - src/main/resources/lang/lang_pt_ref.xml | 2 - .../de/neemann/digital/docu/ScreenShots.java | 3 +- .../table/LaTeXExpressionListenerTest.java | 3 +- .../components/table/TestReorderInputs.java | 10 +- .../components/table/TestReorderOutputs.java | 5 +- 19 files changed, 317 insertions(+), 159 deletions(-) diff --git a/src/main/java/de/neemann/digital/analyse/TruthTable.java b/src/main/java/de/neemann/digital/analyse/TruthTable.java index e865f7f7c..329d668ac 100644 --- a/src/main/java/de/neemann/digital/analyse/TruthTable.java +++ b/src/main/java/de/neemann/digital/analyse/TruthTable.java @@ -16,15 +16,17 @@ import de.neemann.digital.analyse.quinemc.BoolTable; import de.neemann.digital.analyse.quinemc.BoolTableByteArray; import de.neemann.digital.analyse.quinemc.ThreeStateValue; import de.neemann.digital.lang.Lang; +import de.neemann.digital.undo.Copyable; import java.io.*; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Collection; /** * The description of a truth table. */ -public class TruthTable { +public class TruthTable implements Copyable { private final ArrayList variables; private final ArrayList results; @@ -148,6 +150,29 @@ public class TruthTable { } } + private TruthTable(TruthTable truthTable) { + variables = new ArrayList<>(truthTable.variables.size()); + for (Variable v : truthTable.variables) + variables.add(new Variable(v.getIdentifier())); + results = new ArrayList<>(); + for (int i = 0; i < truthTable.getResultCount(); i++) { + Result result = truthTable.results.get(i); + addResult(result.getName(), new BoolTableByteArray(result.values)); + } + this.modelAnalyzerInfo = truthTable.modelAnalyzerInfo; + } + + /** + * Clears the table and sets the given variables + * + * @param vars the variables to use + */ + public void clear(Collection vars) { + variables.clear(); + variables.addAll(vars); + results.clear(); + } + /** * Returns the number of rows * @@ -489,6 +514,31 @@ public class TruthTable { return modelAnalyzerInfo; } + @Override + public TruthTable createDeepCopy() { + return new TruthTable(this); + } + + /** + * @return the names of all input variables + */ + public ArrayList getVarNames() { + ArrayList names = new ArrayList<>(); + for (Variable v : variables) + names.add(v.getIdentifier()); + return names; + } + + /** + * @return the names of al result variables + */ + public ArrayList getResultNames() { + ArrayList names = new ArrayList<>(); + for (Result r : results) + names.add(r.getName()); + return names; + } + /** * A single result column */ diff --git a/src/main/java/de/neemann/digital/analyse/TruthTableTableModel.java b/src/main/java/de/neemann/digital/analyse/TruthTableTableModel.java index 0b8bc348b..c76925f13 100644 --- a/src/main/java/de/neemann/digital/analyse/TruthTableTableModel.java +++ b/src/main/java/de/neemann/digital/analyse/TruthTableTableModel.java @@ -6,6 +6,8 @@ package de.neemann.digital.analyse; import de.neemann.digital.analyse.quinemc.BoolTable; +import de.neemann.digital.undo.ModifyException; +import de.neemann.digital.undo.UndoManager; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; @@ -23,31 +25,31 @@ public class TruthTableTableModel implements TableModel { */ public static final String[] STATENAMES = new String[]{"0", "1", "x"}; - private final TruthTable truthTable; private final ArrayList listeners = new ArrayList<>(); + private final UndoManager undoManager; /** * Creates a new instance * - * @param truthTable the truthTable which is to visualize + * @param undoManager the undoManager */ - public TruthTableTableModel(TruthTable truthTable) { - this.truthTable = truthTable; + public TruthTableTableModel(UndoManager undoManager) { + this.undoManager = undoManager; } @Override public int getRowCount() { - return truthTable.getRows(); + return undoManager.getActual().getRows(); } @Override public int getColumnCount() { - return truthTable.getCols(); + return undoManager.getActual().getCols(); } @Override public String getColumnName(int columnIndex) { - return truthTable.getColumnName(columnIndex); + return undoManager.getActual().getColumnName(columnIndex); } @Override @@ -57,35 +59,52 @@ public class TruthTableTableModel implements TableModel { @Override public boolean isCellEditable(int rowIndex, int columnIndex) { - return truthTable.isEditable(columnIndex); + return undoManager.getActual().isEditable(columnIndex); } @Override public Object getValueAt(int rowIndex, int columnIndex) { - return truthTable.getValue(rowIndex, columnIndex); + return undoManager.getActual().getValue(rowIndex, columnIndex); } @Override public void setValueAt(Object aValue, int rowIndex, int columnIndex) { if (aValue instanceof Integer) - truthTable.setValue(rowIndex, columnIndex, (Integer) aValue); + setValue(rowIndex, columnIndex, (Integer) aValue); if (aValue instanceof String) { if (aValue.toString().equals("0")) - truthTable.setValue(rowIndex, columnIndex, 0); + setValue(rowIndex, columnIndex, 0); else if (aValue.toString().equals("1")) - truthTable.setValue(rowIndex, columnIndex, 1); + setValue(rowIndex, columnIndex, 1); else - truthTable.setValue(rowIndex, columnIndex, 2); + setValue(rowIndex, columnIndex, 2); } fireModelEvent(rowIndex); } + private void setValue(int rowIndex, int columnIndex, int val) { + try { + undoManager.apply(truthTable -> truthTable.setValue(rowIndex, columnIndex, val)); + } catch (ModifyException e) { + e.printStackTrace(); + } + } + private void fireModelEvent(int rowIndex) { TableModelEvent e = new TableModelEvent(this, rowIndex); for (TableModelListener l : listeners) l.tableChanged(e); } + /** + * Fires a structural table change + */ + public void fireTableChanged() { + TableModelEvent e = new TableModelEvent(this, HEADER_ROW); + for (TableModelListener l : listeners) + l.tableChanged(e); + } + @Override public void addTableModelListener(TableModelListener l) { listeners.add(l); @@ -95,13 +114,6 @@ public class TruthTableTableModel implements TableModel { public void removeTableModelListener(TableModelListener l) { } - /** - * @return the truth table used by this model - */ - public TruthTable getTable() { - return truthTable; - } - /** * Sets the column name * @@ -109,7 +121,11 @@ public class TruthTableTableModel implements TableModel { * @param name the new name */ public void setColumnName(int columnIndex, String name) { - truthTable.setColumnName(columnIndex, name); + try { + undoManager.apply(truthTable -> truthTable.setColumnName(columnIndex, name)); + } catch (ModifyException e) { + e.printStackTrace(); + } fireModelEvent(HEADER_ROW); } @@ -121,18 +137,26 @@ public class TruthTableTableModel implements TableModel { */ public void incValue(BoolTable boolTable, int row) { int col = -1; - for (int i = 0; i < truthTable.getResultCount(); i++) { - if (truthTable.getResult(i) == boolTable) { + TruthTable tt = undoManager.getActual(); + for (int i = 0; i < tt.getResultCount(); i++) { + if (tt.getResult(i) == boolTable) { col = i; break; } } if (col >= 0) { - col += truthTable.getVars().size(); - int value = truthTable.getValue(row, col); + col += tt.getVars().size(); + int value = tt.getValue(row, col); if (value == 2) value = 0; else value++; setValueAt(value, row, col); } } + + /** + * @return the truth table shown + */ + public TruthTable getTable() { + return undoManager.getActual(); + } } diff --git a/src/main/java/de/neemann/digital/analyse/quinemc/BoolTableByteArray.java b/src/main/java/de/neemann/digital/analyse/quinemc/BoolTableByteArray.java index 3228e05a5..5ed3f589d 100644 --- a/src/main/java/de/neemann/digital/analyse/quinemc/BoolTableByteArray.java +++ b/src/main/java/de/neemann/digital/analyse/quinemc/BoolTableByteArray.java @@ -32,6 +32,17 @@ public class BoolTableByteArray implements BoolTable { this.table = table; } + /** + * Creates a new instance + * + * @param values the values to initialize the table + */ + public BoolTableByteArray(BoolTable values) { + table = new byte[values.size()]; + for (int i = 0; i < values.size(); i++) + table[i] = (byte) values.get(i).asInt(); + } + @Override public int size() { return table.length; diff --git a/src/main/java/de/neemann/digital/gui/components/table/LaTeXExpressionListener.java b/src/main/java/de/neemann/digital/gui/components/table/LaTeXExpressionListener.java index 001182e0a..883680621 100644 --- a/src/main/java/de/neemann/digital/gui/components/table/LaTeXExpressionListener.java +++ b/src/main/java/de/neemann/digital/gui/components/table/LaTeXExpressionListener.java @@ -5,7 +5,7 @@ */ package de.neemann.digital.gui.components.table; -import de.neemann.digital.analyse.TruthTableTableModel; +import de.neemann.digital.analyse.TruthTable; import de.neemann.digital.analyse.expression.Expression; import de.neemann.digital.analyse.expression.ExpressionException; import de.neemann.digital.analyse.expression.NamedExpression; @@ -15,10 +15,10 @@ import de.neemann.digital.draw.graphics.text.formatter.LaTeXFormatter; final class LaTeXExpressionListener implements ExpressionListener { private final StringBuilder sb; - LaTeXExpressionListener(TruthTableTableModel model) throws ExpressionException { + LaTeXExpressionListener(TruthTable truthTable) throws ExpressionException { sb = new StringBuilder(); - if (model.getTable().getRows() <= 256) { - String text = new TruthTableFormatterLaTeX().format(model.getTable()); + if (truthTable.getRows() <= 256) { + String text = new TruthTableFormatterLaTeX().format(truthTable); sb.append(text); } sb.append("\\begin{eqnarray*}\n"); diff --git a/src/main/java/de/neemann/digital/gui/components/table/ProgressDialog.java b/src/main/java/de/neemann/digital/gui/components/table/ProgressDialog.java index 957ba956c..a12a9b42b 100644 --- a/src/main/java/de/neemann/digital/gui/components/table/ProgressDialog.java +++ b/src/main/java/de/neemann/digital/gui/components/table/ProgressDialog.java @@ -27,7 +27,7 @@ public class ProgressDialog extends JDialog implements ExpressionCreator.Progres super(tableDialog, false); setDefaultCloseOperation(DISPOSE_ON_CLOSE); - bar = new JProgressBar(0, tableDialog.getModel().getTable().getResultCount()); + bar = new JProgressBar(0, tableDialog.getUndoManager().getActual().getResultCount()); int b = Screen.getInstance().getFontSize(); bar.setBorder(BorderFactory.createEmptyBorder(b, b, b, b)); final JLabel label = new JLabel(Lang.get("msg_optimizationInProgress")); diff --git a/src/main/java/de/neemann/digital/gui/components/table/ReorderInputs.java b/src/main/java/de/neemann/digital/gui/components/table/ReorderInputs.java index dc01a4a0f..80381ec96 100644 --- a/src/main/java/de/neemann/digital/gui/components/table/ReorderInputs.java +++ b/src/main/java/de/neemann/digital/gui/components/table/ReorderInputs.java @@ -55,10 +55,9 @@ public class ReorderInputs { /** * Creates a new table matching the actual state of the items * - * @return the new table * @throws ExpressionException ExpressionException */ - public TruthTable reorder() throws ExpressionException { + public void reorder() throws ExpressionException { ArrayList newVars = new ArrayList<>(); ArrayList deletedVars = new ArrayList<>(table.getVars()); @@ -79,21 +78,20 @@ public class ReorderInputs { if (newVars.size() < 2) throw new ExpressionException(Lang.get("err_tableBecomesToSmall")); - TruthTable newTable = new TruthTable(newVars); - newTable.setModelAnalyzerInfo(table.getModelAnalyzerInfo()); - for (int j = 0; j < table.getResultCount(); j++) - newTable.addResult(table.getResultName(j)); + TruthTable oldTable = this.table.createDeepCopy(); - ContextFiller fc = new ContextFiller(newTable.getVars()); + table.clear(newVars); + for (int j = 0; j < oldTable.getResultCount(); j++) + table.addResult(oldTable.getResultName(j)); + + ContextFiller fc = new ContextFiller(table.getVars()); for (Variable v : deletedVars) fc.set(v, false); - for (int row = 0; row < newTable.getRows(); row++) { + for (int row = 0; row < table.getRows(); row++) { fc.setContextTo(row); - for (int t = 0; t < newTable.getResultCount(); t++) - newTable.setByContext(t, fc, table.getByContext(t, fc)); + for (int t = 0; t < table.getResultCount(); t++) + table.setByContext(t, fc, oldTable.getByContext(t, fc)); } - - return newTable; } } diff --git a/src/main/java/de/neemann/digital/gui/components/table/ReorderOutputs.java b/src/main/java/de/neemann/digital/gui/components/table/ReorderOutputs.java index 1f45585a6..ecb17b8c3 100644 --- a/src/main/java/de/neemann/digital/gui/components/table/ReorderOutputs.java +++ b/src/main/java/de/neemann/digital/gui/components/table/ReorderOutputs.java @@ -53,23 +53,20 @@ public class ReorderOutputs { /** * Creates a new table matching the actual state of the items * - * @return the new table * @throws ExpressionException ExpressionException */ - public TruthTable reorder() throws ExpressionException { - TruthTable newTable = new TruthTable(table.getVars()); - newTable.setModelAnalyzerInfo(table.getModelAnalyzerInfo()); + public void reorder() throws ExpressionException { + TruthTable oldTable = table.createDeepCopy(); + table.clear(oldTable.getVars()); for (String name : names) { - for (int i = 0; i < table.getResultCount(); i++) - if (table.getResultName(i).equals(name)) { - newTable.addResult(table.getResultName(i), table.getResult(i)); + for (int i = 0; i < oldTable.getResultCount(); i++) + if (oldTable.getResultName(i).equals(name)) { + table.addResult(oldTable.getResultName(i), oldTable.getResult(i)); break; } } - if (newTable.getResultCount() < 1) + if (table.getResultCount() < 1) throw new ExpressionException(Lang.get("err_oneResultIsRequired")); - - return newTable; } } diff --git a/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java b/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java index 7d4a42c01..fb0ff162d 100644 --- a/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java +++ b/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java @@ -41,6 +41,8 @@ import de.neemann.digital.gui.components.table.hardware.GenerateCUPL; import de.neemann.digital.gui.components.table.hardware.GenerateFile; import de.neemann.digital.gui.components.table.hardware.HardwareDescriptionGenerator; import de.neemann.digital.lang.Lang; +import de.neemann.digital.undo.ModifyException; +import de.neemann.digital.undo.UndoManager; import de.neemann.gui.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -66,7 +68,7 @@ import java.util.prefs.Preferences; import static de.neemann.digital.analyse.ModelAnalyser.addOne; /** - * + * The dialog used to show the truth table. */ public class TableDialog extends JDialog { private static final Logger LOGGER = LoggerFactory.getLogger(TableDialog.class); @@ -102,15 +104,16 @@ public class TableDialog extends JDialog { private final ToolTipAction karnaughMenuAction; private final HashMap availGenerators = new HashMap<>(); private final JMenu hardwareMenu; + private final TruthTableTableModel model; private JCheckBoxMenuItem createJK; private File filename; - private TruthTableTableModel model; private int columnIndex; private AllSolutionsDialog allSolutionsDialog; private ExpressionListenerStore lastGeneratedExpressions; private KarnaughMapDialog kvMap; private JMenuItem lastUsedGenratorMenuItem; private Mouse mouse = Mouse.getMouse(); + private UndoManager undoManager; /** * Creates a new instance @@ -122,10 +125,15 @@ public class TableDialog extends JDialog { */ public TableDialog(Window parent, TruthTable truthTable, ElementLibrary library, File filename) { super(parent, Lang.get("win_table")); + undoManager = new UndoManager<>(truthTable); this.library = library; this.shapeFactory = library.getShapeFactory(); this.filename = filename; setDefaultCloseOperation(DISPOSE_ON_CLOSE); + + model = new TruthTableTableModel(undoManager); + model.addTableModelListener(new CalculationTableModelListener()); + kvMap = new KarnaughMapDialog(this, (boolTable, row) -> model.incValue(boolTable, row)); statusBar = new ExpressionComponent(); @@ -182,63 +190,90 @@ public class TableDialog extends JDialog { } bar.add(sizeMenu); - JMenu columnsMenu = new JMenu(Lang.get("menu_table_columns")); - bar.add(columnsMenu); - columnsMenu.add(new ToolTipAction(Lang.get("menu_table_reorder_inputs")) { + JMenu edit = new JMenu(Lang.get("menu_edit")); + bar.add(edit); + + addUndoRedo(edit); + + edit.addSeparator(); + + edit.add(new ToolTipAction(Lang.get("menu_table_reorder_inputs")) { @Override public void actionPerformed(ActionEvent e) { - ReorderInputs ri = new ReorderInputs(model.getTable()); - if (new ElementOrderer<>(TableDialog.this, Lang.get("menu_table_reorder_inputs"), ri.getItems()) + ArrayList varNames = undoManager.getActual().getVarNames(); + if (new ElementOrderer<>(TableDialog.this, Lang.get("menu_table_reorder_inputs"), new ElementOrderer.ListOrder<>(varNames)) .addDeleteButton() .addOkButton() .showDialog()) { + try { - setModel(new TruthTableTableModel(ri.reorder())); - } catch (ExpressionException e1) { + undoManager.apply(tt -> { + try { + new ReorderInputs(tt, varNames).reorder(); + tableChanged(); + } catch (ExpressionException ex) { + throw new ModifyException("failed to reorder", ex); + } + }); + } catch (ModifyException e1) { new ErrorMessage().addCause(e1).show(TableDialog.this); } } } }.createJMenuItem()); - columnsMenu.add(new ToolTipAction(Lang.get("menu_table_columnsAddVariable")) { + edit.add(new ToolTipAction(Lang.get("menu_table_columnsAddVariable")) { @Override public void actionPerformed(ActionEvent actionEvent) { - TruthTable t = model.getTable(); - t.addVariable(); - setModel(new TruthTableTableModel(t)); + try { + undoManager.apply(TruthTable::addVariable); + tableChanged(); + } catch (ModifyException e) { + new ErrorMessage().addCause(e).show(TableDialog.this); + } } }.setToolTip(Lang.get("menu_table_columnsAddVariable_tt")).createJMenuItem()); - columnsMenu.add(new ToolTipAction(Lang.get("menu_table_reorder_outputs")) { + edit.add(new ToolTipAction(Lang.get("menu_table_reorder_outputs")) { @Override public void actionPerformed(ActionEvent e) { - ReorderOutputs ro = new ReorderOutputs(model.getTable()); - if (new ElementOrderer<>(TableDialog.this, Lang.get("menu_table_reorder_outputs"), ro.getItems()) + ArrayList resultNames = undoManager.getActual().getResultNames(); + if (new ElementOrderer<>(TableDialog.this, Lang.get("menu_table_reorder_outputs"), new ElementOrderer.ListOrder<>(resultNames)) .addDeleteButton() .addOkButton() .showDialog()) { try { - setModel(new TruthTableTableModel(ro.reorder())); - } catch (ExpressionException e1) { + undoManager.apply(tt -> { + try { + new ReorderOutputs(tt, resultNames).reorder(); + tableChanged(); + } catch (ExpressionException ex) { + throw new ModifyException("failed to reorder", ex); + } + }); + } catch (ModifyException e1) { new ErrorMessage().addCause(e1).show(TableDialog.this); } } } }.createJMenuItem()); - columnsMenu.add(new ToolTipAction(Lang.get("menu_table_columnsAdd")) { + edit.add(new ToolTipAction(Lang.get("menu_table_columnsAdd")) { @Override public void actionPerformed(ActionEvent actionEvent) { - TruthTable t = model.getTable(); - t.addResult(); - setModel(new TruthTableTableModel(t)); + try { + undoManager.apply(TruthTable::addResult); + tableChanged(); + } catch (ModifyException e) { + new ErrorMessage().addCause(e).show(TableDialog.this); + } + } }.setToolTip(Lang.get("menu_table_columnsAdd_tt")).createJMenuItem()); - bar.add(columnsMenu); + edit.addSeparator(); - bar.add(createSetMenu()); + createSetMenuEntries(edit); hardwareMenu = createCreateMenu(); bar.add(hardwareMenu); @@ -256,14 +291,55 @@ public class TableDialog extends JDialog { setJMenuBar(bar); - setModel(new TruthTableTableModel(truthTable)); - getContentPane().add(new JScrollPane(table)); getContentPane().add(statusBar, BorderLayout.SOUTH); pack(); setLocationRelativeTo(parent); } + private void addUndoRedo(JMenu edit) { + final ToolTipAction undo = new ToolTipAction(Lang.get("menu_undo")) { + @Override + public void actionPerformed(ActionEvent actionEvent) { + if (undoManager.undoAvailable()) { + try { + undoManager.undo(); + tableChanged(); + } catch (ModifyException e) { + new ErrorMessage().addCause(e).show(TableDialog.this); + } + } + } + }.setAcceleratorCTRLplus("Z"); + final ToolTipAction redo = new ToolTipAction(Lang.get("menu_redo")) { + @Override + public void actionPerformed(ActionEvent actionEvent) { + if (undoManager.redoAvailable()) { + try { + undoManager.redo(); + tableChanged(); + } catch (ModifyException e) { + new ErrorMessage().addCause(e).show(TableDialog.this); + } + } + } + }.setAcceleratorCTRLplus("Y"); + edit.add(undo.createJMenuItem()); + edit.add(redo.createJMenuItem()); + undoManager.addListener(() -> { + undo.setEnabled(undoManager.undoAvailable()); + redo.setEnabled(undoManager.redoAvailable()); + }); + undo.setEnabled(undoManager.undoAvailable()); + redo.setEnabled(undoManager.redoAvailable()); + } + + void tableChanged() { + karnaughMenuAction.setEnabled(undoManager.getActual().getVars().size() <= 4); + calculateExpressions(); + model.fireTableChanged(); + } + private void editColumnName(int columnIndex, Point pos) { ElementAttributes attr = new ElementAttributes(); final String name = model.getColumnName(columnIndex); @@ -290,7 +366,8 @@ public class TableDialog extends JDialog { try { File file = fc.getSelectedFile(); TruthTable truthTable = TruthTable.readFromFile(file); - setModel(new TruthTableTableModel(truthTable)); + undoManager.setInitial(truthTable); + tableChanged(); TableDialog.this.filename = file; } catch (IOException e1) { new ErrorMessage().addCause(e1).show(TableDialog.this); @@ -308,7 +385,7 @@ public class TableDialog extends JDialog { fc.setFileFilter(new FileNameExtensionFilter(Lang.get("msg_truthTable"), "tru")); new SaveAsHelper(TableDialog.this, fc, "tru").checkOverwrite( file -> { - model.getTable().save(file); + undoManager.getActual().save(file); TableDialog.this.filename = file; } ); @@ -320,7 +397,7 @@ public class TableDialog extends JDialog { @Override public void actionPerformed(ActionEvent e) { try { - final LaTeXExpressionListener laTeXExpressionListener = new LaTeXExpressionListener(model); + final LaTeXExpressionListener laTeXExpressionListener = new LaTeXExpressionListener(undoManager.getActual()); ExpressionListener expressionListener = laTeXExpressionListener; if (createJK.isSelected()) expressionListener = new ExpressionListenerJK(expressionListener); @@ -339,14 +416,14 @@ public class TableDialog extends JDialog { @Override public void actionPerformed(ActionEvent e) { int res = JOptionPane.OK_OPTION; - if (model.getTable().getVars().size() > 20) + if (undoManager.getActual().getVars().size() > 20) res = JOptionPane.showConfirmDialog(TableDialog.this, Lang.get("msg_tableHasManyRowsConfirm")); if (res == JOptionPane.OK_OPTION) { JFileChooser fc = new MyFileChooser(); if (TableDialog.this.filename != null) fc.setSelectedFile(SaveAsHelper.checkSuffix(TableDialog.this.filename, "hex")); new SaveAsHelper(TableDialog.this, fc, "hex") - .checkOverwrite(file -> model.getTable().saveHex(file)); + .checkOverwrite(file -> undoManager.getActual().saveHex(file)); } } }.setToolTip(Lang.get("menu_table_exportHex_tt")).createJMenuItem()); @@ -361,49 +438,53 @@ public class TableDialog extends JDialog { return fileMenu; } - private JMenu createSetMenu() { - JMenu setMenu = new JMenu(Lang.get("menu_table_set")); - setMenu.add(new ToolTipAction(Lang.get("menu_table_setXTo0")) { + private void createSetMenuEntries(JMenu edit) { + edit.add(new ToolTipAction(Lang.get("menu_table_setXTo0")) { @Override public void actionPerformed(ActionEvent e) { modifyTable(v -> v > 1 ? 0 : v); } }.setToolTip(Lang.get("menu_table_setXTo0_tt")).createJMenuItem()); - setMenu.add(new ToolTipAction(Lang.get("menu_table_setXTo1")) { + edit.add(new ToolTipAction(Lang.get("menu_table_setXTo1")) { @Override public void actionPerformed(ActionEvent e) { modifyTable(v -> v > 1 ? 1 : v); } }.setToolTip(Lang.get("menu_table_setXTo1_tt")).createJMenuItem()); - setMenu.add(new ToolTipAction(Lang.get("menu_table_setAllToX")) { + edit.add(new ToolTipAction(Lang.get("menu_table_setAllToX")) { @Override public void actionPerformed(ActionEvent e) { modifyTable(v -> (byte) 2); } }.setToolTip(Lang.get("menu_table_setAllToX_tt")).createJMenuItem()); - setMenu.add(new ToolTipAction(Lang.get("menu_table_setAllTo0")) { + edit.add(new ToolTipAction(Lang.get("menu_table_setAllTo0")) { @Override public void actionPerformed(ActionEvent e) { modifyTable(v -> (byte) 0); } }.setToolTip(Lang.get("menu_table_setAllTo0_tt")).createJMenuItem()); - setMenu.add(new ToolTipAction(Lang.get("menu_table_setAllTo1")) { + edit.add(new ToolTipAction(Lang.get("menu_table_setAllTo1")) { @Override public void actionPerformed(ActionEvent e) { modifyTable(v -> (byte) 1); } }.setToolTip(Lang.get("menu_table_setAllTo1_tt")).createJMenuItem()); - setMenu.add(new ToolTipAction(Lang.get("menu_table_invert")) { + edit.add(new ToolTipAction(Lang.get("menu_table_invert")) { @Override public void actionPerformed(ActionEvent e) { modifyTable(v -> v > 1 ? v : (byte) (1 - v)); } }.setToolTip(Lang.get("menu_table_invert_tt")).createJMenuItem()); - return setMenu; } private void modifyTable(BoolTableByteArray.TableModifier m) { - setModel(new TruthTableTableModel(model.getTable().modifyValues(m))); + try { + undoManager.apply(truthTable -> truthTable.modifyValues(m)); + tableChanged(); + } catch (ModifyException e) { + e.printStackTrace(); + new ErrorMessage().addCause(e).show(TableDialog.this); + } } private JMenu createCreateMenu() { @@ -527,8 +608,8 @@ public class TableDialog extends JDialog { private void createCircuit(boolean useJKff, boolean useLUTs, ExpressionModifier... modifier) { try { - final ModelAnalyserInfo modelAnalyzerInfo = model.getTable().getModelAnalyzerInfo(); - CircuitBuilder circuitBuilder = new CircuitBuilder(shapeFactory, model.getTable().getVars()) + final ModelAnalyserInfo modelAnalyzerInfo = undoManager.getActual().getModelAnalyzerInfo(); + CircuitBuilder circuitBuilder = new CircuitBuilder(shapeFactory, undoManager.getActual().getVars()) .setUseJK(useJKff) .setUseLUTs(useLUTs) .setModelAnalyzerInfo(modelAnalyzerInfo); @@ -555,19 +636,6 @@ public class TableDialog extends JDialog { return model; } - /** - * Sets the table model - * - * @param model the model to use - */ - public void setModel(TruthTableTableModel model) { - this.model = model; - model.addTableModelListener(new CalculationTableModelListener()); - table.setModel(model); - karnaughMenuAction.setEnabled(model.getTable().getVars().size() <= 4); - calculateExpressions(); - } - private String getProjectName() { if (filename == null) return "unknown"; @@ -598,6 +666,13 @@ public class TableDialog extends JDialog { } } + /** + * @return the undoManager + */ + public UndoManager getUndoManager() { + return undoManager; + } + private class CalculationTableModelListener implements TableModelListener { @Override public void tableChanged(TableModelEvent tableModelEvent) { @@ -613,7 +688,7 @@ public class TableDialog extends JDialog { if (createJK.isSelected()) expressionListener = new ExpressionListenerJK(expressionListener); - final TruthTable table = model.getTable(); + final TruthTable table = undoManager.getActual(); if (table.getVars().size() >= 8) { ProgressDialog progress = new ProgressDialog(this); @@ -674,7 +749,8 @@ public class TableDialog extends JDialog { @Override public void actionPerformed(ActionEvent actionEvent) { - setModel(new TruthTableTableModel(new TruthTable(n).addResult())); + undoManager.setInitial(new TruthTable(n).addResult()); + tableChanged(); } } @@ -702,7 +778,8 @@ public class TableDialog extends JDialog { i--; } - setModel(new TruthTableTableModel(truthTable)); + undoManager.setInitial(truthTable); + tableChanged(); } } @@ -735,7 +812,8 @@ public class TableDialog extends JDialog { i--; } - setModel(new TruthTableTableModel(truthTable)); + undoManager.setInitial(truthTable); + tableChanged(); } } @@ -746,7 +824,7 @@ public class TableDialog extends JDialog { JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); label.setHorizontalAlignment(SwingConstants.CENTER); label.setFont(font); - if (column < model.getTable().getVars().size()) + if (column < undoManager.getActual().getVars().size()) label.setBackground(MYGRAY); else label.setBackground(Color.WHITE); @@ -761,7 +839,7 @@ public class TableDialog extends JDialog { } } - private final class StringDefaultTableCellRenderer extends DefaultTableCellRenderer { + private static final class StringDefaultTableCellRenderer extends DefaultTableCellRenderer { private StringDefaultTableCellRenderer() { setHorizontalAlignment(SwingConstants.CENTER); } @@ -832,13 +910,13 @@ public class TableDialog extends JDialog { int c = table.getSelectedColumn(); if (r < 0 || c < 0) { r = 0; - c = model.getTable().getVars().size(); + c = undoManager.getActual().getVars().size(); } model.setValueAt(value, r, c); c++; if (c >= table.getColumnCount()) { - c = model.getTable().getVars().size(); + c = undoManager.getActual().getVars().size(); r++; if (r >= model.getRowCount()) r = 0; @@ -859,7 +937,7 @@ public class TableDialog extends JDialog { @Override public void actionPerformed(ActionEvent e) { try { - generator.generate(TableDialog.this, filename, model.getTable(), lastGeneratedExpressions); + generator.generate(TableDialog.this, filename, undoManager.getActual(), lastGeneratedExpressions); setLastUsedGenerator(generator); } catch (Exception e1) { new ErrorMessage(Lang.get("msg_errorDuringHardwareExport")).addCause(e1).show(TableDialog.this); diff --git a/src/main/java/de/neemann/digital/gui/components/table/TableReorderManager.java b/src/main/java/de/neemann/digital/gui/components/table/TableReorderManager.java index 18c1b4d26..a5dda9198 100644 --- a/src/main/java/de/neemann/digital/gui/components/table/TableReorderManager.java +++ b/src/main/java/de/neemann/digital/gui/components/table/TableReorderManager.java @@ -10,6 +10,7 @@ import de.neemann.digital.analyse.TruthTableTableModel; import de.neemann.digital.analyse.expression.ExpressionException; import de.neemann.digital.analyse.expression.Variable; import de.neemann.digital.analyse.quinemc.BoolTable; +import de.neemann.digital.undo.ModifyException; import javax.swing.*; import javax.swing.table.TableModel; @@ -20,7 +21,7 @@ import java.util.ArrayList; /** * Handles reordering of the table columns by mouse drag and drop */ -public class TableReorderManager { +class TableReorderManager { private final TableDialog tableDialog; private final JTable table; @@ -31,7 +32,7 @@ public class TableReorderManager { * @param tableDialog the TableDialog instance * @param table the table which is reordered */ - public TableReorderManager(TableDialog tableDialog, JTable table) { + TableReorderManager(TableDialog tableDialog, JTable table) { this.tableDialog = tableDialog; this.table = table; table.getTableHeader().addMouseListener(new MouseAdapter() { @@ -64,24 +65,32 @@ public class TableReorderManager { } if (wasChange) { - if (isVarChange(varList, vars)) { - try { - TruthTable tt = new ReorderInputs(model.getTable(), vars).reorder(); - tableDialog.setModel(new TruthTableTableModel(tt)); - } catch (ExpressionException e) { - // can't happen because no columns are removed - e.printStackTrace(); - } - } else if (isResultChange(model.getTable(), results)) { - try { - TruthTable tt = new ReorderOutputs(model.getTable(), results).reorder(); - tableDialog.setModel(new TruthTableTableModel(tt)); - } catch (ExpressionException e) { - // can't happen because no columns are removed - e.printStackTrace(); - } - } else - tableDialog.setModel(new TruthTableTableModel(model.getTable())); + try { + if (isVarChange(varList, vars)) { + tableDialog.getUndoManager().apply(tt -> { + try { + new ReorderInputs(tt, vars).reorder(); + } catch (ExpressionException e) { + // can't happen because no columns are removed + e.printStackTrace(); + } + }); + tableDialog.tableChanged(); + } else if (isResultChange(model.getTable(), results)) { + tableDialog.getUndoManager().apply(tt -> { + try { + new ReorderOutputs(tt, results).reorder(); + } catch (ExpressionException e) { + // can't happen because no columns are removed + e.printStackTrace(); + } + }); + tableDialog.tableChanged(); + } else + tableDialog.tableChanged(); + } catch (ModifyException e) { + e.printStackTrace(); + } } } diff --git a/src/main/resources/lang/lang_de.xml b/src/main/resources/lang/lang_de.xml index 61f12aff5..7cdafb23f 100644 --- a/src/main/resources/lang/lang_de.xml +++ b/src/main/resources/lang/lang_de.xml @@ -1546,14 +1546,12 @@ Sind evtl. die Namen der Variablen nicht eindeutig? Kombinatorisch Automat Automat bidirektional - Spalten Eingangsvariablen umsortieren/löschen Ergebnisspalten umsortieren/löschen Ergebnisspalte hinzufügen Fügt der Tabelle eine Ergebnisspalte hinzu. Eingangsvariable hinzufügen Fügt der Tabelle eine Variablenspalte hinzu. - Setzen Setze X auf 0 Setzt die Don't Cares auf 0. Setze X auf 1 diff --git a/src/main/resources/lang/lang_en.xml b/src/main/resources/lang/lang_en.xml index 786738aae..641eabc14 100644 --- a/src/main/resources/lang/lang_en.xml +++ b/src/main/resources/lang/lang_en.xml @@ -1529,14 +1529,12 @@ Combinatorial Sequential Sequential bidirectional - Columns Reorder/Delete Input Variables Add Input Variable Adds a new input variable to the table. Reorder/Delete Output Columns Add Output Column Adds a new result column to the table. - Set Set X to 0 Sets the Don't Cares to 0. Set X to 1 diff --git a/src/main/resources/lang/lang_es.xml b/src/main/resources/lang/lang_es.xml index 1efeb74ea..2efe3dda6 100644 --- a/src/main/resources/lang/lang_es.xml +++ b/src/main/resources/lang/lang_es.xml @@ -1293,14 +1293,12 @@ Combinacional Secuencial Secuencial bidireccional - Columnas Reordena/Borra variables de entrada Reordena/Borra columnas de salida Añade columna de salida Añade una nueva columna de resultado a la tabla. Añade variable de entrada Añade una nueva variable de entrada a la tabla. - Fijar Fijar X a 0 Convierte los "indiferentes" a 0. Poner X a 1 diff --git a/src/main/resources/lang/lang_es_ref.xml b/src/main/resources/lang/lang_es_ref.xml index bb485ee62..c825aa2b4 100644 --- a/src/main/resources/lang/lang_es_ref.xml +++ b/src/main/resources/lang/lang_es_ref.xml @@ -1306,14 +1306,12 @@ Combinatorial Sequential Sequential bidirectional - Columns Reorder/Delete Input Variables Reorder/Delete Output Columns Add Output Column Adds a new result column to the table. Add Input Variable Adds a new input variable to the table. - Set Set X to 0 Sets the Don't Cares to 0. Set X to 1 diff --git a/src/main/resources/lang/lang_pt.xml b/src/main/resources/lang/lang_pt.xml index 65f3725d8..6dbb6e475 100644 --- a/src/main/resources/lang/lang_pt.xml +++ b/src/main/resources/lang/lang_pt.xml @@ -1362,14 +1362,12 @@ Combinacional Sequencial Sequencial bidirecional - Colunas Reordenar/remover variáveis de entrada Adicionar variável de entrada Adicionar uma nova variável de entrada à tabela. Reordenar/remover colunas de saída Adicionar coluna de saída Adicionar uma nova coluna de resultado à tabela. - Definir Definir X como 0 Definir "don't cares" como 0. Definir X como 1 diff --git a/src/main/resources/lang/lang_pt_ref.xml b/src/main/resources/lang/lang_pt_ref.xml index fc8eccb24..df378a19f 100644 --- a/src/main/resources/lang/lang_pt_ref.xml +++ b/src/main/resources/lang/lang_pt_ref.xml @@ -1373,14 +1373,12 @@ Combinatorial Sequential Sequential bidirectional - Columns Reorder/Delete Input Variables Add Input Variable Adds a new input variable to the table. Reorder/Delete Output Columns Add Output Column Adds a new result column to the table. - Set Set X to 0 Sets the Don't Cares to 0. Set X to 1 diff --git a/src/test/java/de/neemann/digital/docu/ScreenShots.java b/src/test/java/de/neemann/digital/docu/ScreenShots.java index 21fa9a3b4..14438be4c 100644 --- a/src/test/java/de/neemann/digital/docu/ScreenShots.java +++ b/src/test/java/de/neemann/digital/docu/ScreenShots.java @@ -159,6 +159,7 @@ public class ScreenShots { .add(new GuiTester.CloseTopMost()) .execute(); + /* File trafficLight = new File(Resources.getRoot(), "../../main/fsm/trafficLightBlink.fsm"); new GuiTester() .press("F10") @@ -217,7 +218,7 @@ public class ScreenShots { .add(new GuiTester.CloseTopMost()) .add(new GuiTester.CloseTopMost()) .add(new GuiTester.CloseTopMost()) - .execute();/**/ + .execute();*/ } private static GuiTester.WindowCheck closeAllSolutionsDialog() { diff --git a/src/test/java/de/neemann/digital/gui/components/table/LaTeXExpressionListenerTest.java b/src/test/java/de/neemann/digital/gui/components/table/LaTeXExpressionListenerTest.java index b7611eab9..478c2d76a 100644 --- a/src/test/java/de/neemann/digital/gui/components/table/LaTeXExpressionListenerTest.java +++ b/src/test/java/de/neemann/digital/gui/components/table/LaTeXExpressionListenerTest.java @@ -21,8 +21,7 @@ public class LaTeXExpressionListenerTest extends TestCase { .addVariable("A") .addVariable("B") .addResult("Y", new BoolTableBoolArray(new boolean[]{false, false, true, false})); - TruthTableTableModel model = new TruthTableTableModel(tt); - LaTeXExpressionListener l = new LaTeXExpressionListener(model); + LaTeXExpressionListener l = new LaTeXExpressionListener(tt); l.resultFound("Y", Operation.and(new Variable("A"), new Not(new Variable("B")))); l.close(); diff --git a/src/test/java/de/neemann/digital/gui/components/table/TestReorderInputs.java b/src/test/java/de/neemann/digital/gui/components/table/TestReorderInputs.java index 5c623756d..50c1f9f30 100644 --- a/src/test/java/de/neemann/digital/gui/components/table/TestReorderInputs.java +++ b/src/test/java/de/neemann/digital/gui/components/table/TestReorderInputs.java @@ -21,9 +21,10 @@ public class TestReorderInputs extends TestCase { col.set(i, i + 1); - ReorderInputs reorderInputs = new ReorderInputs(t); + TruthTable newTable = t.createDeepCopy(); + ReorderInputs reorderInputs = new ReorderInputs(newTable); reorderInputs.getItems().swap(1, 2); - TruthTable newTable = reorderInputs.reorder(); + reorderInputs.reorder(); ContextFiller cf = new ContextFiller(t.getVars()); @@ -39,9 +40,10 @@ public class TestReorderInputs extends TestCase { for (int i = 0; i < t.getRows(); i++) col.set(i, i + 1); - ReorderInputs reorderInputs = new ReorderInputs(t); + TruthTable newTable = t.createDeepCopy(); + ReorderInputs reorderInputs = new ReorderInputs(newTable); reorderInputs.getItems().delete(2); - TruthTable newTable = reorderInputs.reorder(); + reorderInputs.reorder(); assertEquals(2, newTable.getVars().size()); assertEquals(1, newTable.getResultCount()); diff --git a/src/test/java/de/neemann/digital/gui/components/table/TestReorderOutputs.java b/src/test/java/de/neemann/digital/gui/components/table/TestReorderOutputs.java index bbaac7059..56f3c2a14 100644 --- a/src/test/java/de/neemann/digital/gui/components/table/TestReorderOutputs.java +++ b/src/test/java/de/neemann/digital/gui/components/table/TestReorderOutputs.java @@ -19,9 +19,10 @@ public class TestReorderOutputs extends TestCase { for (int i = 0; i < t.getRows(); i++) col.set(i, i + 1); - ReorderOutputs reorderOutputs = new ReorderOutputs(t); + TruthTable newTable = t.createDeepCopy(); + ReorderOutputs reorderOutputs = new ReorderOutputs(newTable); reorderOutputs.getItems().delete(1); - TruthTable newTable = reorderOutputs.reorder(); + reorderOutputs.reorder(); assertEquals(3, newTable.getVars().size()); assertEquals(1, newTable.getResultCount()); From 50fd1db2c7291c8bd8e50823c4ef10039e34bb73 Mon Sep 17 00:00:00 2001 From: hneemann Date: Wed, 25 Sep 2019 17:38:11 +0200 Subject: [PATCH 3/7] adds missing initial setup --- .../de/neemann/digital/gui/components/table/TableDialog.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java b/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java index fb0ff162d..6264bc615 100644 --- a/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java +++ b/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java @@ -291,6 +291,9 @@ public class TableDialog extends JDialog { setJMenuBar(bar); + karnaughMenuAction.setEnabled(undoManager.getActual().getVars().size() <= 4); + calculateExpressions(); + getContentPane().add(new JScrollPane(table)); getContentPane().add(statusBar, BorderLayout.SOUTH); pack(); From 061e3864d7887c3a0c19a5c4a20c16debc154908 Mon Sep 17 00:00:00 2001 From: hneemann Date: Wed, 25 Sep 2019 18:36:59 +0200 Subject: [PATCH 4/7] fixed the gui tests --- src/test/java/de/neemann/digital/integration/TestInGUI.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/de/neemann/digital/integration/TestInGUI.java b/src/test/java/de/neemann/digital/integration/TestInGUI.java index 9cfe94d21..5d3df6f31 100644 --- a/src/test/java/de/neemann/digital/integration/TestInGUI.java +++ b/src/test/java/de/neemann/digital/integration/TestInGUI.java @@ -332,7 +332,7 @@ public class TestInGUI extends TestCase { new GuiTester() .use(create4BitCounterTruthTable) .press("F10") - .press("RIGHT", 4) + .press("RIGHT", 3) .press("DOWN", 2) .press("ENTER") .delay(500) @@ -424,7 +424,7 @@ public class TestInGUI extends TestCase { })) .delay(500) .press("F10") - .press("RIGHT", 4) + .press("RIGHT", 3) .press("DOWN", 7) .press("RIGHT") .press("DOWN", 2) @@ -947,7 +947,7 @@ public class TestInGUI extends TestCase { assertEquals(4, model.getRowCount()); for (int i = 0; i < 4; i++) { final Object valueAt = model.getValueAt(i, 1); - assertEquals("0x0", valueAt.toString()); + assertEquals("0", valueAt.toString()); } found(); } From 34ada97add4d4522b9bd636ddb9b20fae55b31f2 Mon Sep 17 00:00:00 2001 From: hneemann Date: Wed, 25 Sep 2019 18:47:57 +0200 Subject: [PATCH 5/7] fixed the screenshot generation --- .../digital/gui/components/table/TableDialog.java | 5 ++++- .../java/de/neemann/digital/docu/ScreenShots.java | 13 +++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java b/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java index 6264bc615..334fb5b96 100644 --- a/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java +++ b/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java @@ -337,7 +337,10 @@ public class TableDialog extends JDialog { redo.setEnabled(undoManager.redoAvailable()); } - void tableChanged() { + /** + * Called if table was modified. + */ + public void tableChanged() { karnaughMenuAction.setEnabled(undoManager.getActual().getVars().size() <= 4); calculateExpressions(); model.fireTableChanged(); diff --git a/src/test/java/de/neemann/digital/docu/ScreenShots.java b/src/test/java/de/neemann/digital/docu/ScreenShots.java index 14438be4c..21337104f 100644 --- a/src/test/java/de/neemann/digital/docu/ScreenShots.java +++ b/src/test/java/de/neemann/digital/docu/ScreenShots.java @@ -115,6 +115,7 @@ public class ScreenShots { .press("F1") .add(new MainScreenShot("distribution/screenshot.png")) .execute(); /**/ + new GuiTester() .press("F10") .press("RIGHT", 4) @@ -157,9 +158,8 @@ public class ScreenShots { .add(new GuiTester.CloseTopMost()) .add(new GuiTester.CloseTopMost()) .add(new GuiTester.CloseTopMost()) - .execute(); - - /* + .execute();/**/ + File trafficLight = new File(Resources.getRoot(), "../../main/fsm/trafficLightBlink.fsm"); new GuiTester() .press("F10") @@ -180,13 +180,14 @@ public class ScreenShots { ReorderOutputs ro = new ReorderOutputs(tt); ro.getItems().swap(3, 4); ro.getItems().swap(4, 5); - tableDialog.setModel(new TruthTableTableModel(ro.reorder())); + ro.reorder(); + tableDialog.tableChanged(); })) .delay(500) .add(closeAllSolutionsDialog()) .delay(500) .press("F10") - .press("RIGHT", 4) + .press("RIGHT", 3) .press("DOWN", 2) .press("ENTER") .delay(500) @@ -218,7 +219,7 @@ public class ScreenShots { .add(new GuiTester.CloseTopMost()) .add(new GuiTester.CloseTopMost()) .add(new GuiTester.CloseTopMost()) - .execute();*/ + .execute(); } private static GuiTester.WindowCheck closeAllSolutionsDialog() { From 6fd75f5705f397532e48422716225d9a553552b9 Mon Sep 17 00:00:00 2001 From: hneemann Date: Sat, 28 Sep 2019 09:21:49 +0200 Subject: [PATCH 6/7] shows modified status in the window title --- .../digital/analyse/TruthTableTableModel.java | 13 ++++++++----- .../digital/gui/components/table/TableDialog.java | 9 ++++++--- .../java/de/neemann/digital/undo/UndoManager.java | 5 ++++- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/main/java/de/neemann/digital/analyse/TruthTableTableModel.java b/src/main/java/de/neemann/digital/analyse/TruthTableTableModel.java index c76925f13..a4fcee4cd 100644 --- a/src/main/java/de/neemann/digital/analyse/TruthTableTableModel.java +++ b/src/main/java/de/neemann/digital/analyse/TruthTableTableModel.java @@ -79,14 +79,17 @@ public class TruthTableTableModel implements TableModel { else setValue(rowIndex, columnIndex, 2); } - fireModelEvent(rowIndex); } private void setValue(int rowIndex, int columnIndex, int val) { - try { - undoManager.apply(truthTable -> truthTable.setValue(rowIndex, columnIndex, val)); - } catch (ModifyException e) { - e.printStackTrace(); + int actVal = undoManager.getActual().getValue(rowIndex, columnIndex); + if (actVal != val) { + try { + undoManager.apply(truthTable -> truthTable.setValue(rowIndex, columnIndex, val)); + } catch (ModifyException e) { + e.printStackTrace(); + } + fireModelEvent(rowIndex); } } diff --git a/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java b/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java index 334fb5b96..e9490ab1d 100644 --- a/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java +++ b/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java @@ -327,14 +327,17 @@ public class TableDialog extends JDialog { } } }.setAcceleratorCTRLplus("Y"); + edit.add(undo.createJMenuItem()); edit.add(redo.createJMenuItem()); undoManager.addListener(() -> { undo.setEnabled(undoManager.undoAvailable()); redo.setEnabled(undoManager.redoAvailable()); - }); - undo.setEnabled(undoManager.undoAvailable()); - redo.setEnabled(undoManager.redoAvailable()); + if (undoManager.isModified()) + setTitle("*" + Lang.get("win_table")); + else + setTitle(Lang.get("win_table")); + }).hasChanged(); } /** diff --git a/src/main/java/de/neemann/digital/undo/UndoManager.java b/src/main/java/de/neemann/digital/undo/UndoManager.java index a3c2d3ecc..30d15516c 100644 --- a/src/main/java/de/neemann/digital/undo/UndoManager.java +++ b/src/main/java/de/neemann/digital/undo/UndoManager.java @@ -45,6 +45,7 @@ public class UndoManager> { modifications = new ArrayList<>(); modificationCounter = 0; savedCounter = 0; + fireChangedEvent(); } @@ -187,9 +188,11 @@ public class UndoManager> { * Adds a listener * * @param listener the listener to add + * @return the given listener for chained calls. */ - public void addListener(ChangedListener listener) { + public ChangedListener addListener(ChangedListener listener) { listeners.add(listener); + return listener; } /** From c697bb7d987026390587fb48fcb285ff6a8330e9 Mon Sep 17 00:00:00 2001 From: hneemann Date: Sat, 28 Sep 2019 09:25:04 +0200 Subject: [PATCH 7/7] fixed a checkstyle issue --- .../de/neemann/digital/gui/components/table/TableDialog.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java b/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java index e9490ab1d..54deb1f01 100644 --- a/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java +++ b/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java @@ -327,7 +327,7 @@ public class TableDialog extends JDialog { } } }.setAcceleratorCTRLplus("Y"); - + edit.add(undo.createJMenuItem()); edit.add(redo.createJMenuItem()); undoManager.addListener(() -> {