diff --git a/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java b/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java index 2c1fa6678..5c3d7decb 100644 --- a/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java +++ b/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java @@ -153,11 +153,7 @@ public class ElementLibrary implements Iterable node.add(TestCaseElement.TESTCASEDESCRIPTION); root.add(node); - try { - populateNodeMap(); - } catch (IOException e) { - // can not happen because there are no custom elements yet - } + populateNodeMap(); } /** @@ -176,11 +172,9 @@ public class ElementLibrary implements Iterable return customNode; } - private void populateNodeMap() throws IOException { + private void populateNodeMap() { map.clear(); - String dn = root.traverse(new PopulateModelVisitor(map)).getDoubleNode(); - if (dn != null) - throw new IOException(Lang.get("err_file_N0_ExistsTwiceBelow_N1", dn, rootLibraryPath)); + root.traverse(new PopulateMapVisitor(map)); } /** @@ -555,11 +549,10 @@ public class ElementLibrary implements Iterable } } - private static final class PopulateModelVisitor implements Visitor { + private static final class PopulateMapVisitor implements Visitor { private final HashMap map; - private String doubleNode; - private PopulateModelVisitor(HashMap map) { + private PopulateMapVisitor(HashMap map) { this.map = map; } @@ -568,15 +561,15 @@ public class ElementLibrary implements Iterable if (libraryNode.isLeaf()) { final String name = libraryNode.getName(); - if (map.containsKey(name)) - doubleNode = name; - - map.put(name, libraryNode); + LibraryNode presentNode = map.get(name); + if (presentNode==null) { + map.put(name, libraryNode); + libraryNode.setUnique(true); + } else { + presentNode.setUnique(false); + libraryNode.setUnique(false); + } } } - - private String getDoubleNode() { - return doubleNode; - } } } diff --git a/src/main/java/de/neemann/digital/draw/library/LibraryNode.java b/src/main/java/de/neemann/digital/draw/library/LibraryNode.java index 9bd7d734d..3310a52e7 100644 --- a/src/main/java/de/neemann/digital/draw/library/LibraryNode.java +++ b/src/main/java/de/neemann/digital/draw/library/LibraryNode.java @@ -5,6 +5,7 @@ import de.neemann.digital.core.element.ElementTypeDescription; import de.neemann.digital.draw.elements.VisualElement; import de.neemann.digital.draw.shapes.ShapeFactory; import de.neemann.digital.lang.Lang; +import de.neemann.gui.IconCreator; import de.neemann.gui.StringUtils; import javax.swing.*; @@ -18,6 +19,7 @@ import java.util.Iterator; * Created by hneemann on 25.03.17. */ public class LibraryNode implements Iterable { + private static final Icon ICON_NOT_UNIQUE = IconCreator.create("testFailed.png"); private final ArrayList children; private final String translatedName; @@ -27,6 +29,7 @@ public class LibraryNode implements Iterable { private ImageIcon icon; private ElementLibrary library; private LibraryNode parent; + private boolean unique; /** * Creates a new node with the given name. @@ -121,6 +124,9 @@ public class LibraryNode implements Iterable { */ public ElementTypeDescription getDescription() throws IOException { if (description == null) { + if (!unique) + throw new IOException(Lang.get("err_file_N0_ExistsTwiceBelow_N1", file, library.getRootFilePath())); + description = library.importElement(file); library.fireLibraryChanged(this); } @@ -210,7 +216,7 @@ public class LibraryNode implements Iterable { * @return the icon * @throws IOException IOException */ - public ImageIcon getIcon(ShapeFactory shapeFactory) throws IOException { + public Icon getIcon(ShapeFactory shapeFactory) throws IOException { getDescription(); return getIconOrNull(shapeFactory); } @@ -222,10 +228,13 @@ public class LibraryNode implements Iterable { * @param shapeFactory the shape factory to create the icon * @return the icon or null */ - public ImageIcon getIconOrNull(ShapeFactory shapeFactory) { - if (icon == null && description != null) - icon = new VisualElement(description.getName()).setShapeFactory(shapeFactory).createIcon(75); - return icon; + public Icon getIconOrNull(ShapeFactory shapeFactory) { + if (unique) { + if (icon == null && description != null) + icon = new VisualElement(description.getName()).setShapeFactory(shapeFactory).createIcon(75); + return icon; + } else + return ICON_NOT_UNIQUE; } /** @@ -280,11 +289,30 @@ public class LibraryNode implements Iterable { */ public String getToolTipText() { if (isCustom()) { - if (description == null) - return null; - else - return StringUtils.textToHTML(description.getDescription(new ElementAttributes())); + if (isUnique()) { + if (description == null) + return null; + else + return StringUtils.textToHTML(description.getDescription(new ElementAttributes())); + } else + return Lang.get("msg_fileIsNotUnique"); } else return StringUtils.textToHTML(Lang.getNull("elem_" + getName() + "_tt")); } + + /** + * sets the unique state of this node + * + * @param unique true if this node is unique + */ + void setUnique(boolean unique) { + this.unique = unique; + } + + /** + * @return true if element is unique + */ + public boolean isUnique() { + return unique; + } } diff --git a/src/main/java/de/neemann/digital/gui/InsertAction.java b/src/main/java/de/neemann/digital/gui/InsertAction.java index 640bbfa9d..8fc929cb3 100644 --- a/src/main/java/de/neemann/digital/gui/InsertAction.java +++ b/src/main/java/de/neemann/digital/gui/InsertAction.java @@ -37,6 +37,7 @@ public final class InsertAction extends ToolTipAction { this.node = node; this.insertHistory = insertHistory; this.circuitComponent = circuitComponent; + setActive(node.isUnique()); } @Override @@ -76,7 +77,7 @@ public final class InsertAction extends ToolTipAction { public void update(LibraryNode node) { this.node = node; try { - final ImageIcon icon = node.getIcon(shapeFactory); + final Icon icon = node.getIcon(shapeFactory); setIcon(icon); } catch (IOException ex) { SwingUtilities.invokeLater(new ErrorMessage(Lang.get("msg_errorImportingModel")).addCause(ex)); diff --git a/src/main/java/de/neemann/digital/gui/components/tree/SelectTree.java b/src/main/java/de/neemann/digital/gui/components/tree/SelectTree.java index 016216ebb..971932f66 100644 --- a/src/main/java/de/neemann/digital/gui/components/tree/SelectTree.java +++ b/src/main/java/de/neemann/digital/gui/components/tree/SelectTree.java @@ -43,7 +43,7 @@ public class SelectTree extends JTree { TreePath path = getSelectionPath(); if (path != null && path.getPathCount() > 0) { LibraryNode node = (LibraryNode) path.getLastPathComponent(); - if (node.isLeaf()) { + if (node.isLeaf() && node.isUnique()) { clearSelection(); try { ElementTypeDescription d = node.getDescription(); diff --git a/src/main/resources/lang/lang_de.xml b/src/main/resources/lang/lang_de.xml index 73ce86986..6f50f94cf 100644 --- a/src/main/resources/lang/lang_de.xml +++ b/src/main/resources/lang/lang_de.xml @@ -737,6 +737,7 @@ Die Icons stammen aus dem Tango Desktop Project. Starten des externen Fitters Aktuelle Schaltung Dieser Dateiename ist nicht aus dem aktuellen Projekt importierbar! + Der Dateiname ist nicht eindeutig! Ok diff --git a/src/main/resources/lang/lang_en.xml b/src/main/resources/lang/lang_en.xml index 21754a0a0..888e54a89 100644 --- a/src/main/resources/lang/lang_en.xml +++ b/src/main/resources/lang/lang_en.xml @@ -724,6 +724,7 @@ The icons are taken from the Tango Desktop Project. Execution of external fitter Actual Circuit The selected file name is not importable from the actual project! + The file name is not unique! Ok diff --git a/src/test/java/de/neemann/digital/core/pld/DiodeTest.java b/src/test/java/de/neemann/digital/core/pld/DiodeTest.java index a74c528f4..1b04ae125 100644 --- a/src/test/java/de/neemann/digital/core/pld/DiodeTest.java +++ b/src/test/java/de/neemann/digital/core/pld/DiodeTest.java @@ -14,11 +14,12 @@ import java.io.IOException; public class DiodeTest extends TestCase { /** - * Two antiparallel unidirectional diodes are able to hold each other either in low or in + * Two anti parallel unidirectional diodes are able to hold each other either in low or in * high state, depending on which diode is processed first. - * The current simulation model which is build up on inputs which are modifing the outputs + * The current simulation model which is build up on inputs which are modifying the outputs * is not suited to handle bidirectional passive diodes. - * For the same reason also bidirectional switches are impossible to implement. + * The solution implemented for switches - form a common net if switch is closed - is also + * not able to handle diodes. * * To make this possible the simulation core needs a significant improvement. */