Refactoring of creating a sub circuit.

This commit is contained in:
hneemann 2017-04-01 12:52:36 +02:00
parent c69f8a96a4
commit 121a126142
9 changed files with 142 additions and 62 deletions

View File

@ -189,7 +189,7 @@ public class ElementLibrary implements Iterable<ElementLibrary.ElementContainer>
* @param rootLibraryPath the path
* @throws IOException IOException
*/
public void setFilePath(File rootLibraryPath) throws IOException {
public void setRootFilePath(File rootLibraryPath) throws IOException {
if (rootLibraryPath == null) {
if (this.rootLibraryPath != null) {
this.rootLibraryPath = null;
@ -201,6 +201,31 @@ public class ElementLibrary implements Iterable<ElementLibrary.ElementContainer>
}
}
/**
* @return the actual root file path
*/
public File getRootFilePath() {
return rootLibraryPath;
}
/**
* Checks if the given file is accessible from the actual library.
*
* @param file the file to check
* @return true if given file is importable
*/
public boolean isFileAccessible(File file) {
if (rootLibraryPath == null) return true;
try {
String root = rootLibraryPath.getCanonicalPath();
String path = file.getParentFile().getCanonicalPath();
return path.startsWith(root);
} catch (IOException e) {
return false;
}
}
/**
* Returns the node or null if node not present.
*
@ -358,14 +383,18 @@ public class ElementLibrary implements Iterable<ElementLibrary.ElementContainer>
}
/**
* Removes an element from the library
* Removes an element from the library to enforce a reload
*
* @param name the elements name
*/
public void invalidateElement(File name) {
public void invalidateElement(File name) throws IOException {
LibraryNode n = map.get(name.getName());
if (n != null)
n.invalidate();
else {
if (rootLibraryPath != null && isFileAccessible(name))
rescanFolder();
}
}
/**

View File

@ -90,6 +90,7 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
private static final Icon ICON_STEP = IconCreator.create("media-seek-forward.png");
private static final Icon ICON_STOP = IconCreator.create("media-playback-stop.png");
private static final Icon ICON_NEW = IconCreator.create("document-new.png");
private static final Icon ICON_NEW_SUB = IconCreator.create("document-new-sub.png");
private static final Icon ICON_OPEN = IconCreator.create("document-open.png");
private static final Icon ICON_OPEN_WIN = IconCreator.create("document-open-new.png");
private static final Icon ICON_SAVE = IconCreator.create("document-save.png");
@ -109,7 +110,6 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
private final ScheduledThreadPoolExecutor timerExecuter = new ScheduledThreadPoolExecutor(1);
private final WindowPosManager windowPosManager = new WindowPosManager();
private final InsertHistory insertHistory;
private final boolean isNestedFile;
private ToolTipAction doStep;
private ToolTipAction runToBreakAction;
@ -153,41 +153,41 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
* @param parent the parent component
* @param circuit circuit to show
*/
public Main(Component parent, Circuit circuit) {
this(parent, null, null, circuit);
public Main(Component parent, ElementLibrary parentsLibrary, Circuit circuit) {
this(parent, null, parentsLibrary, circuit);
}
/**
* Creates a new instance
*
* @param parent the parent component
* @param fileToOpen a file to open
* @param parentsLibrary the parents library. If not null means opening a nested circuit
* @param circuit circuit to show
* @param parent the parent component
* @param nestedFileToOpen a file to open
* @param parentsLibrary the parents library. If not null means opening a nested circuit
* @param circuit circuit to show
*/
private Main(Component parent, File fileToOpen, ElementLibrary parentsLibrary, Circuit circuit) {
private Main(Component parent, File nestedFileToOpen, ElementLibrary parentsLibrary, Circuit circuit) {
super(Lang.get("digital"));
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
setIconImages(IconCreator.createImages("icon32.png", "icon64.png", "icon128.png"));
isNestedFile = parentsLibrary != null;
if (isNestedFile) this.library = parentsLibrary;
if (parentsLibrary != null) library = parentsLibrary;
else library = new ElementLibrary();
shapeFactory = new ShapeFactory(library, Settings.getInstance().get(Keys.SETTINGS_IEEE_SHAPES));
fileHistory = new FileHistory(this);
circuitComponent = new CircuitComponent(this, library, shapeFactory);
if (circuit != null) {
circuitComponent = new CircuitComponent(this, library, shapeFactory);
SwingUtilities.invokeLater(() -> circuitComponent.setCircuit(circuit));
setFilename(nestedFileToOpen, false);
} else {
circuitComponent = new CircuitComponent(this, library, shapeFactory);
if (fileToOpen != null) {
SwingUtilities.invokeLater(() -> loadFile(fileToOpen, false));
if (nestedFileToOpen != null) {
SwingUtilities.invokeLater(() -> loadFile(nestedFileToOpen, false));
} else {
File name = fileHistory.getMostRecent();
if (name != null) {
SwingUtilities.invokeLater(() -> loadFile(name, false));
SwingUtilities.invokeLater(() -> loadFile(name, true));
}
}
}
@ -205,7 +205,7 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
JMenuBar menuBar = new JMenuBar();
JToolBar toolBar = new JToolBar();
save = createFileMenu(menuBar, toolBar);
save = createFileMenu(menuBar, toolBar, nestedFileToOpen == null);
toolBar.addSeparator();
createViewMenu(menuBar, toolBar);
@ -350,7 +350,7 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
* @param toolBar the toolBar
* @return the save action
*/
private ToolTipAction createFileMenu(JMenuBar menuBar, JToolBar toolBar) {
private ToolTipAction createFileMenu(JMenuBar menuBar, JToolBar toolBar, boolean allowAll) {
ToolTipAction newFile = new ToolTipAction(Lang.get("menu_new"), ICON_NEW) {
@Override
public void actionPerformed(ActionEvent e) {
@ -358,9 +358,21 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
setFilename(null, true);
circuitComponent.setCircuit(new Circuit());
windowPosManager.closeAll();
try {
library.setRootFilePath(null);
} catch (IOException e1) {
// can not happen, no folder is scanned
}
}
}
}.setActive(!isNestedFile);
}.setToolTip(Lang.get("menu_new_tt")).setActive(allowAll);
ToolTipAction newSubFile = new ToolTipAction(Lang.get("menu_newSub"), ICON_NEW_SUB) {
@Override
public void actionPerformed(ActionEvent e) {
new Main(Main.this, library, new Circuit()).setVisible(true);
}
}.setToolTip(Lang.get("menu_newSub_tt"));
ToolTipAction open = new ToolTipAction(Lang.get("menu_open"), ICON_OPEN) {
@Override
@ -372,7 +384,7 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
}
}
}
}.setActive(!isNestedFile);
}.setActive(allowAll);
ToolTipAction openWin = new ToolTipAction(Lang.get("menu_openWin"), ICON_OPEN_WIN) {
@Override
@ -384,21 +396,46 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
m.setVisible(true);
}
}
}.setToolTip(Lang.get("menu_openWin_tt")).setActive(!isNestedFile);
}.setToolTip(Lang.get("menu_openWin_tt")).setActive(allowAll);
JMenu openRecent = new JMenu(Lang.get("menu_openRecent"));
fileHistory.setMenu(openRecent);
openRecent.setEnabled(!isNestedFile);
openRecent.setEnabled(allowAll);
ToolTipAction saveas = new ToolTipAction(Lang.get("menu_saveAs"), ICON_SAVE_AS) {
@Override
public void actionPerformed(ActionEvent e) {
JFileChooser fc = getJFileChooser(lastFilename);
if (fc.showSaveDialog(Main.this) == JFileChooser.APPROVE_OPTION) {
saveFile(fc.getSelectedFile());
}
if (lastFilename == null && library.getRootFilePath() != null)
fc.setCurrentDirectory(library.getRootFilePath());
boolean repeat;
do {
repeat = false;
if (fc.showSaveDialog(Main.this) == JFileChooser.APPROVE_OPTION) {
final File selectedFile = fc.getSelectedFile();
if (library.isFileAccessible(selectedFile))
saveFile(selectedFile, false);
else {
Object[] options = {Lang.get("btn_saveAnyway"), Lang.get("btn_newName"), Lang.get("cancel")};
int res = JOptionPane.showOptionDialog(Main.this,
Lang.get("msg_fileNotAccessible"),
Lang.get("msg_warning"),
JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
null, options, options[0]);
switch (res) {
case 0:
saveFile(selectedFile, true);
break;
case 1:
repeat = true;
break;
}
}
}
} while (repeat);
}
}.setActive(!isNestedFile);
}.setActive(allowAll);
ToolTipAction save = new ToolTipAction(Lang.get("menu_save"), ICON_SAVE) {
@Override
@ -406,7 +443,7 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
if (filename == null)
saveas.actionPerformed(e);
else
saveFile(filename);
saveFile(filename, false);
}
};
@ -418,12 +455,13 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
JMenu file = new JMenu(Lang.get("menu_file"));
menuBar.add(file);
file.add(newFile);
file.add(newFile.createJMenuItem());
file.add(newSubFile.createJMenuItem());
file.add(openRecent);
file.add(open);
file.add(openWin);
file.add(save);
file.add(saveas);
file.add(open.createJMenuItem());
file.add(openWin.createJMenuItem());
file.add(save.createJMenuItem());
file.add(saveas.createJMenuItem());
file.add(export);
toolBar.add(newFile.createJButtonNoText());
@ -525,7 +563,7 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
circuit.add((VisualElement) m);
}
Main m = new Main(Main.this, circuit);
Main m = new Main(Main.this, library, circuit);
m.lastFilename = filename;
m.setLocationRelativeTo(Main.this);
m.setVisible(true);
@ -694,7 +732,7 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
public void actionPerformed(ActionEvent e) {
try {
Model model = new ModelCreator(circuitComponent.getCircuit(), library).createModel(false);
new TableDialog(Main.this, new ModelAnalyser(model).analyse(), shapeFactory, filename)
new TableDialog(Main.this, new ModelAnalyser(model).analyse(), library, shapeFactory, filename)
.setVisible(true);
stoppedState.enter();
} catch (PinException | NodeException | AnalyseException | ElementNotFoundException | RuntimeException e1) {
@ -709,7 +747,7 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
@Override
public void actionPerformed(ActionEvent e) {
TruthTable tt = new TruthTable(3).addResult();
new TableDialog(Main.this, tt, shapeFactory, null).setVisible(true);
new TableDialog(Main.this, tt, library, shapeFactory, null).setVisible(true);
stoppedState.enter();
}
}
@ -719,7 +757,7 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
analyse.add(new ToolTipAction(Lang.get("menu_expression")) {
@Override
public void actionPerformed(ActionEvent e) {
new ExpressionDialog(Main.this, shapeFactory).setVisible(true);
new ExpressionDialog(Main.this, library, shapeFactory).setVisible(true);
}
}
.setToolTip(Lang.get("menu_expression_tt"))
@ -899,9 +937,10 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
}
}
private void loadFile(File filename, boolean toPrefs) {
private void loadFile(File filename, boolean setLibraryRoot) {
try {
setFilename(filename, toPrefs);
setFilename(filename, setLibraryRoot);
if (setLibraryRoot) library.setRootFilePath(filename.getParentFile());
Circuit circ = Circuit.loadCircuit(filename, shapeFactory);
circuitComponent.setCircuit(circ);
stoppedState.enter();
@ -914,12 +953,12 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
}
}
private void saveFile(File filename) {
private void saveFile(File filename, boolean toPrefs) {
filename = checkSuffix(filename, "dig");
try {
circuitComponent.getCircuit().save(filename);
stoppedState.enter();
setFilename(filename, !isNestedFile);
setFilename(filename, toPrefs);
library.invalidateElement(filename);
} catch (IOException e) {
new ErrorMessage(Lang.get("msg_errorWritingFile")).addCause(e).show();
@ -927,20 +966,14 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
}
private void setFilename(File filename, boolean toPrefs) {
try {
this.filename = filename;
if (filename != null) {
this.lastFilename = filename;
if (!isNestedFile) library.setFilePath(filename.getParentFile());
if (toPrefs)
fileHistory.add(filename);
setTitle(filename + " - " + Lang.get("digital"));
} else {
if (!isNestedFile) library.setFilePath(null);
setTitle(Lang.get("digital"));
}
} catch (IOException e) {
new ErrorMessage(Lang.get("msg_errorReadingFile")).addCause(e).show(this);
this.filename = filename;
if (filename != null) {
this.lastFilename = filename;
if (toPrefs)
fileHistory.add(filename);
setTitle(filename + " - " + Lang.get("digital"));
} else {
setTitle(Lang.get("digital"));
}
}

View File

@ -5,6 +5,7 @@ import de.neemann.digital.analyse.expression.format.FormatToExpression;
import de.neemann.digital.analyse.parser.Parser;
import de.neemann.digital.builder.circuit.CircuitBuilder;
import de.neemann.digital.draw.elements.Circuit;
import de.neemann.digital.draw.library.ElementLibrary;
import de.neemann.digital.draw.shapes.ShapeFactory;
import de.neemann.digital.gui.Main;
import de.neemann.digital.gui.components.table.ShowStringDialog;
@ -31,7 +32,7 @@ public class ExpressionDialog extends JDialog {
* @param parent the parent
* @param shapeFactory the shapeFactory used for new circuits
*/
public ExpressionDialog(JFrame parent, ShapeFactory shapeFactory) {
public ExpressionDialog(Main parent, ElementLibrary library, ShapeFactory shapeFactory) {
super(parent, Lang.get("expression"), false);
JTextField text = new JTextField("(C B) ∧ (A C) ∧ (B !C) * (C + !A)", 40);
@ -64,7 +65,7 @@ public class ExpressionDialog extends JDialog {
for (Expression exp : expList)
circuitBuilder.addCombinatorial(FormatToExpression.defaultFormat(exp), exp);
Circuit circuit = circuitBuilder.createCircuit();
SwingUtilities.invokeLater(() -> new Main(null, circuit).setVisible(true));
SwingUtilities.invokeLater(() -> new Main(parent, library, circuit).setVisible(true));
} catch (Exception ex) {
new ErrorMessage().addCause(ex).show(ExpressionDialog.this);
}

View File

@ -32,6 +32,7 @@ import de.neemann.digital.core.element.ElementAttributes;
import de.neemann.digital.core.element.Key;
import de.neemann.digital.core.element.Keys;
import de.neemann.digital.draw.elements.Circuit;
import de.neemann.digital.draw.library.ElementLibrary;
import de.neemann.digital.draw.shapes.ShapeFactory;
import de.neemann.digital.gui.Main;
import de.neemann.digital.gui.components.AttributeDialog;
@ -74,6 +75,7 @@ public class TableDialog extends JDialog {
private final JLabel label;
private final JTable table;
private final Font font;
private final ElementLibrary library;
private final ShapeFactory shapeFactory;
private JCheckBoxMenuItem createJK;
private File filename;
@ -89,8 +91,9 @@ public class TableDialog extends JDialog {
* @param parent the parent frame
* @param truthTable the table to show
*/
public TableDialog(JFrame parent, TruthTable truthTable, ShapeFactory shapeFactory, File filename) {
public TableDialog(JFrame parent, TruthTable truthTable, ElementLibrary library, ShapeFactory shapeFactory, File filename) {
super(parent, Lang.get("win_table"));
this.library = library;
this.shapeFactory = shapeFactory;
this.filename = filename;
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
@ -519,7 +522,7 @@ public class TableDialog extends JDialog {
CircuitBuilder circuitBuilder = new CircuitBuilder(shapeFactory, useJKff);
new BuilderExpressionCreator(circuitBuilder, modifier).setUseJKOptimizer(useJKff).create(lastGeneratedExpressions);
Circuit circuit = circuitBuilder.createCircuit();
SwingUtilities.invokeLater(() -> new Main(null, circuit).setVisible(true));
SwingUtilities.invokeLater(() -> new Main(null, library, circuit).setVisible(true));
} catch (ExpressionException | FormatterException | RuntimeException e) {
new ErrorMessage(Lang.get("msg_errorDuringCalculation")).addCause(e).show();
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -36,6 +36,9 @@
<string name="btn_clearData_tt">Setzt alle Werte auf 0 zurück!</string>
<string name="btn_addTransitions">Übergänge</string>
<string name="btn_addTransitions_tt">Alle möglichen Übergänge werden als Testfälle ergänzt. Dient zur Erzeugung von Testfällen für den Simulator selbst.</string>
<string name="btn_newName">Neuer Name</string>
<string name="btn_saveAnyway">Trotzdem speichern</string>
<string name="msg_warning">Warnung</string>
<string name="cancel">Abbrechen</string>
<string name="digital">Digital</string>
<string name="expression">Ausdruck</string>
@ -592,6 +595,9 @@ Es sind nur {1} Variablen erlaubt, es wurden jedoch {2} gefunden.</string>
<string name="menu_micro">Gatterschrittmodus</string>
<string name="menu_micro_tt">Startet die Schaltung im Gatterschrittmodus</string>
<string name="menu_new">Neu</string>
<string name="menu_new_tt">Aktuelle Schaltung löschen.</string>
<string name="menu_newSub">Neue Teilschaltung</string>
<string name="menu_newSub_tt">Öffnet ein neues Fenster um darin eine neue eingebettete Teilschaltung zu erstellen.</string>
<string name="menu_open">Öffnen</string>
<string name="menu_openRecent">Zuletzt verwendet</string>
<string name="menu_openWin">Öffnen in neuem Fenster</string>
@ -730,6 +736,7 @@ Die Icons stammen aus dem Tango Desktop Project.</string>
<string name="msg_fitterResult">Meldung vom externen Fitter</string>
<string name="msg_startExternalFitter">Starten des externen Fitters</string>
<string name="msg_actualCircuit">Aktuelle Schaltung</string>
<string name="msg_fileNotAccessible">Dieser Dateiename ist nicht aus dem aktuellen Projekt importierbar!</string>
<string name="ok">Ok</string>
<string name="rot_0"></string>

View File

@ -36,6 +36,9 @@
<string name="btn_clearData_tt">All values are set to zero!</string>
<string name="btn_addTransitions">Transitions</string>
<string name="btn_addTransitions_tt">All possible transitions are added as test cases. Is used to create test cases to test the simulator itself.</string>
<string name="btn_newName">New Name</string>
<string name="btn_saveAnyway">Save anyway</string>
<string name="msg_warning">Warning</string>
<string name="cancel">Cancel</string>
<string name="digital">Digital</string>
<string name="expression">Expression</string>
@ -579,6 +582,9 @@ allowed are {1} variables but {2} are found.</string>
<string name="menu_micro">Single gate stepping</string>
<string name="menu_micro_tt">Runs the circuit in single gate step mode</string>
<string name="menu_new">New</string>
<string name="menu_new_tt">Clear actual circuit.</string>
<string name="menu_newSub">New nested Circuit</string>
<string name="menu_newSub_tt">Opens a new window to create a new nested circuit.</string>
<string name="menu_open">Open</string>
<string name="menu_openRecent">Open Recent</string>
<string name="menu_openWin">Open in New Window</string>
@ -717,6 +723,7 @@ The icons are taken from the Tango Desktop Project.</string>
<string name="msg_fitterResult">Message from the external fitter</string>
<string name="msg_startExternalFitter">Execution of external fitter</string>
<string name="msg_actualCircuit">Actual Circuit</string>
<string name="msg_fileNotAccessible">The selected file name is not importable from the actual project!</string>
<string name="ok">Ok</string>
<string name="rot_0"></string>

View File

@ -64,7 +64,7 @@ public class TestNesting extends TestCase {
private TestExecuter createTestExecuterForNesting(String file) throws IOException, NodeException, PinException, ElementNotFoundException {
ElementLibrary library = new ElementLibrary();
library.setFilePath(new File(Resources.getRoot(), "dig"));
library.setRootFilePath(new File(Resources.getRoot(), "dig"));
return TestExecuter.createFromFile(file, library);
}

View File

@ -70,7 +70,7 @@ public class ToBreakRunner {
private ToBreakRunner(File filename, boolean doInit) throws IOException, PinException, NodeException, ElementNotFoundException {
library = new ElementLibrary();
library.setFilePath(filename.getParentFile());
library.setRootFilePath(filename.getParentFile());
ShapeFactory shapeFactory = new ShapeFactory(library);
circuit = Circuit.loadCircuit(filename, shapeFactory);